/* Copyright (C) 1989, Digital Equipment Corporation */ /* All rights reserved. */ /* See the file COPYRIGHT for a full description. */ /* Last modified on Wed Jul 11 05:51:42 1990 by muller */ #include #include #include #include #include #define TRUE 1 #define FALSE 0 extern char *tmpnam (); extern char *malloc (); extern char *strtok (); extern char *strrchr (); typedef struct stamps { char *module; char *symbol; char *stamp; struct stamps *next; } STAMPS_STRUCT, *STAMPS; typedef struct modules { char *module; STAMPS stamps; struct modules *next; } MODULES_STRUCT, *MODULES; /*---------- INPUTS ----------*/ char *prog_name; /* the name by with the user calls us */ int verbose = FALSE; /* print why we have to recompile */ int debug = FALSE; /* print strategic info */ char *m3_sourcefile = NULL; /* the name of the source file to process */ char *m3_objfile = NULL; /* the name of the corresponding obj file */ #define MAXPATHCOMPONENTS 500 char *path_components [MAXPATHCOMPONENTS] = { NULL }; /* where to look for imports */ /*---------------OUTPUTS ----------*/ #define OK 0 #define RECOMPILE 1 #define ERROR 2 MODULES known_modules; #define NEW(type) ((type *) malloc (sizeof (type))) #define loop while (1) #if defined (DS3100) #define DEFINED 'N' #else #define DEFINED 'D' #endif #if defined (DS3100) #define UNDEFINED 'V' #else #define UNDEFINED 'U' #endif #define WHATEVER NULL #if defined (DS3100) #define STAMP_HEADER "VS_" #else #define STAMP_HEADER "__VS_" #endif char *duplicate (string) char *string; { int n = strlen (string) + 1; char *c = malloc (n); bcopy (string, c, n); return (c); } STAMPS extract_version_stamps (path, module, defined) char *path; char *module; char defined; { char symbol_list [MAXPATHLEN]; FILE *sym; char command [2*MAXPATHLEN + 11]; int status; char c; int i; char *aux, *stamp, *start; char buff[500]; STAMPS vs; STAMPS stamps = NULL; tmpnam (symbol_list); sprintf (command, "nm -p %s > %s\n", path, symbol_list); if ((status = system (command)) != 0) { fprintf (stderr, "%s: could not read symbols from %s (status = %d)", prog_name, path, status); exit (ERROR); } if (debug) { fprintf (stderr, "%s: reading symbols from %s\n", prog_name, path); } sym = fopen (symbol_list, "r"); loop { i = 0; while (((c = getc (sym)) != '\n') && (c != EOF)) { buff [i++] = c; } if (c == EOF) { break; } buff [i] = '\0'; for (start = buff + i - 1; *start != ' '; start--); start++; if (((defined != NULL) && (*(start-2) != defined)) || (strncmp (start, STAMP_HEADER, strlen (STAMP_HEADER)) != 0)) { continue; } start += strlen (STAMP_HEADER); /* check that we have a stamp at the end */ stamp = aux = strrchr (buff, '_') + 1; while ((('0' <= *aux) && (*aux <= '9')) || (('a' <= *aux) && (*aux <= 'f'))) { aux++; } if (*aux != '\0') { continue; } /* ok, say it is a version stamp */ vs = NEW (STAMPS_STRUCT); vs->stamp = duplicate (stamp); stamp -= 2; *stamp = '\0'; aux = start; while ((*aux != '\0') && ((*aux != '_') || (*(aux+1) != '_'))) { aux++; } vs->symbol = duplicate (aux + 2); *aux = '\0'; vs->module = duplicate (start); vs->next = stamps; stamps = vs; if (debug) { fprintf (stderr, " %s.%s: %s\n", vs->module, vs->symbol, vs->stamp); }} fclose (sym); unlink (symbol_list); return (stamps); } STAMPS stamps_for (module_name) char *module_name; { MODULES m = known_modules; while ((m != NULL) && (strcmp (m->module, module_name) != 0)) { m = m->next; } if (m == NULL) { char **p; char path [MAXPATHLEN + 1]; for (p = path_components; *p != NULL; p++) { sprintf (path, "%s/%s.io", *p, module_name); if (access (path, R_OK) == 0) { m = NEW (MODULES_STRUCT); m->module = module_name; m->stamps = extract_version_stamps (path, module_name, WHATEVER); m->next = known_modules; known_modules = m; break; }}} if (m == NULL) { fprintf (stderr, "%s: could not find %s.io\n", prog_name, module_name); return (NULL); } else { return (m->stamps); } } void parse_arguments (argc, argv) int argc; char **argv; { prog_name = strrchr (argv[0], '/'); if (prog_name == NULL) { prog_name = argv[0]; } else { prog_name++; } path_components [0] = "."; path_components [1] = NULL; while ((--argc > 0) && ((++argv)[0][0] == '-')) { switch (argv[0][1]) { case 'B': { char **p = path_components; *p = strtok (argv[0]+2, ":"); while ((*p++ != NULL) && (p < path_components + sizeof (path_components))) { *p = strtok (NULL, ":"); } break; } default: { char * s; for (s = argv[0]+1; *s != '\0'; s++) { switch (*s) { case 'v': { verbose = TRUE; break; } case 'd': { debug = TRUE; verbose = TRUE; break; } default: { fprintf (stderr, "%s: illegal option %c\n", prog_name, *s); argc = -1; break; }}}}}} if ((argc < 1) || (argc > 2)) { printf ("usage: %s [-Bpath] [-v] [-d] m3_sourcefile [m3_objfile]\n", prog_name); exit (ERROR); } m3_sourcefile = *argv++; argc--; if (argc > 0) { m3_objfile = *argv++; argc--; } } main (argc, argv) int argc; char **argv; { STAMPS ustamps, dstamps; parse_arguments (argc, argv); if (m3_objfile == NULL) { if (verbose) { fprintf (stderr, "%s: recompile %s because no obj is has not been specified\n", prog_name, m3_sourcefile); } exit (RECOMPILE); } /* Compare the dates of the files */ { struct stat buf; int source_time; if (stat (m3_sourcefile, &buf) != 0) { char buff [500]; sprintf (buff, "%s: %s", prog_name, m3_sourcefile); perror (buff); exit (ERROR); } source_time = buf.st_mtime; if (stat (m3_objfile, &buf) != 0) { char buff[500]; sprintf (buff, "%s: %s", prog_name, m3_objfile); perror (buff); exit (ERROR); } if (buf.st_mtime < source_time) { if (verbose) { fprintf (stderr, "%s: recompile %s because %s is older\n", prog_name, m3_sourcefile, m3_objfile); } exit (RECOMPILE); }} /* Get the timestamps of the object */ ustamps = extract_version_stamps (m3_objfile, NULL, UNDEFINED); while (ustamps != NULL) { if (debug) { fprintf (stderr, "Looking for %s.%s: %s\n", ustamps->module, ustamps->symbol, ustamps->stamp); } dstamps = stamps_for (ustamps->module); while ((dstamps != NULL) && ((strcmp (dstamps->symbol, ustamps->symbol) != 0) || (strcmp (dstamps->module, ustamps->module) != 0))) { dstamps = dstamps->next; } if (dstamps == NULL) { fprintf (stderr, "%s: could not find the definition for stamp %s.%s\n", prog_name, ustamps->module, ustamps->symbol); } else if (strcmp (dstamps->stamp, ustamps->stamp) != 0) { if (verbose) { fprintf (stderr, "%s: timestamps for %s.%s do not agree (%s and %s)\n", prog_name, ustamps->module, ustamps->symbol, dstamps->stamp, ustamps->stamp); } exit (RECOMPILE); } ustamps = ustamps->next; } exit (OK); }