/* * Update files, given dependency list. * Based on a programme originally written * by Tom Duff (NYIT). * More closely based on a version of the * above tarted up by Charles Forsyth. */ #include #define NFB 32 #define NANTI 20 typedef long time_t; struct dep { struct dep *d_fp; /* Forward pointer */ struct file *d_cons; /* Consequent */ char *d_work; /* Command lines */ int d_nanti; /* Number of anticedents */ struct file *d_anti[]; /* Antidecents */ }; struct file { struct file *f_fp; /* Forward pointer */ char *f_name; /* Name */ char f_level; /* Level */ char f_mark; /* Loop detect flag */ time_t f_time; /* Modification time */ }; struct file *file; struct dep *dep; int vflag; int line; int maxlevel; char *mfn; FILE *mfp; main(argc, argv) char *argv[]; { register char *p; register c, i; mfn = "makefile"; for (i=1; i= NANTI) err("Too many anticedents"); anti[na++] = fp; } if (na == 0) err("No anticedents"); dp = newspace(sizeof(*dp) + na*sizeof(dp->d_anti[0])); dp->d_cons = cfp; dp->d_nanti = na; while (na--) dp->d_anti[na] = anti[na]; dp->d_work = getwork(); } } struct file * getfile(f) { register struct file *fp; register char *cp; register c; char fb[NFB]; while ((c = getc(ifp)) == ' ' || c == '\t') { if (c == '\n') { ++line; if (f == 0) break; } } if (c == EOF || c == '\n') return (NULL); cp = fb; do { if (cp < &fb[NFB-1]) { if (c>='A' && c<='Z') c += 'a'-'A'; *cp++ = c; } } while ((c = getc(ifp)) != ' ' && c!='\t' && c!='\n' && c!=EOF); *cp = 0; ungetc(c, mfp); fp = file; while (fp != NULL) { if (strcmp(fb, fp->f_name) == 0) return (fp); fp = fp->f_fp; } fp = newspace(sizeof(*fp)); fp->f_fp = file; file = fp; fp->f_name = strsave(fb); fp->f_mark = 0; fp->f_level = -1; settime(fp); return (fp); } char * getwork() { cp = work; while ((c = getc(mfp)) == '\t') { while ((c = getc(ifp)) != EOF && c != '\n') { if (cp >= &work[NWORK]) err("Too many commands"); *cp++ = c; } *cp++ = '\n'; } ungetc(c, mfp); if (cp == work) return (NULL); *cp = 0; return (strsave(work)); } dowork() { register struct file *fp; register struct dep *dp; register i; setlevel(); for (i=1; i<=maxlevel; ++i) { dp = dep; while (dp != NULL) { if (dp->d_cons->f_level==i && youngest(dp->d_group) >= dp->d_cons->f_time) domcr(dp); dp = dp->d_fp; } dp = dep; while (dp != NULL) { if (dp->d_cons->f_level == n) { t = youngest(dp); if (t < dp->d_cons->f_time) continue; if (dp->d_work != NULL) setime(dp->d_cons); else dp->d_cons->f_time = t; } dp = dp->d_fp; } } } domcr(dp) register struct dep *dp; { if (dp->d_work == NULL) return; if (vflag) printf("%s", dp->d_work); /* ... */ } time_t youngest(dp) register struct dep *dp; { register struct file *fp; register na; time_t t; t = 0; na = dp->d_nanti; while (na--) { fp = dp->d_anti[na]; if (fp->f_time > t) t = fp->f_time; } return (t); } setlevel() { register struct file *fp; fp = file; while (fp != NULL) { follow(fp, 0); fp = fp->f_fp; } } follow(fp, level) register struct file *fp; { register struct dep *dp; register struct file **ap; int na; if (fp->f_mark) { fprintf(stderr, "Circularity on %s!\n", fp->f_name); exit(1); } if (fp->f_level < level) { if (level > maxlevel) maxlevel = level; fp->f_level = level; fp->f_mark = 1; dp = dep; while (dp != NULL) { na = dp->d_nanti; ap = dp->d_anti; while (na--) if (*ap++ == fp) { follow(dp->d_cons, level+1); break; } dp = dp->d_fp; } fp->f_mark = 0; } } err(s) char *s; { if (line != 0) fprintf(stderr, "%d: ", line); fprintf(stderr, "%s\n", s); exit(1); } char * newspace(n) { register char *p; p = alloc(n); if (p == (char *)-1) err("Out of space"); return (p); } char * strsave(s) char *s; { register char *p; p = newspace(strlen(s) + sizeof(char)); strcpy(p, s); return (p); } usage() { fprintf(stderr, "Usage: make [-v] [file]\n"); exit(1); }