home *** CD-ROM | disk | FTP | other *** search
- /* pmake -- bring a system of files up to date */
- /* Portions copyright 1984 Michael M Rubenstein */
- /* Portions copyright 1984 John M Sellens */
-
- /* based on pc-make by John M Sellens. Significant portions have been */
- /* copied almost verbatim from pc-make. Mr. Sellens has requested the */
- /* following notice be included in all copies of his program: */
-
- /*
- Written by John M Sellens, April, 1984
-
- Until August, 1984:
- jmsellens@watrose.UUCP
-
- 107 - 180 Brybeck Cres.
- Kitchener, Ontario
- N2M 5G4
-
- After August, 1984:
- c/o 1135 Lansdowne Ave. SW
- Calgary, Alberta
- T2S 1A4
-
- (c) Copyright 1984 John M Sellens
- Permission is granted to use, distribute and/or modify this code unless
- done for direct commercial profit. If you find these routines useful,
- modest contributions (monetary or otherwise) will be gratefully accepted.
- Author's name, address and this notice must be included in any copies.
-
- */
-
- #define PGMNAME "pmake"
- #include <stdio.h>
- #include "pmake.h"
-
- int modbit = MODBIT;
- unsigned submax = SUBMAX;
- char submit[9] = SUBMIT;
- struct howrec { char *howcom;
- struct howrec *nexthow;
- };
-
- struct deprec { char *name;
- char *def; /* really struct defnrec * */
- struct deprec *nextdep;
- };
-
- struct defnrec { char *name;
- int uptodate;
- int modified;
- struct deprec *dependson;
- struct howrec *howto;
- struct defnrec *nextdefn;
- };
-
- struct dorec { char *name;
- struct dorec *nextdo;
- };
-
- struct setrec { char *name;
- struct setrec *nextset;
- };
-
- struct defnrec *defnlist = NULL;
- struct dorec *dolist = NULL;
- struct defnrec *initrec = NULL,
- *finrec = NULL;
- struct setrec *setlist = NULL;
-
- int subsize;
-
- int stopOnErr = TRUE;
- int madesomething;
- int knowhow;
- int noinit = FALSE;
- FILE *outfile;
- int outnum = 0;
-
- char *vars;
- char *endvars;
-
- #ifdef DEBUG
- int debug = 0;
- #endif
-
- int xargc;
- char **xargv;
-
- char *findvar();
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- static int didsomething = FALSE;
- char vars_[MAXLVAR + 1];
-
- vars = endvars = vars_;
- *vars = '\0';
- xargc = argc;
- xargv = argv;
- init();
-
- /* now fall down the dolist and do them all */
- while (dolist != NULL)
- {
- madesomething = FALSE;
- make(dolist->name);
- didsomething |= madesomething;
- if (!madesomething)
- {
- if (knowhow)
- fprintf(stderr,"pmake: '%s' is up to date\n",dolist->name);
- else
- {
- fprintf(stderr,"pmake: Don't know how to make '%s'\n", dolist->name);
- if (stopOnErr)
- exit(1);
- }
- }
- dolist = dolist->nextdo;
- }
- if (didsomething || setlist != NULL)
- {
- setdone();
- if (finrec != NULL && didsomething)
- {
- finrec->uptodate = FALSE;
- make(".FIN");
- }
- }
- else
- {
- setflg(outfile, "d");
- fclose(outfile);
- exit(1);
- }
- fclose(outfile);
- }
-
-
- init()
- {
- static int usedefault = TRUE;
- static int argind = 0;
- static int i;
- static int done = FALSE;
-
- extern int optind;
- extern char *optarg;
-
- #ifdef DEBUG
- #define OPTFLAGS "-DF:IN:O:V:"
- #else
- #define OPTFLAGS "-F:IN:O:V:"
- #endif
-
- do
- {
- switch (getopt(xargc, xargv, OPTFLAGS))
- {
- #ifdef DEBUG
- case 'D': /* debug */
- ++debug;
- break;
- #endif
-
- case 'F': /* arg following is a makefile */
- if (*optarg == '\0')
- error("'-f' requires filename");
- readmakefile(optarg);
- usedefault = FALSE;
- break;
-
- case 'I': /* ignore errors on execution */
- stopOnErr = FALSE;
- break;
-
- case 'N': if ((submax = atoi(optarg)) == 0)
- submax = 0xffff;
- break;
-
- case 'V': addvar(optarg);
- break;
-
- case '?': break;
-
- case EOF: if (optind < xargc)
- add_do(xargv[optind++]);
- else
- done = TRUE;
- break;
-
- default: error("dryrot -- invalid option parse");
- }
- } while (!done);
-
- if (dolist == NULL)
- add_do(DEFDO);
- if (usedefault)
- readmakefile(DEFAULT);
- opnout();
- }
-
- opnout()
- {
- char outname[13];
-
-
- if (outnum)
- {
- fprintf(outfile, "%s MAKEF%03d\n", submit, outnum);
- fclose(outfile);
- }
-
- sprintf(outname, "MAKEF%03d.SUB", outnum++);
-
- if ((outfile = fopen(outname, "w")) == NULL)
- error("Cannot create output file");
-
- subsize = 0;
-
- #ifdef DEBUG
- if (debug)
- setflg(outfile, "e");
- #endif
-
- delfil(outname);
- }
-
- make(s)
- char *s;
- {
- struct defnrec *defnp;
- struct deprec *depp;
- struct howrec *howp;
- int latest;
-
- #ifdef DEBUG
- if (debug > 1)
- fprintf(stderr, "***Making %s\n", s);
- #endif
-
- /* look for the definition */
- for (defnp = defnlist;
- defnp != NULL && strcmp(defnp->name, s);
- defnp = defnp->nextdefn)
- ;
-
- if (defnp == NULL) /* don't know how to make it */
- {
- knowhow = FALSE;
- latest = getmod(s);
- if (latest == 0) /* doesn't exist */
- { /* but don't know how to make */
- fprintf(stderr,"pmake: Can't make '%s'\n",s);
- if (stopOnErr)
- exit(1);
- return NOTTHERE;
- }
- else /* exists - assume it's up to date */
- {
- if (latest == CHANGED)
- {
- addset(s);
- return THISRUN;
- }
- return latest; /* since we don't know */
- }
- }
-
- if (defnp->uptodate)
- return defnp->modified;
-
- /* now make sure everything that it depends on is up to date */
- latest = 0;
- depp = defnp->dependson;
- while (depp != NULL)
- {
- latest = max(make(depp->name),latest);
- depp = depp->nextdep;
- }
-
- knowhow = TRUE; /* has dependencies -- we know how */
-
- /* if necessary, execute all of the commands to make it */
- /* if (out of date) || (depends on nothing) */
- if (latest > defnp->modified || defnp->dependson == NULL)
- {
- /* make those suckers */
- if ((defnp->howto != NULL || defnp->modified == CHANGED)
- && initrec != NULL)
- {
- initrec->uptodate = FALSE;
- initrec = NULL;
- make(".INIT");
- }
- for (howp = defnp->howto; howp != NULL; howp = howp->nexthow)
- {
- if (subsize >= submax)
- opnout();
- fputs(howp->howcom, outfile);
- putc('\n', outfile);
- ++subsize;
- }
-
- if (*s == '.')
- defnp->modified = (defnp->dependson == NULL) ? THISRUN : latest;
- else
- {
- defnp->modified = THISRUN;
- addset(s);
- }
- defnp->uptodate = TRUE;
- if (defnp->howto != NULL) /* we had instructions */
- madesomething = TRUE;
- }
-
- if (defnp->modified == CHANGED)
- {
- addset(s);
- defnp->modified = THISRUN;
- defnp->uptodate = TRUE;
- }
-
- return defnp->modified;
- }
-
-
- add_do(s)
- char *s;
- {
- struct dorec *ptr1, *ptr2;
- char *getmem();
-
- #ifdef DEBUG
- if (debug > 1)
- fprintf(stderr, "***Adding %s to do-list\n", s);
- #endif
-
- ptr1 = getmem(sizeof(struct dorec));
-
- ptr1->name = s; /* okay since only called with */
- ptr1->nextdo = NULL; /* an argv or constant */
-
- upcase(ptr1->name);
-
- /* now go down the dolist */
- if (dolist == NULL)
- dolist = ptr1;
- else
- {
- ptr2 = dolist;
- while (ptr2->nextdo != NULL)
- ptr2 = ptr2->nextdo;
- ptr2->nextdo = ptr1;
- }
- }
-
- addset(s)
- char *s;
- {
- struct setrec *setp, *setp2;
-
- char *getmem();
-
- if (setlist == NULL)
- setlist = setp = getmem(sizeof(struct setrec));
- else
- {
- for (setp = setlist; setp != NULL; setp = setp->nextset)
- {
- if (strcmp(s, setp->name) == 0)
- return;
- setp2 = setp;
- }
- setp2->nextset = setp = getmem(sizeof(struct setrec));
- }
- setp->name = s;
- setp->nextset = NULL;
- }
-
-
-
- readmakefile(s)
- char *s;
- {
- static FILE *fil;
- static int doneline, pos, i, j, c;
- char inline[INMAX + 1], info[INMAX + 1];
- char *getmem();
- static struct defnrec *defnp, *defnp2;
- static struct deprec *depp, *depp2;
- static struct howrec *howp, *howp2;
-
- if ( (fil = fopen(s,"r")) == NULL)
- {
- fprintf(stderr,"pmake: Couldn't open '%s'\n",s);
- return;
- }
-
- #ifdef DEBUG
- if (debug > 1)
- fprintf(stderr, "***Reading make file %s\n", s);
- #endif
-
- while (fgets(inline, INMAX, fil) != NULL)
- {
- if (inline[0] == COMMENT)
- continue;
- inline[strlen(inline)-1] = '\0'; /* strip trailing newline */
- if (inline[0] == '\0') /* ignore blank lines */
- continue;
-
- if (inline[0] == VARCHAR)
- {
- addvar(inline + 1);
- continue;
- }
-
- xlate(inline);
-
- if (inline[0] != '\t') /* start of a new definition */
- {
- upcase(inline);
- /* get what we're defining into info */
- for (pos = 0; isspace(inline[pos]); ++pos)
- ;
- i = 0;
- while (!isspace(inline[pos]) && inline[pos]!='\0')
- info[i++] = inline[pos++];
- info[i] = '\0';
-
- /* get a new struct */
- defnp = getmem(sizeof(struct defnrec));
- /* add it to the end of defnlist */
- if (defnlist == NULL)
- defnlist = defnp;
- else
- {
- defnp2 = defnlist;
- while (defnp2->nextdefn != NULL)
- defnp2 = defnp2->nextdefn;
- defnp2->nextdefn = defnp;
- }
- /* initialize it */
- defnp->name = getmem(strlen(info)+1);
- strcpy(defnp->name,info);
- if (!noinit && strcmp(info, ".INIT") == 0)
- {
- initrec = defnp;
- defnp->uptodate = TRUE;
- defnp->modified = THISRUN;
- }
- else
- if (strcmp(info, ".FIN") == 0)
- {
- finrec = defnp;
- defnp->uptodate = TRUE;
- defnp->modified = THISRUN;
- }
- else
- {
- defnp->uptodate = FALSE; /* actually unknown */
- defnp->modified = getmod(defnp->name);
- }
- defnp->dependson = NULL;
- defnp->howto = NULL;
- defnp->nextdefn = NULL;
-
- /* now go through all of its dependecies */
- /* first move past the first name */
- /* now loop through those suckers */
- doneline = FALSE;
- while (!doneline)
- {
- while (isspace(inline[pos]))
- pos++;
- if (inline[pos] == '\0')
- {
- doneline = TRUE;
- continue;
- }
- for(i = 0; !isspace(inline[pos]) && inline[pos]!='\0';)
- info[i++] = inline[pos++];
- info[i] = '\0';
- /* get a new struct */
- depp = getmem(sizeof(struct deprec));
- /* add it to the end of deplist */
- if (defnp->dependson == NULL)
- defnp->dependson = depp;
- else
- {
- depp2 = defnp->dependson;
- while (depp2->nextdep != NULL)
- depp2 = depp2->nextdep;
- depp2->nextdep = depp;
- }
- depp->name = getmem(strlen(info)+1);
- strcpy(depp->name,info);
- depp->nextdep = NULL;
- }
- }
- else
- { /* a how to line */
- if (defnp == NULL)
- {
- fprintf(stderr,"pmake: Howto line without a definition:\n");
- fprintf(stderr,"pmake: '%s'\n",inline);
- }
- /* remove leading & trailing spaces */
- for (pos=0;isspace(inline[pos]); pos++);
- ;
- for (i=strlen(inline); i>pos && isspace(inline[i-1]); --i)
- ;
- /* if there is something there, allocate mem and copy */
- if (i > pos)
- {
- /* get a new struct */
- howp = getmem(sizeof(struct howrec));
- /* add it to the end of howlist */
- if (defnp->howto == NULL)
- defnp->howto = howp;
- else
- {
- howp2 = defnp->howto;
- while (howp2->nexthow != NULL)
- howp2 = howp2->nexthow;
- howp2->nexthow = howp;
- }
- /* copy command filename */
- howp->howcom = getmem(i-pos+1);
- for(j=0; pos < i;)
- howp->howcom[j++] = inline[pos++];
- howp->howcom[j] = '\0';
- howp->nexthow = NULL;
- }
- }
- }
- }
-
-
- setdone()
- {
- static struct setrec *setp;
- static FILE *setfile;
-
- if ((setfile = fopen(SETFILE, "w")) == NULL)
- error("cannot open set file");
-
- for (setp = setlist; setp != NULL; setp = setp->nextset)
- {
- fputs(setp->name, setfile);
- putc('\n', setfile);
- }
- fclose(setfile);
- }
-
- addvar(vdef)
- char *vdef;
- {
- char name[VNAMELEN + 1];
- static int i;
- static char *s;
-
- for (s = vdef; isspace(*s); ++s)
- ;
- i = 0;
- for (;issymch(*s); ++s)
- if (i < VNAMELEN)
- name[i++] = toupper(*s);
- name[i] = '\0';
- while (isspace(*s))
- ++s;
- if (!name[0])
- {
- fprintf(stderr, "pmake: Illegal variable definition: %s\n", vdef);
- exit(1);
- }
- if (findvar(name) != NULL)
- return;
- for (i = 0; name[i];)
- addchar(name[i++]);
- addchar('\0');
- s = (*s == '=') ? (s + 1) : name;
- while (*s)
- addchar(*(s++));
- addchar('\0');
- *endvars = '\0';
- }
-
- addchar(c)
- int c;
- {
- if (endvars - vars >= MAXLVAR)
- error("Variable space exhausted");
- *(endvars++) = c;
- }
-
- char *findvar(s)
- register char *s;
- {
- static char *p;
-
- if (!*s)
- return NULL;
- for (p = vars; *p; p += strlen(p) + 1, p += strlen(p) + 1)
- if (strcmp(s, p) == 0)
- return p + strlen(p) + 1;
- return NULL;
- }
-
- xlate(line)
- register char *line;
- {
- char wkline[INMAX + 1];
- static int i, j;
- static char *p, *q;
- char name[VNAMELEN + 1];
- static int changed;
-
- #ifdef DEBUG
- if (debug >1)
- fprintf(stderr, "***TRANSLATING: %s\n", line);
- #endif
-
- do
- {
- changed = FALSE;
- strcpy(wkline, line);
- for (p = wkline, i = 0; *p;)
- {
- if (*p != VARCHAR || *++p == VARCHAR)
- {
- if (i >= INMAX)
- {
- fprintf("pmake: Line too long:\n%s\n", stderr);
- exit(1);
- }
- line[i++] = *(p++);
- continue;
- }
-
- j = 0;
- changed = TRUE;
- for (; issymch(*p); ++p)
- {
- if (j < VNAMELEN)
- name[j++] = toupper(*p);
- }
- name[j] = '\0';
- if (*p == '%')
- ++p;
- if ((q = findvar(name)) == NULL)
- continue;
- if (i + (j = strlen(q)) > INMAX)
- {
- fprintf("pmake: Line too long:\n%s\n", stderr);
- exit(1);
- }
- strcpy(&line[i], q);
- i += j;
- }
- line[i] = '\0';
- } while (changed);
-
- #ifdef DEBUG
- if (debug >1)
- fprintf(stderr, "***NEW VALUE: %s\n", line);
- #endif
- }
-
- issymch(c)
- register int c;
- {
- return isalpha(c) || isdigit(c) || c == '-' || c == '_' || c == '.';
- }
- UG
- if (debug >1)
- fprintf(stderr, "***TRANSLATING: %s\n", line);
- #endif
-
- do
- {