From 99822b433c23aabc26d69a3f6c52477d0699a8ae Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 25 Oct 2017 20:04:57 +0100 Subject: [PATCH] make: make Add the older MwC make as it fits a small machine nicely --- Applications/MWC/cmd/Makefile.68000 | 2 +- Applications/MWC/cmd/Makefile.6809 | 2 +- Applications/MWC/cmd/Makefile.z80 | 2 +- Applications/MWC/cmd/make.c | 1215 +++++++++++++++++++++++++++ Applications/MWC/cmd/make.h | 115 +++ Applications/MWC/cmd/makeactions | 22 + Applications/MWC/cmd/makemacros | 17 + 7 files changed, 1372 insertions(+), 3 deletions(-) create mode 100644 Applications/MWC/cmd/make.c create mode 100644 Applications/MWC/cmd/make.h create mode 100644 Applications/MWC/cmd/makeactions create mode 100644 Applications/MWC/cmd/makemacros diff --git a/Applications/MWC/cmd/Makefile.68000 b/Applications/MWC/cmd/Makefile.68000 index 68aef931..bfb25b08 100644 --- a/Applications/MWC/cmd/Makefile.68000 +++ b/Applications/MWC/cmd/Makefile.68000 @@ -14,7 +14,7 @@ CRT0NS = ../../../Library/libs/crt0nostdio_68000.o ELF2FUZIX = elf2flt .SUFFIXES: .c .o -SRCS = ac.c almanac.c at.c calendar.c col.c cron.c deroff.c expr.c find.c m4.c moo.c pr.c tar.c test.c ttt.c units.c +SRCS = ac.c almanac.c at.c calendar.c col.c cron.c deroff.c expr.c find.c m4.c make.c moo.c pr.c tar.c test.c ttt.c units.c OBJS = $(SRCS:.c=.o) diff --git a/Applications/MWC/cmd/Makefile.6809 b/Applications/MWC/cmd/Makefile.6809 index a7b8c0f8..eebb127f 100644 --- a/Applications/MWC/cmd/Makefile.6809 +++ b/Applications/MWC/cmd/Makefile.6809 @@ -14,7 +14,7 @@ CRT0 = ../../../Library/libs/crt0_6809.o .SUFFIXES: .c .o -SRCS = ac.c almanac.c at.c calendar.c col.c cron.c deroff.c expr.c find.c m4.c moo.c pr.c tar.c test.c ttt.c units.c +SRCS = ac.c almanac.c at.c calendar.c col.c cron.c deroff.c expr.c find.c m4.c make.c moo.c pr.c tar.c test.c ttt.c units.c OBJS = $(SRCS:.c=.o) diff --git a/Applications/MWC/cmd/Makefile.z80 b/Applications/MWC/cmd/Makefile.z80 index ed0965d0..6e55d736 100644 --- a/Applications/MWC/cmd/Makefile.z80 +++ b/Applications/MWC/cmd/Makefile.z80 @@ -13,7 +13,7 @@ PROGLOAD=`(cat ../../Kernel/platform/config.h; echo PROGLOAD) | cpp -E | tail -n SRCSNS = expr.c test.c -SRCS = ac.c almanac.c at.c col.c cron.c deroff.c find.c moo.c pr.c tar.c ttt.c units.c +SRCS = ac.c almanac.c at.c col.c cron.c deroff.c find.c make.c moo.c pr.c tar.c ttt.c units.c SRCSBAD = calendar.c m4.c diff --git a/Applications/MWC/cmd/make.c b/Applications/MWC/cmd/make.c new file mode 100644 index 00000000..21b6b0bc --- /dev/null +++ b/Applications/MWC/cmd/make.c @@ -0,0 +1,1215 @@ +/* + * make -- maintain program groups + * td 80.09.17 + * things done: + * 20-Oct-82 Made nextc properly translate "\\\n[ ]*" to ' '. + * 15-Jan-85 Made portable enough for z-8000, readable enough for + * human beings. + * 06-Nov-85 Added free(t) to make() to free used space. + * 07-Nov-85 Modified docmd() to call varexp() only if 'cmd' + * actually contains macros, for efficiency. + * 24-Feb-86 Minor fixes by rec to many things. Deferred + * macro expansion in actions until needed, deferred + * getmdate() until needed, added canonicalization in + * archive searches, allowed ${NAME} in actions for + * shell to expand, put macro definitions in malloc, + * entered environ into macros. + * 17-Oct-86 Very minor MS-DOS changes by steve: add _cmdname[], + * conditionalize archive code as #if COHERENT || GEMDOS. + * 8-Dec-86 Rec makes inpath() search current directory first, + * and allows : in dependency list under MSDOS && GEMDOS. + * 8-Feb-91 steve: fix comment handling, allow "\#", allow ${VAR}. + * Add docmd0() to make $< and $* work in Makefiles. + * 12-Feb-91 steve: add $SRCPATH source path searching. + * 1-Nov-91 steve: fix bug in nextc() to handle "\n\t\n" correctly + * 29-Sep-92 michael: fix problem with defining a rule that also + * exists in the ACTIONFILE. + * 08-Oct-92 michael: fix problem with making targets with no + * specified actions (empty productions). + */ + +#include "make.h" + +char usage[] = "Usage: make [-deinpqrst] [-f file] [macro=value] [target]"; +char nospace[] = "out of space"; +char badmac[] = "bad macro name"; +char incomp[] = "incomplete line at end of file"; + +/* Command line flags. */ +int iflag; /* ignore command errors */ +int sflag; /* don't print command lines */ +int rflag; /* don't read built-in rules */ +int nflag; /* don't execute commands */ +int tflag; /* touch files rather than run commands */ +int qflag; /* zero exit status if file up to date */ +int pflag; /* print macro defns, target descriptions */ +int dflag; /* debug mode -- verbose printout */ +int eflag; /* make environ macros protected */ + +/* Globals. */ +unsigned char backup[NBACKUP]; +int defining; /* nonzero => do not expand macros */ +int instring; /* Are we in the middle of a string? */ +SYM *deflt; +char *deftarget; +FILE *fd; +int lastc; +int lineno; +MACRO *macro; +char macroname[NMACRONAME+1]; +char *mvarval[4]; /* list of macro variable values */ +int nbackup; +time_t now; +char *srcpath; +struct stat statbuf; +SYM *suffixes; +SYM *sym; +char tokbuf[NTOKBUF]; +char *token; +int toklen; +char *tokp; +int inactionfile = 0; + +/* cry and die */ +/* VARARGS */ +void die(const char *s, ...) +{ + va_list args; + va_start(args, s); + fflush(stdout); + verrx(ERROR, "make: ", args); + exit(ERROR); +} + +/* print lineno, cry and die */ +/* VARARGS */ +void doerr(const char *s, ...) +{ + va_list args; + va_start(args, s); + fprintf(stderr, "make: %d: ", lineno); + vfprintf(stderr, s, args); + exit(ERROR); +} + +/* Malloc nbytes and abort on failure */ +char *mmalloc(size_t n) +{ + char *p; + if (p = malloc(n)) + return p; + doerr(nospace); +} + +/* Whine about usage and then quit */ +void Usage(void) +{ + fprintf(stderr, "%s\n", usage); + exit(1); +} + +/* read characters from backup (where macros have been expanded) or from + * whatever the open file of the moment is. keep track of line #s. + */ +int readc(void) +{ + if (nbackup!=0) + return(backup[--nbackup]); + if (lastc=='\n') + lineno++; + lastc=getc(fd); + return(lastc); +} + +/* put c into backup[] */ +void putback(int c) +{ + if (c==EOF) + return; + if (nbackup == NBACKUP) + doerr("macro definition too long"); + backup[nbackup++]=c; +} + +/* put s into backup */ +void unreads(register char *s) +{ + register char *t; + + t = &s[strlen(s)]; + while (t > s) + putback(*--t); +} + +/* return a pointer to the macro definition assigned to macro name s. + * return NULL if the macro has not been defined. + */ +char *mexists(register char *s) +{ + register MACRO *i; + + for (i = macro; i != NULL; i=i->next) + if (Streq(s, i->name)) + return (i->value); + + return (NULL); +} + +/* install macro with name name and value value in macro[]. Overwrite an + * existing value if it is not protected. + */ +void define(char *name, char *value, int protected) +{ + register MACRO *i; + + if (dflag) + printf("define %s = %s\n", name, value); + for (i = macro; i != NULL; i=i->next) + if (Streq(name, i->name)) { + if (!i->protected) { + free(i->value); + i->value = value; + i->protected = protected; + } else if (dflag) + printf("... definition suppressed\n"); + return; + } + i = (MACRO *)mmalloc(sizeof(*i)); + i->name = name; + i->value = value; + i->protected = protected; + i->next = macro; + macro = i; +} + +/* Accept single letter user defined macros */ +int ismacro(int c) +{ + return ((c>='0'&&c<='9') + || (c>='a'&&c<='z') + || (c>='A'&&c<='Z')); +} + +/* + * Return the next character from the input file. + * Eat comments. + * Return EOS for newline not followed by an action. + * Return '\n' for newline followed by an action. + * If not in a macro definition or action specification, + * then expand macro in backup or complain about the name. + */ +int nextc(void) +{ + register char *s; + register int c, endc; + +Again: + if ((c = readc()) == '\\') { + c = readc(); + if (c == '\n') { /* escaped newline */ + while ((c=readc())==' ' || c=='\t') + ; /* eat following whitespace */ + putback(c); + return(' '); + } else if (c == '#') + return c; /* "\#" means literal '#' */ + putback(c); + return '\\'; + } + if ((c=='#') && !instring) { + do + c = readc(); + while (c != '\n' && c != EOF); + } + if ((c=='"') || (c=='\'')) + { + instring = !instring; + return c; + } + if (c == '\n') { + instring = 0; +Again2: + if ((c = readc()) != ' ' && c != '\t') { + putback(c); + if (c == '#') + goto Again; /* "\n# comment" */ + return EOS; /* no action follows */ + } + do + c = readc(); + while (c == ' ' || c == '\t'); /* skip whitespace */ + if (c == '\n') + goto Again2; /* "\n\t\n" */ + putback(c); + if (c == '#') + goto Again; /* "\n\t# comment" */ + return '\n'; /* action follows */ + } + if (!defining && c=='$'){ + c=readc(); + if (c == '(' || c == '{') { + endc = (c == '(') ? ')' : '}'; + s = macroname; + while (' ' < (c = readc()) && c < 0177 && c != endc) + if (s != ¯oname[NMACRONAME]) + *s++=c; + if (c != endc) + doerr(badmac); + *s++ = '\0'; + } else if (ismacro(c)) { + macroname[0]=c; + macroname[1]='\0'; + } else + doerr(badmac); + if ((s=mexists(macroname))!=NULL) + unreads(s); + goto Again; + } + + return(c); +} + +/* Get a block of l0+l1 bytes copy s0 and s1 into it, and return a pointer to + * the beginning of the block. + */ +char *extend(char *s0, int l0, char *s1, int l1) +{ + register char *t; + + if (s0 == NULL) + t = mmalloc(l1); + else { + if ((t = realloc(s0, l0 + l1)) == NULL) + doerr(nospace); + } + strncpy(t+l0, s1, l1); + return(t); +} + +/* Return 1 if c is EOS, EOF, or one of the characters in s */ +int delim(char c, char *s) +{ + return (c == EOS || c == EOF || index(s, c) != NULL); +} + +/* Prepare to copy a new token string into the token buffer; if the old value + * in token wasn't saved, tough matzohs. + */ +void starttoken(void) +{ + token=NULL; + tokp=tokbuf; + toklen=0; +} + +/* Put c in the token buffer; if the buffer is full, copy its contents into + * token and start agin at the beginning of the buffer. + */ +void addtoken(int c) +{ + if (tokp==&tokbuf[NTOKBUF]){ + token=extend(token, toklen-NTOKBUF, tokbuf, NTOKBUF); + tokp=tokbuf; + } + *tokp++=c; + toklen++; +} + +/* mark the end of the token in the buffer and save it in token. */ +void endtoken(void) +{ + addtoken('\0'); + token=extend(token, toklen-(tokp-tokbuf), tokbuf, tokp-tokbuf); +} + +/* Install value at the end of the token list which begins with next; return + * a pointer to the beginning of the list, which is the one just installed if + * next was NULL. + */ +TOKEN *listtoken(char *value, TOKEN *next) +{ + register TOKEN *p; + register TOKEN *t; + + t=(TOKEN *)mmalloc(sizeof *t); /*Necessaire ou le contraire?*/ + t->value=value; + t->next=NULL; + if (next==NULL) + return(t); + for(p=next;p->next!=NULL;p=p->next); + p->next=t; + return(next); +} + +/* Free the overhead of a token list */ +TOKEN *freetoken(register TOKEN *t) +{ + register TOKEN *tp; + while (t != NULL) { + tp = t->next; + free(t); + t = tp; + } + return t; +} + +/* Read macros, dependencies, and actions from the file with name file, or + * from whatever file is already open. The first string of tokens is saved + * in a list pointed to by tp; if it was a macro, the definition goes in + * token, and we install it in macro[]; if tp points to a string of targets, + * its depedencies go in a list pointed to by dp, and the action to recreate + * it in token, and the whole shmear is installed. + */ +void input(const char *file) +{ + TOKEN *tp = NULL, *dp = NULL; + register int c; + char *action; + int twocolons; + + if (file!=NULL && (fd=fopen(file, "r"))==NULL) + die("cannot open %s", file); + lineno=1; + lastc=EOF; + for(;;){ + c=nextc(); + for(;;){ + while(c==' ' || c=='\t') + c=nextc(); + if (delim(c, "=:;\n")) + break; + starttoken(); + while(!delim(c, " \t\n=:;")){ + addtoken(c); + c=nextc(); + } + endtoken(); + tp=listtoken(token, tp); + } + switch(c){ + case EOF: + if (tp!=NULL) + doerr(incomp); + fclose(fd); + return; + case EOS: + if (tp==NULL) + break; + case '\n': + doerr("newline after target or macroname"); + case ';': + doerr("; after target or macroname"); + case '=': + if (tp==NULL || tp->next!=NULL) + doerr("= without macro name or in token list"); + defining++; + while((c=nextc())==' ' || c=='\t'); + starttoken(); + while(c!=EOS && c!=EOF) { + addtoken(c); + c=nextc(); + } + endtoken(); + define(tp->value, token, 0); + defining=0; + break; + case ':': + if (tp==NULL) + doerr(": without preceding target"); + c=nextc(); + if (c==':'){ + twocolons=1; + c=nextc(); + } else + twocolons=0; + for(;;){ + while(c==' ' || c=='\t') + c=nextc(); + if (delim(c, "=:;\n")) + break; + starttoken(); + while(!delim(c, TDELIM)){ + addtoken(c); + c=nextc(); + } + endtoken(); + dp=listtoken(token, dp); + } + switch(c){ + case ':': + doerr("::: or : in or after dependency list"); + case '=': + doerr("= in or after dependency"); + case EOF: + doerr(incomp); + case ';': + case '\n': + ++defining; + starttoken(); + while((c=nextc())!=EOS && c!=EOF) + addtoken(c); + endtoken(); + defining = 0; + action=token; + break; + case EOS: + action=NULL; + } + install(tp, dp, action, twocolons); + } + tp = freetoken(tp); + dp = freetoken(dp); + dp = NULL; + } +} + +char *path(const char *p1, const char *p2, int mode) +{ + static char *pv = NULL; + int l1 = strlen(p1); + if (pv) + free(pv); + pv = malloc(strlen(p1) + strlen(p2) + 2); + strcpy(pv, p1); + pv[l1] = '/'; + strcpy(pv + l1 + 1, p2); + if (access(pv, mode) == 0) + return pv; + free(pv); + return NULL; +} + +/* Input with library lookup */ +void inlib(char *file) +{ + const char *p, *cp; + if ((p = getenv("LIBPATH")) == NULL) + p = "/lib:/usr/lib"; + cp = path(p, file, R_OK); + input(cp ? cp : file); +} + +/* Input first file in list which is found via SRCPATH. */ +/* Look in current directory first */ +void inpath(char *file, ...) +{ + register char **vp, *cp; + va_list ap; + va_start(ap, file); + + cp = NULL; + for (vp = va_arg(ap, char *); *vp != NULL;) + if (access(*vp, R_OK) >= 0) { + cp = *vp; + break; + } + va_end(ap); + if ( ! cp) { + va_start(ap, file); + for (vp = va_arg(ap, char *); *vp != NULL; vp += 1) + if ((cp = path(srcpath, *vp, R_OK)) != NULL) + break; + va_end(ap); + } + input(cp ? cp : file); +} + +/* Return the last modified date of file with name name. If it's an archive, + * open it up and read the insertion date of the pertinent member. + */ +time_t getmdate(char *name) +{ +#if _I386 + char *subname; + char *lwa; + int fd, x; + char magic[SARMAG]; + int size; + + time_t result; + struct ar_hdr hdrbuf; +#endif + + if (stat(name, &statbuf) == 0) + return(statbuf.st_mtime); + + +#if _I386 + subname = index(name, '('); + if (subname == NULL) + return (0); + lwa = &name[strlen(name) - 1]; + if (*lwa != ')') + return (0); + *subname = NUL; + fd = open(name, READ); + *subname++ = '('; + if (fd == EOF) + return (0); + if (read(fd, magic, SARMAG) != SARMAG) + { + close(fd); + return (0); + } + if (!strcmp(magic, ARMAG)) { + close(fd); + return (0); + } + *lwa = NUL; + result = 0; + while (read(fd, &hdrbuf, sizeof hdrbuf) == sizeof hdrbuf) { + if ((strncmp(hdrbuf.ar_name, subname, x = strlen(subname)) == 0) + && (hdrbuf.ar_name[x] == '/')) + { + result = atoi(hdrbuf.ar_date); + break; + } + size = atoi(hdrbuf.ar_size); + lseek(fd, size, SEEK_CUR); + } + *lwa = ')'; + + return (result); +#else + return 0; +#endif +} + + +/* Does file name exist? */ +int fexists(char *name) +{ +#if 0 + if (dflag) + printf("fexists(%s) = %d getmdate(name) = %d\n", name, + getmdate(name) != 0, getmdate(name)); +#endif + return getmdate(name) != 0; +} + +/* + * Find name on srcpath. + * Return 'name' unchanged if file exists as 'name', 'name' is absolute, + * or 'name' not found on sourcepath. + * If successful, return pointer to allocated copy. + */ +char *fpath(char *name) +{ + register char *s; + + if (fexists(name) + || *name == '/' + || srcpath == NULL + || (s = path(srcpath, name, R_OK)) == NULL) + return name; + starttoken(); + while (*s) + addtoken(*s++); + endtoken(); + return token; +} + +/* Return a pointer to the symbol table entry with name "name", NULL if it's + * not there. + */ +SYM *sexists(char *name) +{ + register SYM *sp; + + for(sp=sym;sp!=NULL;sp=sp->next) + if (Streq(name, sp->name)) + return(sp); + return(NULL); +} + +/* + * Return a pointer to the member of deplist which has name as the last + * part of it's pathname, otherwise return NULL. + */ +SYM *dexists(char *name, DEP *dp) +{ + register char *p; + while (dp != NULL) { + if ((p = rindex(dp->symbol->name, '/')) && Streq(name, p+1)) + return dp->symbol; + else + dp = dp->next; + } + return NULL; +} + +/* Look for symbol with name "name" in the symbol table; install it if it's + * not there; initialize the action and dependency lists to NULL, the type to + * unknown, zero the modification date, and return a pointer to the entry. + */ +SYM *lookup(char *name) +{ + register SYM *sp; + + if ((sp=sexists(name))!=NULL) + return(sp); + sp = (SYM *)mmalloc(sizeof (*sp)); /*necessary?*/ + sp->name=name; + sp->filename=fpath(name); + sp->action=NULL; + sp->deplist=NULL; + sp->type=T_UNKNOWN; + sp->moddate=0; + sp->next=sym; + sym=sp; + return(sp); +} + +/* Install a dependency with symbol having name "name", action "action" in + * the end of the dependency list pointed to by next. If s has already + * been noted as a file in the dependency list, install action. Return a + * pointer to the beginning of the dependency list. + */ +DEP *adddep(char *name, char *action, DEP *next) +{ + register DEP *v; + register SYM *s; + DEP *dp; + + s=lookup(name); + for(v=next;v!=NULL;v=v->next) + if (s==v->symbol){ + if (action != NULL) { + if (v->action!=NULL) + doerr("multiple detailed actions for %s", + s->name); + v->action=action; + } + return(next); + } + v = (DEP *)malloc(sizeof (*v)); /*necessary?*/ + v->symbol=s; + v->action=action; + v->next=NULL; + if (next==NULL) + return(v); + for(dp=next;dp->next!=NULL;dp=dp->next); + dp->next=v; + return(next); +} + +/* Do everything for a dependency with left-hand side cons, r.h.s. ante, + * action "action", and one or two colons. If cons is the first target in the + * file, it becomes the default target. Mark each target in cons as detailed + * if twocolons, undetailed if not, and install action in the symbol table + * action slot for cons in the latter case. Call adddep() to actually create + * the dependency list. + */ + +void install(TOKEN *cons, TOKEN *ante, char *action, int twocolons) +{ + SYM *cp; + TOKEN *ap; + + if (deftarget==NULL && cons->value[0]!='.') + deftarget=cons->value; + if (dflag){ + printf("Ante:"); + ap=ante; + while(ap!=NULL){ + printf(" %s", ap->value); + ap=ap->next; + } + printf("\nCons:"); + ap=cons; + while(ap!=NULL){ + printf(" %s", ap->value); + ap=ap->next; + } + printf("\n"); + if (action!=NULL) + printf("Action: '%s'\n", action); + if (twocolons) + printf("two colons\n"); + } + for (; cons != NULL; cons = cons->next) { + cp=lookup(cons->value); + if (cp==suffixes && ante==NULL) + cp->deplist=NULL; + else{ + if (twocolons){ + if (cp->type==T_UNKNOWN) + cp->type=T_DETAIL; + else if (cp->type!=T_DETAIL) + doerr("'::' not allowed for %s", + cp->name); + } else { + if (cp->type==T_UNKNOWN) + cp->type=T_NODETAIL; + else if (cp->type!=T_NODETAIL) + doerr("must use '::' for %s", cp->name); + if (action != NULL) { + if (cp->action != NULL) + { + if (!inactionfile) + doerr("multiple action" + "s for %s", cp->name); + } + else + cp->action = action; + } + } + for(ap=ante;ap!=NULL;ap=ap->next) + cp->deplist=adddep(ap->value, + twocolons?action:NULL, cp->deplist); + } + } +} + +/* Make s; first, make everything s depends on; if the target has detailed + * actions, execute any implicit actions associated with it, then execute + * the actions associated with the dependencies which are newer than s. + * Otherwise, put the dependencies that are newer than s in token ($?), + * make s if it doesn't exist, and call docmd. + */ +void make(SYM *s) +{ + register DEP *dep; + register char *t, *name; + int update; + int type; + + if (s->type==T_DONE) + return; + name = s->filename; + if (dflag) { + if (s->name == name) + printf("Making %s\n", name); + else + printf("Making %s (file %s)\n", s->name, name); + } + type=s->type; + s->type=T_DONE; + s->moddate=getmdate(name); + for(dep=s->deplist;dep!=NULL;dep=dep->next) + make(dep->symbol); + if (type==T_DETAIL){ + implicit(s, "", 0); + for(dep=s->deplist;dep!=NULL;dep=dep->next) + if (dep->symbol->moddate>s->moddate) + docmd0(s, dep->action, name, dep->symbol->filename); + } else { + update=0; + starttoken(); + for(dep=s->deplist;dep!=NULL;dep=dep->next){ + if (dflag) + printf("%s time=%ld %s time=%ld\n", + dep->symbol->filename, dep->symbol->moddate, + name, s->moddate); + if (dep->symbol->moddate>s->moddate){ + update++; + addtoken(' '); + for(t=dep->symbol->filename;*t;t++) + addtoken(*t); + } + } + endtoken(); + t = token; + if (!update && !fexists(name)) { + update = TRUE; + if (dflag) + printf("'%s' made due to non-existence\n", + name); + } + if (s->action==NULL) + implicit(s, t, update); + else if (update) + docmd0(s, s->action, name, t); + free(t); + } +} + +/* + * Expand substitutes the macros in actions and returns the string. + */ +void expand(char *str) +{ + register int c; + register char *p; + int endc; + + while (c = *str++) { + if (c == '$') { + c = *str++; + switch (c) { + case '\0': doerr(badmac); + case '$': addtoken(c); continue; + case '@': p = mvarval[0]; break; + case '?': p = mvarval[1]; break; + case '<': p = mvarval[2]; break; + case '*': p = mvarval[3]; break; + case '{': + case '(': + endc = (c == '(') ? ')' : '}'; + c = '('; + p = str; + do c = *str++; while (c != 0 && c != endc); + if (c == 0) + doerr(badmac); + *--str = 0; + p = mexists(p); + *str++ = endc; + break; + default: + if ( ! ismacro(c)) + doerr(badmac); + c = *str; + *str = 0; + p = mexists(str-1); + *str = c; + break; + } + if (p != NULL) + expand(p); + } else + addtoken(c); + } +} + +/* Like docmd(), except builds its own dependency list and prefix args. */ +void docmd0(SYM *s, char *cmd, char *at, char *ques) +{ + register char *cp; + register DEP *dep; + char *less, *prefix; + + /* Build dependency list. */ + starttoken(); + for (dep = s->deplist; dep != NULL; dep = dep->next) { + addtoken(' '); + for (cp = dep->symbol->filename; *cp; cp++) + addtoken(*cp); + } + endtoken(); + less = token; + + /* Build prefix. */ + starttoken(); + for (cp = s->name; *cp; cp++) + addtoken(*cp); + endtoken(); + prefix = token; + + if ((cp = rindex(prefix, '.')) != NULL) + *cp = '\0'; + docmd(s, cmd, at, ques, less, prefix); + free(less); + free(prefix); +} + +/* Mark s as modified; if tflag, touch s, otherwise execute the necessary + * commands. + */ +void docmd(SYM *s, char *cmd, char *at, char *ques, char *less, char *star) +{ + if (dflag) + printf("ex '%s'\n\t$@='%s'\n\t$?='%s'\n\t$<='%s'\n\t$*='%s'\n", + cmd, at, ques, less, star); + if (qflag) + exit(NOTUTD); + s->moddate = now; + if (tflag) + cmd = "touch $@"; + if (cmd == NULL) + return; + mvarval[0] = at; + mvarval[1] = ques; + mvarval[2] = less; + mvarval[3] = star; + starttoken(); + expand(cmd); + endtoken(); + doit(token); + free(token); +} + + +/* look for '-' (ignore errors) and '@' (silent) in cmd, then execute it + * and note the return status. + */ +void doit(char *cmd) +{ + register char *mark; + int sflg, iflg, rstat; + + if (nflag) { + printf("%s\n", cmd); + return; + } + do { + mark = index(cmd, '\n'); + if (mark != NULL) + *mark = NUL; + if (*cmd == '-') { + ++cmd; + iflg = TRUE; + } else + iflg = iflag; + if (*cmd == '@') { + ++cmd; + sflg = TRUE; + } else + sflg = sflag; + if (!sflg) + printf("%s\n", cmd); + fflush(stdout); + rstat = system(cmd); + if (rstat != 0 && !iflg) + if (sflg) + die("%s exited with status %d", + cmd, rstat); + else + die(" exited with status %d", rstat); + cmd = mark + 1; + } while (mark != NULL && *cmd != NUL); +} + + +/* Find the implicit rule to generate obj and execute it. Put the name of + * obj up to '.' in prefix, and look for the rest in the dependency list + * of .SUFFIXES. Find the file "prefix.foo" upon which obj depends, where + * foo appears in the dependency list of suffixes after the suffix of obj. + * Then make obj according to the rule from makeactions. If we can't find + * any rules, use .DEFAULT, provided we're definite. + */ + +void implicit(SYM *obj, char *ques, int definite) +{ + register char *s; + register DEP *d; + char *prefix, *file, *rulename, *suffix; + SYM *rule; + SYM *subj; + + if (dflag) + printf("Implicit %s (%s)\n", obj->name, ques); + if ((suffix=rindex(obj->name, '.')) == NULL + || suffix==obj->name) { + if (definite) + defalt(obj, ques); + return; + } + starttoken(); + for(s=obj->name; sdeplist;d!=NULL;d=d->next) + if (Streq(suffix, d->symbol->name)) + break; + if (d==NULL){ + free(prefix); + if (definite) + defalt(obj, ques); + return; + } + while((d=d->next)!=NULL){ + starttoken(); + for(s=obj->name; s!=suffix; s++) + addtoken(*s); + for(s=d->symbol->name;*s;s++) + addtoken(*s); + endtoken(); + file=token; + if ((s = fpath(file)) != file) { + free(file); + file = s; + } + subj=NULL; + if (fexists(file) || (subj=dexists(file, obj->deplist))){ + starttoken(); + for(s=d->symbol->filename;*s!='\0';s++) + addtoken(*s); + for(s=suffix;*s!='\0';s++) + addtoken(*s); + endtoken(); + rulename=token; + if ((rule=sexists(rulename))!=NULL){ + if (subj != NULL || (subj=sexists(file))) { + free(file); + file=subj->name; + } else + subj=lookup(file); + make(subj); + if (definite || subj->moddate>obj->moddate) + docmd(obj, rule->action, + obj->name, ques, file, prefix); + free(prefix); + free(rulename); + return; + } + free(rulename); + } + free(file); + } + free(prefix); + if (definite) + defalt(obj, ques); +} + +/* + * Deflt uses the commands associated to '.DEFAULT' to make the object + * 'obj'. + */ + +void defalt(SYM *obj, char *ques) +{ + if (deflt == NULL) + { + if (obj->deplist == NULL) + die("do not know how to make %s", obj->name); + } + else + docmd0(obj, deflt->action, obj->name, ques); +} + +int main(int argc, char *argv[]) +{ + register char *s, *value; + register char *namesave; + register int c; + int len, numtargets = 0; + char **dtarget; + TOKEN *fp = NULL; + SYM *sp; + DEP *d; + MACRO *mp; + extern char **environ; + char **envp = environ; + + + if ((dtarget = malloc(argc * sizeof(char *))) == NULL) + doerr(nospace); + + time(&now); + ++argv; + --argc; + + while (argc > 0) + { + if (argv[0][0] == '-') + { + for (--argc, s = *argv++; *++s != NUL;) + switch (*s) { + case 'd': dflag++; break; + case 'e': eflag++; break; + case 'i': iflag++; break; + case 'n': nflag++; break; + case 'p': pflag++; break; + case 'q': qflag++; break; + case 'r': rflag++; break; + case 's': sflag++; break; + case 't': tflag++; break; + case 'f': + if (--argc < 0) + Usage(); + fp=listtoken(*argv++, fp); + break; + default: + Usage(); + } + } + else if ((value = index(*argv, '=')) != NULL) + { + s = *argv; + while (*s != ' ' && *s != '\t' && *s != '=') + ++s; + *s = '\0'; + define(*argv++, value+1, 1); + --argc; + } + else + { + dtarget[numtargets++] = *argv++; + --argc; + } + } + while (*envp != NULL) { + if ((value = index(*envp, '=')) != NULL + && index(value, '$') == NULL) { + s = *envp; + while ((c=*s) != ' ' && c != '\t' && c != '=') + ++s; + + len = s - *envp; + namesave=mmalloc(len+1); + strncpy(namesave, *envp, len); + namesave[len] = '\0'; + + if (eflag) + define(namesave, value+1, 1); + else { + starttoken(); + while (*++value) addtoken(*value); + endtoken(); + define(namesave, token, 0); + } + } + ++envp; + } + srcpath = mexists("SRCPATH"); + suffixes=lookup(".SUFFIXES"); + if (!rflag) + inlib(MACROFILE); + deftarget = NULL; + if (fp == NULL) + inpath("makefile", "Makefile", NULL); + else { + fd = stdin; + do { + input( strcmp(fp->value, "-") == 0 ? NULL : fp->value); + fp = fp->next; + } while (fp != NULL); + } + if (!rflag) + { + inactionfile = 1; + inlib(ACTIONFILE); + inactionfile = 0; + } + + if (sexists(".IGNORE") != NULL) + ++iflag; + if (sexists(".SILENT") != NULL) + ++sflag; + deflt = sexists(".DEFAULT"); + if (pflag){ + if (macro != NULL) { + printf("Macros:\n"); + for (mp = macro; mp != NULL; mp=mp->next) + printf("%s=%s\n", mp->name, mp->value); + } + printf("Rules:\n"); + for(sp=sym;sp!=NULL;sp=sp->next){ + if (sp->type!=T_UNKNOWN){ + printf("%s:", sp->name); + if (sp->type==T_DETAIL) + putchar(':'); + for(d=sp->deplist;d!=NULL;d=d->next) + printf(" %s", d->symbol->name); + printf("\n"); + if (sp->action) + printf("\t%s\n", sp->action); + } + } + } + if (numtargets) + + { + int i; + + for (i=0;i +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Exit codes. */ +#define ALLOK 0 /* all ok, if -q option then all uptodate */ +#define ERROR 1 /* something went wrong */ +#define NOTUTD 2 /* with -q option, something is not uptodate */ + +/* Types. */ +#define T_UNKNOWN 0 +#define T_NODETAIL 1 +#define T_DETAIL 2 +#define T_DONE 3 + +/* Other manifest constants. */ +#define TRUE (0 == 0) +#define FALSE (0 != 0) +#define EOS 0200 +#define NUL '\0' +#define NBACKUP 2048 +#define NMACRONAME 48 +#define NTOKBUF 100 +#define READ 0 /* open argument for reading */ + +/* Macros. */ +#define Streq(a,b) (strcmp(a,b) == 0) + +/* Structures. */ +typedef struct token { + struct token *next; + char *value; +} TOKEN; + +typedef struct macro { + struct macro *next; + char *value; + char *name; + int protected; +} MACRO; + +typedef struct sym { + struct sym *next; + char *action; + char *name; + char *filename; + struct dep *deplist; + int type; + time_t moddate; +} SYM; + +typedef struct dep { + struct dep *next; + char *action; + struct sym *symbol; +} DEP; + +/* System dependencies. */ + +#define ACTIONFILE "makeactions" +#define MACROFILE "makemacros" +#define TDELIM " \t\n=:;" + +extern void die(const char *, ...); +extern void doerr(const char *, ...); +extern char *mmaloc(size_t); +extern void Usage(void); +extern int readc(void); +extern void putback(int); +extern void unreads(char *); +extern char *mexists(char *); +extern void define(char *, char *, int); +extern int ismacro(int); +extern int nextc(void); +extern char *extend(char *, int, char *, int); +extern int delim(char , char *); +extern void starttoken(void); +extern void addtoken(int); +extern void endtoken(void); +extern TOKEN *listtoken(char *, TOKEN *); +extern TOKEN *freetoken(TOKEN *); +extern void input(char *); +extern void inlib(char *); +extern void inpath(char *, ...); +extern time_t getmdate(char *); +extern int fexists(char *); +extern char *fpath(char *); +extern SYM *sexists(char *name); +extern SYM *dexists(char *name, DEP *dp); +extern SYM *lookup(char *); +extern DEP *adddep(char *, char *, DEP *); +extern void install(TOKEN *, TOKEN *, char *, int); +extern void make(SYM *); +extern void expand(char *); +extern void docmd0(SYM *, char *, char *, char *); +extern void docmd(SYM *, char *, char *, char *, char *, char *); +extern void doit(char *cmd); +extern void implicit(SYM *, char *, int); +extern void defalt(SYM *, char *); + + +/* end of make.h */ diff --git a/Applications/MWC/cmd/makeactions b/Applications/MWC/cmd/makeactions new file mode 100644 index 00000000..f0c9297d --- /dev/null +++ b/Applications/MWC/cmd/makeactions @@ -0,0 +1,22 @@ +# Default actions. + +.c.o .c.obj .m.o .m.obj: + $(CC) $(CFLAGS) -c $< +.s.o .s.obj: + $(AS) $(ASFLAGS) -o $@ $< +.y.o: + $(YACC) $(YFLAGS) $< + $(CC) $(CFLAGS) -c y.tab.c + rm y.tab.c + mv y.tab.o $@ +.y.c: + $(YACC) $(YFLAGS) $< + mv y.tab.c $@ +.l.o: + $(LEX) $(LFLAGS) $< + $(CC) $(CFLAGS) -c lex.yy.c + rm lex.yy.c + mv lex.yy.o $@ +.l.c: + $(LEX) $(LFLAGS) $< + mv lex.yy.c $@ diff --git a/Applications/MWC/cmd/makemacros b/Applications/MWC/cmd/makemacros new file mode 100644 index 00000000..751fbde5 --- /dev/null +++ b/Applications/MWC/cmd/makemacros @@ -0,0 +1,17 @@ +# /usr/lib/makemacros 2/14/92 +# Default macro definitions. + +.SUFFIXES: .o .obj .c .y .l .s .m +AR = ar +AS = as +ASFLAGS = -gx +CC = cc +CFLAGS = -O +CPP = cpp +CPPFLAGS= -E +LEX = lex +LFLAGS = +YACC = yacc +YFLAGS = + +# end of /usr/lib/makemacros -- 2.34.1