From 36be9057f974161d6acf9abbc886cb2f4da7fd64 Mon Sep 17 00:00:00 2001 From: Bill Joy Date: Wed, 13 Feb 1980 18:58:44 -0800 Subject: [PATCH] BSD 3 development Work on file usr/src/cmd/make/defs Work on file usr/src/cmd/make/Makefile Work on file usr/src/cmd/make/doname.c Work on file usr/src/cmd/make/dosys.c Work on file usr/src/cmd/make/gram.y Work on file usr/src/cmd/make/files.c Work on file usr/src/cmd/make/ident.c Work on file usr/src/cmd/make/main.c Work on file usr/src/cmd/make/misc.c Synthesized-from: 3bsd --- usr/src/cmd/make/Makefile | 71 ++++++ usr/src/cmd/make/defs | 130 ++++++++++ usr/src/cmd/make/doname.c | 299 +++++++++++++++++++++++ usr/src/cmd/make/dosys.c | 169 +++++++++++++ usr/src/cmd/make/files.c | 502 ++++++++++++++++++++++++++++++++++++++ usr/src/cmd/make/gram.y | 306 +++++++++++++++++++++++ usr/src/cmd/make/ident.c | 99 ++++++++ usr/src/cmd/make/main.c | 370 ++++++++++++++++++++++++++++ usr/src/cmd/make/misc.c | 337 +++++++++++++++++++++++++ 9 files changed, 2283 insertions(+) create mode 100644 usr/src/cmd/make/Makefile create mode 100644 usr/src/cmd/make/defs create mode 100644 usr/src/cmd/make/doname.c create mode 100644 usr/src/cmd/make/dosys.c create mode 100644 usr/src/cmd/make/files.c create mode 100644 usr/src/cmd/make/gram.y create mode 100644 usr/src/cmd/make/ident.c create mode 100644 usr/src/cmd/make/main.c create mode 100644 usr/src/cmd/make/misc.c diff --git a/usr/src/cmd/make/Makefile b/usr/src/cmd/make/Makefile new file mode 100644 index 0000000000..e2369136e8 --- /dev/null +++ b/usr/src/cmd/make/Makefile @@ -0,0 +1,71 @@ +# Description file for the Make command + +P = und -3 | opr -r2 +T = +FILES = Makefile ident.c defs main.c doname.c misc.c files.c dosys.c\ + gram.y gcos.c +OBJECTS = ident.o main.o doname.o misc.o files.o dosys.o gram.o +LIBES= +LINT = lint -ps +CFLAGS = -O + +GCOSFILES = defs ident.c main.c doname.c misc.c gram.c gcos.c + +all: make + +cmp: make + cmp make /bin/make + rm *.o gram.c make + +cp: make + cp make /bin/make + rm *.o gram.c make + +make: $(OBJECTS) + $(CC) -n -s $(CFLAGS) $(OBJECTS) $(LIBES) -o make + +$(OBJECTS): defs + +clean: + -rm *.o gram.c + +install: + install make $(DESTDIR)/bin/make + +printall: # Print files off line. + -pr $(FILES) | $P + touch print + +print: $(FILES) # print recently changed files + -pr $? | $P + touch print + +save: # Write files on Spider store. + -nfs -ucv make $(FILES) + +test: 1zap 2zap + diff 1zap 2zap + rm 1zap 2zap + +1zap: + ./make -dp | grep -v TIME >1zap + +2zap: + /bin/make -dp | grep -v TIME >2zap + +time: time1 time2 ; + +time1 time2 : + time ./make $T + time /bin/make $T + +lint : dosys.c doname.c files.c main.c misc.c ident.c gram.c + $(LINT) dosys.c doname.c files.c main.c misc.c ident.c gram.c + rm gram.c + +src: + cp $(FILES) /usr/src/cmd/make + +gcos: $(GCOSFILES) + fsend -c -u sif $? + touch gcos diff --git a/usr/src/cmd/make/defs b/usr/src/cmd/make/defs new file mode 100644 index 0000000000..79c817c68b --- /dev/null +++ b/usr/src/cmd/make/defs @@ -0,0 +1,130 @@ +#include +#include + +#define SHELLCOM "/bin/sh" +typedef long int TIMETYPE; + +#ifdef unix +/* to install metering, add a statement like */ +#define METERFILE "/usr/sif/make/Meter" +/* to turn metering on, set external variable meteron to 1 */ +#endif + +/* define FSTATIC to be static on systems with C compilers + supporting file-static; otherwise define it to be null +*/ +#define FSTATIC static + +#define NO 0 +#define YES 1 + +#define unequal strcmp +#define HASHSIZE 509 +#define NLEFTS 40 +#define NCHARS 500 +#define NINTS 250 +#define INMAX 1500 +#define OUTMAX 2500 +#define QBUFMAX 1500 +#define MAXDIR 10 + +#define ALLDEPS 1 +#define SOMEDEPS 2 + +#define META 01 +#define TERMINAL 02 +extern char funny[128]; + + +#define ALLOC(x) (struct x *) ckalloc(sizeof(struct x)) + +extern int sigivalue; +extern int sigqvalue; +extern int waitpid; +extern int dbgflag; +extern int prtrflag; +extern int silflag; +extern int noexflag; +extern int keepgoing; +extern int noruleflag; +extern int touchflag; +extern int questflag; +extern int ndocoms; +extern int ignerr; +extern int okdel; +extern int inarglist; +extern char *prompt; +extern int nopdir; +extern char junkname[ ]; + + + +struct nameblock + { + struct nameblock *nxtnameblock; + char *namep; + struct lineblock *linep; + int done:3; + int septype:3; + TIMETYPE modtime; + }; + +extern struct nameblock *mainname ; +extern struct nameblock *firstname; + +struct lineblock + { + struct lineblock *nxtlineblock; + struct depblock *depp; + struct shblock *shp; + }; +extern struct lineblock *sufflist; + +struct depblock + { + struct depblock *nxtdepblock; + struct nameblock *depname; + }; + +struct shblock + { + struct shblock *nxtshblock; + char *shbp; + }; + +struct varblock + { + struct varblock *nxtvarblock; + char *varname; + char *varval; + int noreset:1; + int used:1; + }; +extern struct varblock *firstvar; + +struct pattern + { + struct pattern *nxtpattern; + char *patval; + }; +extern struct pattern *firstpat; + +struct opendir + { + struct opendir *nxtopendir; + FILE * dirfc; + char *dirn; + }; +extern struct opendir *firstod; + + +struct chain + { + struct chain *nextp; + char *datap; + }; + +char *copys(), *concat(), *subst(); +int *ckalloc(); +struct nameblock *srchname(), *makename(); +TIMETYPE exists(); diff --git a/usr/src/cmd/make/doname.c b/usr/src/cmd/make/doname.c new file mode 100644 index 0000000000..407b57a5f3 --- /dev/null +++ b/usr/src/cmd/make/doname.c @@ -0,0 +1,299 @@ +#include "defs" + +/* BASIC PROCEDURE. RECURSIVE. */ + +/* +p->done = 0 don't know what to do yet +p->done = 1 file in process of being updated +p->done = 2 file already exists in current state +p->done = 3 file make failed +*/ + +doname(p, reclevel, tval) +register struct nameblock *p; +int reclevel; +TIMETYPE *tval; +{ +int errstat; +int okdel1; +int didwork; +TIMETYPE td, td1, tdep, ptime, ptime1, prestime(); +register struct depblock *q; +struct depblock *qtemp, *srchdir(), *suffp, *suffp1; +struct nameblock *p1, *p2; +struct shblock *implcom, *explcom; +register struct lineblock *lp; +struct lineblock *lp1, *lp2; +char sourcename[100], prefix[100], temp[100], concsuff[20]; +char *pnamep, *p1namep; +char *mkqlist(); +struct chain *qchain, *appendq(); + +if(p == 0) + { + *tval = 0; + return(0); + } + +if(dbgflag) + { + printf("doname(%s,%d)\n",p->namep,reclevel); + fflush(stdout); + } + +if(p->done > 0) + { + *tval = p->modtime; + return(p->done == 3); + } + +errstat = 0; +tdep = 0; +implcom = 0; +explcom = 0; +ptime = exists(p->namep); +ptime1 = 0; +didwork = NO; +p->done = 1; /* avoid infinite loops */ + +qchain = NULL; + +/* Expand any names that have embedded metacharaters */ + +for(lp = p->linep ; lp ; lp = lp->nxtlineblock) + for(q = lp->depp ; q ; q=qtemp ) + { + qtemp = q->nxtdepblock; + expand(q); + } + +/* make sure all dependents are up to date */ + +for(lp = p->linep ; lp ; lp = lp->nxtlineblock) + { + td = 0; + for(q = lp->depp ; q ; q = q->nxtdepblock) + { + errstat += doname(q->depname, reclevel+1, &td1); + if(dbgflag) + printf("TIME(%s)=%ld\n", q->depname->namep, td1); + if(td1 > td) td = td1; + if(ptime < td1) + qchain = appendq(qchain, q->depname->namep); + } + if(p->septype == SOMEDEPS) + { + if(lp->shp!=0) + if( ptimedepp==0) + { + okdel1 = okdel; + okdel = NO; + setvar("@", p->namep); + setvar("?", mkqlist(qchain) ); + qchain = NULL; + if( !questflag ) + errstat += docom(lp->shp); + setvar("@", (char *) NULL); + okdel = okdel1; + ptime1 = prestime(); + didwork = YES; + } + } + + else { + if(lp->shp != 0) + { + if(explcom) + fprintf(stderr, "Too many command lines for `%s'\n", + p->namep); + else explcom = lp->shp; + } + + if(td > tdep) tdep = td; + } + } + +/* Look for implicit dependents, using suffix rules */ + +for(lp = sufflist ; lp ; lp = lp->nxtlineblock) + for(suffp = lp->depp ; suffp ; suffp = suffp->nxtdepblock) + { + pnamep = suffp->depname->namep; + if(suffix(p->namep , pnamep , prefix)) + { + srchdir( concat(prefix,"*",temp) , NO, (struct depblock *) NULL); + for(lp1 = sufflist ; lp1 ; lp1 = lp1->nxtlineblock) + for(suffp1=lp1->depp ; suffp1 ; suffp1 = suffp1->nxtdepblock) + { + p1namep = suffp1->depname->namep; + if( (p1=srchname(concat(p1namep, pnamep ,concsuff))) && + (p2=srchname(concat(prefix, p1namep ,sourcename))) ) + { + errstat += doname(p2, reclevel+1, &td); + if(ptime < td) + qchain = appendq(qchain, p2->namep); +if(dbgflag) printf("TIME(%s)=%ld\n", p2->namep, td); + if(td > tdep) tdep = td; + setvar("*", prefix); + setvar("<", copys(sourcename)); + for(lp2=p1->linep ; lp2 ; lp2 = lp2->nxtlineblock) + if(implcom = lp2->shp) break; + goto endloop; + } + } + } + } + +endloop: + + +if(errstat==0 && (ptime0 ? tdep : prestime() ); + setvar("@", p->namep); + setvar("?", mkqlist(qchain) ); + if(explcom) + errstat += docom(explcom); + else if(implcom) + errstat += docom(implcom); + else if(p->septype == 0) + if(p1=srchname(".DEFAULT")) + { + setvar("<", p->namep); + for(lp2 = p1->linep ; lp2 ; lp2 = lp2->nxtlineblock) + if(implcom = lp2->shp) + { + errstat += docom(implcom); + break; + } + } + else if(keepgoing) + { + printf("Don't know how to make %s\n", p->namep); + ++errstat; + } + else + fatal1(" Don't know how to make %s", p->namep); + + setvar("@", (char *) NULL); + if(noexflag || (ptime = exists(p->namep)) == 0) + ptime = prestime(); + } + +else if(errstat!=0 && reclevel==0) + printf("`%s' not remade because of errors\n", p->namep); + +else if(!questflag && reclevel==0 && didwork==NO) + printf("`%s' is up to date.\n", p->namep); + +if(questflag && reclevel==0) + exit(ndocoms>0 ? -1 : 0); + +p->done = (errstat ? 3 : 2); +if(ptime1 > ptime) ptime = ptime1; +p->modtime = ptime; +*tval = ptime; +return(errstat); +} + +docom(q) +struct shblock *q; +{ +char *s; +struct varblock *varptr(); +int ign, nopr; +char string[OUTMAX]; + +++ndocoms; +if(questflag) + return(NO); + +if(touchflag) + { + s = varptr("@")->varval; + if(!silflag) + printf("touch(%s)\n", s); + if(!noexflag) + touch(YES, s); + } + +else for( ; q ; q = q->nxtshblock ) + { + subst(q->shbp,string); + + ign = ignerr; + nopr = NO; + for(s = string ; *s=='-' || *s=='@' ; ++s) + if(*s == '-') ign = YES; + else nopr = YES; + + if( docom1(s, ign, nopr) && !ign) + if(keepgoing) + return(YES); + else fatal( (char *) NULL); + } +return(NO); +} + + + +docom1(comstring, nohalt, noprint) +register char *comstring; +int nohalt, noprint; +{ +register int status; + +if(comstring[0] == '\0') return(0); + +if(!silflag && (!noprint || noexflag) ) + { + printf("%s%s\n", (noexflag ? "" : prompt), comstring); + fflush(stdout); + } + +if(noexflag) return(0); + +if( status = dosys(comstring, nohalt) ) + { + if( status>>8 ) + printf("*** Error code %d", status>>8 ); + else printf("*** Termination code %d", status ); + + if(nohalt) printf(" (ignored)\n"); + else printf("\n"); + fflush(stdout); + } + +return(status); +} + + +/* + If there are any Shell meta characters in the name, + expand into a list, after searching directory +*/ + +expand(q) +register struct depblock *q; +{ +register char *s; +char *s1; +struct depblock *p, *srchdir(); + +s1 = q->depname->namep; +for(s=s1 ; ;) switch(*s++) + { + case '\0': + return; + + case '*': + case '?': + case '[': + if( p = srchdir(s1 , YES, q->nxtdepblock) ) + { + q->nxtdepblock = p; + q->depname = 0; + } + return; + } +} diff --git a/usr/src/cmd/make/dosys.c b/usr/src/cmd/make/dosys.c new file mode 100644 index 0000000000..3250b41d20 --- /dev/null +++ b/usr/src/cmd/make/dosys.c @@ -0,0 +1,169 @@ +#include "defs" +#include + +dosys(comstring,nohalt) +register char *comstring; +int nohalt; +{ +register int status; + +if(metas(comstring)) + status = doshell(comstring,nohalt); +else status = doexec(comstring); + +return(status); +} + + + +metas(s) /* Are there are any Shell meta-characters? */ +register char *s; +{ +register char c; + +while( (funny[c = *s++] & META) == 0 ) + ; +return( c ); +} + +doshell(comstring,nohalt) +char *comstring; +int nohalt; +{ +if((waitpid = vfork()) == 0) + { + enbint(SIG_DFL); + doclose(); + + execl(SHELLCOM, "sh", (nohalt ? "-c" : "-ce"), comstring, 0); + fatal("Couldn't load Shell"); + } + +return( await() ); +} + + + + +await() +{ +int intrupt(); +int status; +register int pid; + +enbint(intrupt); +while( (pid = wait(&status)) != waitpid) + if(pid == -1) + fatal("bad wait code"); +waitpid = 0; +return(status); +} + + + + + + +doclose() /* Close open directory files before exec'ing */ +{ +register struct opendir *od; +for (od = firstod; od; od = od->nxtopendir) + if (od->dirfc != NULL) + /* fclose(od->dirfc); */ + close(od->dirfc->_file); +} + + + + + +doexec(str) +register char *str; +{ +register char *t; +char *argv[200]; +register char **p; + +while( *str==' ' || *str=='\t' ) + ++str; +if( *str == '\0' ) + return(-1); /* no command */ + +p = argv; +for(t = str ; *t ; ) + { + *p++ = t; + while(*t!=' ' && *t!='\t' && *t!='\0') + ++t; + if(*t) + for( *t++ = '\0' ; *t==' ' || *t=='\t' ; ++t) + ; + } + +*p = NULL; + +if((waitpid = vfork()) == 0) + { + enbint(SIG_DFL); + doclose(); + execvp(str, argv); + fatal1("Cannot load %s",str); + } + +return( await() ); +} + +#include + +#include +#include + + + + +touch(force, name) +int force; +char *name; +{ +struct stat stbuff; +char junk[1]; +int fd; + +if( stat(name,&stbuff) < 0) + if(force) + goto create; + else + { + fprintf(stderr, "touch: file %s does not exist.\n", name); + return; + } + +if(stbuff.st_size == 0) + goto create; + +if( (fd = open(name, 2)) < 0) + goto bad; + +if( read(fd, junk, 1) < 1) + { + close(fd); + goto bad; + } +lseek(fd, 0L, 0); +if( write(fd, junk, 1) < 1 ) + { + close(fd); + goto bad; + } +close(fd); +return; + +bad: + fprintf(stderr, "Cannot touch %s\n", name); + return; + +create: + if( (fd = creat(name, 0666)) < 0) + goto bad; + close(fd); +} diff --git a/usr/src/cmd/make/files.c b/usr/src/cmd/make/files.c new file mode 100644 index 0000000000..474a74a58e --- /dev/null +++ b/usr/src/cmd/make/files.c @@ -0,0 +1,502 @@ +/* UNIX DEPENDENT PROCEDURES */ + + +/* DEFAULT RULES FOR UNIX */ + +char *builtin[] = + { +#ifdef pwb + ".SUFFIXES : .L .out .o .c .f .e .r .y .yr .ye .l .s .z .x .t .h", +#else + ".SUFFIXES : .out .o .c .f .e .r .y .yr .ye .l .s", +#endif + "YACC=yacc", + "YACCR=yacc -r", + "YACCE=yacc -e", + "YFLAGS=", + "LEX=lex", + "LFLAGS=", + "CC=cc", +#ifdef vax + "AS=as", +#else + "AS=as -", +#endif + "CFLAGS=", + "RC=f77", + "RFLAGS=", + "EC=f77", + "EFLAGS=", + "FFLAGS=", + "LOADLIBES=", +#ifdef pwb + "SCOMP=scomp", + "SCFLAGS=", + "CMDICT=cmdict", + "CMFLAGS=", +#endif + + ".c.o :", + "\t$(CC) $(CFLAGS) -c $<", + + ".e.o .r.o .f.o :", + "\t$(EC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $<", + + ".s.o :", + "\t$(AS) -o $@ $<", + + ".y.o :", + "\t$(YACC) $(YFLAGS) $<", + "\t$(CC) $(CFLAGS) -c y.tab.c", + "\trm y.tab.c", + "\tmv y.tab.o $@", + + ".yr.o:", + "\t$(YACCR) $(YFLAGS) $<", + "\t$(RC) $(RFLAGS) -c y.tab.r", + "\trm y.tab.r", + "\tmv y.tab.o $@", + + ".ye.o :", + "\t$(YACCE) $(YFLAGS) $<", + "\t$(EC) $(RFLAGS) -c y.tab.e", + "\trm y.tab.e", + "\tmv y.tab.o $@", + + ".l.o :", + "\t$(LEX) $(LFLAGS) $<", + "\t$(CC) $(CFLAGS) -c lex.yy.c", + "\trm lex.yy.c", + "\tmv lex.yy.o $@", + + ".y.c :", + "\t$(YACC) $(YFLAGS) $<", + "\tmv y.tab.c $@", + + ".l.c :", + "\t$(LEX) $(LFLAGS) $<", + "\tmv lex.yy.c $@", + + ".yr.r:", + "\t$(YACCR) $(YFLAGS) $<", + "\tmv y.tab.r $@", + + ".ye.e :", + "\t$(YACCE) $(YFLAGS) $<", + "\tmv y.tab.e $@", + +#ifdef pwb + ".o.L .c.L .t.L:", + "\t$(SCOMP) $(SCFLAGS) $<", + + ".t.o:", + "\t$(SCOMP) $(SCFLAGS) -c $<", + + ".t.c:", + "\t$(SCOMP) $(SCFLAGS) -t $<", + + ".h.z .t.z:", + "\t$(CMDICT) $(CMFLAGS) $<", + + ".h.x .t.x:", + "\t$(CMDICT) $(CMFLAGS) -c $<", +#endif + + ".s.out .c.out .o.out :", + "\t$(CC) $(CFLAGS) $< $(LOADLIBES) -o $@", + + ".f.out .r.out .e.out :", + "\t$(EC) $(EFLAGS) $(RFLAGS) $(FFLAGS) $< $(LOADLIBES) -o $@", + "\t-rm $*.o", + + ".y.out :", + "\t$(YACC) $(YFLAGS) $<", + "\t$(CC) $(CFLAGS) y.tab.c $(LOADLIBES) -ly -o $@", + "\trm y.tab.c", + + ".l.out :", + "\t$(LEX) $(LFLAGS) $<", + "\t$(CC) $(CFLAGS) lex.yy.c $(LOADLIBES) -ll -o $@", + "\trm lex.yy.c", + + 0 }; + +#include "defs" +#include + + +TIMETYPE exists(filename) +char *filename; +{ +#include +struct stat buf; +register char *s; +TIMETYPE lookarch(); + +for(s = filename ; *s!='\0' && *s!='(' ; ++s) + ; + +if(*s == '(') + return(lookarch(filename)); + +if(stat(filename,&buf) < 0) + return(0); +else return(buf.st_mtime); +} + + +TIMETYPE prestime() +{ +TIMETYPE t; +time(&t); +return(t); +} + + + +#include +FSTATIC char n15[15]; +FSTATIC char *n15end = &n15[14]; + + + +struct depblock *srchdir(pat, mkchain, nextdbl) +register char *pat; /* pattern to be matched in directory */ +int mkchain; /* nonzero if results to be remembered */ +struct depblock *nextdbl; /* final value for chain */ +{ +FILE * dirf; +int i, nread, cldir; +char *dirname, *dirpref, *endir, *filepat, *p, temp[100]; +char fullname[100], *p1, *p2; +struct nameblock *q; +struct depblock *thisdbl; +struct opendir *od; +struct pattern *patp; + +struct direct entry[32]; + + +thisdbl = 0; + +if(mkchain == NO) + for(patp=firstpat ; patp ; patp = patp->nxtpattern) + if(! unequal(pat, patp->patval)) return(0); + +patp = ALLOC(pattern); +patp->nxtpattern = firstpat; +firstpat = patp; +patp->patval = copys(pat); + +endir = 0; + +for(p=pat; *p!='\0'; ++p) + if(*p=='/') endir = p; + +if(endir==0) + { + dirname = "."; + dirpref = ""; + filepat = pat; + } +else { + dirname = pat; + *endir = '\0'; + dirpref = concat(dirname, "/", temp); + filepat = endir+1; + } + +dirf = NULL; +cldir = NO; + +for(od = firstod ; od; od = od->nxtopendir) + if(! unequal(dirname, od->dirn) ) + { + dirf = od->dirfc; + fseek(dirf,0L,0); /* start over at the beginning */ + break; + } + +if(dirf == NULL) + { + dirf = fopen(dirname, "r"); + if(nopdir >= MAXDIR) + cldir = YES; + else { + ++nopdir; + od = ALLOC(opendir); + od->nxtopendir = firstod; + firstod = od; + od->dirfc = dirf; + od->dirn = copys(dirname); + } + } + +if(dirf == NULL) + { + fprintf(stderr, "Directory %s: ", dirname); + fatal("Cannot open"); + } + +else do + { + nread = fread( (char *) &entry[0], sizeof(struct direct), 32, dirf) ; + for(i=0; inxtdepblock = nextdbl; + thisdbl->depname = q; + nextdbl = thisdbl; + } + } + } + + } while(nread==32); + +if(endir != 0) *endir = '/'; + +if(cldir) + fclose(dirf); +return(thisdbl); +} + +/* stolen from glob through find */ + +static amatch(s, p) +char *s, *p; +{ + register int cc, scc, k; + int c, lc; + + scc = *s; + lc = 077777; + switch (c = *p) { + + case '[': + k = 0; + while (cc = *++p) { + switch (cc) { + + case ']': + if (k) + return(amatch(++s, ++p)); + else + return(0); + + case '-': + k |= (lc <= scc) & (scc <= (cc=p[1]) ) ; + } + if (scc==(lc=cc)) k++; + } + return(0); + + case '?': + caseq: + if(scc) return(amatch(++s, ++p)); + return(0); + case '*': + return(umatch(s, ++p)); + case 0: + return(!scc); + } + if (c==scc) goto caseq; + return(0); +} + +static umatch(s, p) +char *s, *p; +{ + if(*p==0) return(1); + while(*s) + if (amatch(s++,p)) return(1); + return(0); +} + +#ifdef METERFILE +#include +int meteron = 0; /* default: metering off */ + +meter(file) +char *file; +{ +TIMETYPE tvec; +char *p, *ctime(); +FILE * mout; +struct passwd *pwd, *getpwuid(); + +if(file==0 || meteron==0) return; + +pwd = getpwuid(getuid()); + +time(&tvec); + +if( (mout=fopen(file,"a")) != NULL ) + { + p = ctime(&tvec); + p[16] = '\0'; + fprintf(mout,"User %s, %s\n",pwd->pw_name,p+4); + fclose(mout); + } +} +#endif + + +/* look inside archives for notations a(b) and a((b)) + a(b) is file member b in archive a + a((b)) is entry point _b in object archive a +*/ +#include +#include + +static struct ar_hdr arhead; +FILE *arfd; +long int arpos, arlen; + +static struct exec objhead; + +static struct nlist objentry; + + +TIMETYPE lookarch(filename) +char *filename; +{ +char *p, *q, *send, s[15]; +int i, nc, nsym, objarch; + +for(p = filename; *p!= '(' ; ++p) + ; +*p = '\0'; +openarch(filename); +*p++ = '('; + +if(*p == '(') + { + objarch = YES; + nc = 8; + ++p; + } +else + { + objarch = NO; + nc = 14; + } +send = s + nc; + +for( q = s ; q +struct stat buf; + +stat(f, &buf); +arlen = buf.st_size; + +arfd = fopen(f, "r"); +if(arfd == NULL) + fatal1("cannot open %s", f); +fread( (char *) &word, sizeof(word), 1, arfd); +if(word != ARMAG) + fatal1("%s is not an archive", f); +arpos = 0; +arhead.ar_size = 2 - sizeof(arhead); +} + + + +getarch() +{ +arpos += sizeof(arhead); +arpos += (arhead.ar_size + 1 ) & ~1L; +if(arpos >= arlen) + return(0); +fseek(arfd, arpos, 0); +fread( (char *) &arhead, sizeof(arhead), 1, arfd); +return(1); +} + + +getobj() +{ +long int skip; + +fread( (char *) &objhead, sizeof(objhead), 1, arfd); +if( objhead.a_magic != A_MAGIC1 && + objhead.a_magic != A_MAGIC2 && + objhead.a_magic != A_MAGIC3 && + objhead.a_magic != A_MAGIC4 ) + fatal1("%s is not an object module", arhead.ar_name); +skip = objhead.a_text + objhead.a_data; +#ifdef vax +skip += objhead.a_trsize + objhead.a_drsize; +#else +if(! objhead.a_flag ) + skip *= 2; +#endif +fseek(arfd, skip, 1); +} + + +eqstr(a,b,n) +register char *a, *b; +int n; +{ +register int i; +for(i = 0 ; i < n ; ++i) + if(*a++ != *b++) + return(NO); +return(YES); +} diff --git a/usr/src/cmd/make/gram.y b/usr/src/cmd/make/gram.y new file mode 100644 index 0000000000..a6c3d175fe --- /dev/null +++ b/usr/src/cmd/make/gram.y @@ -0,0 +1,306 @@ +%{#include "defs" +%} + +%term NAME SHELLINE START MACRODEF COLON DOUBLECOLON GREATER +%union + { + struct shblock *yshblock; + struct depblock *ydepblock; + struct nameblock *ynameblock; + } + +%type SHELLINE, shlist, shellist +%type NAME, namelist +%type deplist, dlist + + +%% + +%{ +struct depblock *pp; +FSTATIC struct shblock *prevshp; + +FSTATIC struct nameblock *lefts[NLEFTS]; +struct nameblock *leftp; +FSTATIC int nlefts; + +struct lineblock *lp, *lpp; +FSTATIC struct depblock *prevdep; +FSTATIC int sepc; +%} + + +file: + | file comline + ; + +comline: START + | MACRODEF + | START namelist deplist shellist = { + while( --nlefts >= 0) + { + leftp = lefts[nlefts]; + if(leftp->septype == 0) + leftp->septype = sepc; + else if(leftp->septype != sepc) + fprintf(stderr, "Inconsistent rules lines for `%s'\n", + leftp->namep); + else if(sepc==ALLDEPS && *(leftp->namep)!='.' && $4!=0) + { + for(lp=leftp->linep; lp->nxtlineblock!=0; lp=lp->nxtlineblock) + if(lp->shp) + fprintf(stderr, "Multiple rules lines for `%s'\n", + leftp->namep); + } + + lp = ALLOC(lineblock); + lp->nxtlineblock = NULL; + lp->depp = $3; + lp->shp = $4; + + if(! unequal(leftp->namep, ".SUFFIXES") && $3==0) + leftp->linep = 0; + else if(leftp->linep == 0) + leftp->linep = lp; + else { + for(lpp = leftp->linep; lpp->nxtlineblock; + lpp = lpp->nxtlineblock) ; + if(sepc==ALLDEPS && leftp->namep[0]=='.') + lpp->shp = 0; + lpp->nxtlineblock = lp; + } + } + } + | error + ; + +namelist: NAME = { lefts[0] = $1; nlefts = 1; } + | namelist NAME = { lefts[nlefts++] = $2; + if(nlefts>NLEFTS) fatal("Too many lefts"); } + ; + +deplist: + { + char junk[10]; + sprintf(junk, "%d", yylineno); + fatal1("Must be a separator on rules line %s", junk); + } + | dlist + ; + +dlist: sepchar = { prevdep = 0; $$ = 0; } + | dlist NAME = { + pp = ALLOC(depblock); + pp->nxtdepblock = NULL; + pp->depname = $2; + if(prevdep == 0) $$ = pp; + else prevdep->nxtdepblock = pp; + prevdep = pp; + } + ; + +sepchar: COLON = { sepc = ALLDEPS; } + | DOUBLECOLON = { sepc = SOMEDEPS; } + ; + +shellist: = {$$ = 0; } + | shlist = { $$ = $1; } + ; + +shlist: SHELLINE = { $$ = $1; prevshp = $1; } + | shlist SHELLINE = { $$ = $1; + prevshp->nxtshblock = $2; + prevshp = $2; + } + ; + +%% + +char *zznextc; /* zero if need another line; otherwise points to next char */ +int yylineno; +extern FILE * fin; + +yylex() +{ +register char *p; +register char *q; +char word[INMAX]; + +if(zznextc == 0) + return( nextlin() ); + +while( isspace(*zznextc) ) + ++zznextc; + +if(*zznextc == '\0') + return( nextlin() ); + +if(*zznextc == ':') + { + if(*++zznextc == ':') + { + ++zznextc; + return(DOUBLECOLON); + } + else return(COLON); + } + +if(*zznextc == '>') + { + ++zznextc; + return(GREATER); + } + +if(*zznextc == ';') + return( retsh(zznextc) ); + +p = zznextc; +q = word; + +while( ! ( funny[*p] & TERMINAL) ) + *q++ = *p++; + +if(p != zznextc) + { + *q = '\0'; + if((yylval.ynameblock=srchname(word))==0) + yylval.ynameblock = makename(word); + zznextc = p; + return(NAME); + } + +else { + fprintf(stderr,"Bad character %c (octal %o), line %d", + *zznextc,*zznextc,yylineno); + fatal( (char *) NULL ); + } +return(0); /* never executed */ +} + + + + + +retsh(q) +char *q; +{ +register char *p; +struct shblock *sp; +char *copys(); + +for(p=q+1 ; *p==' '||*p=='\t' ; ++p) ; + +sp = ALLOC(shblock); +sp->nxtshblock = NULL; +sp->shbp = (fin == NULL ? p : copys(p) ); +yylval.yshblock = sp; +zznextc = 0; +return(SHELLINE); +} + +nextlin() +{ +static char yytext[INMAX]; +static char *yytextl = yytext+INMAX; +char *text, templin[INMAX]; +register char c; +register char *p, *t; +char lastch, *lastchp; +extern char **linesptr; +int incom; +int kc; + +again: + + incom = NO; + zznextc = 0; + +if(fin == NULL) + { + if( (text = *linesptr++) == 0) + return(0); + ++yylineno; + } + +else { + for(p = text = yytext ; p I/O System (stdio.h) + +2.16 Removed references to double floats and macro HAVELONGS; + committed to use of long ints for times. +2.17 Corrected metacharacter list in dosys.c. +2.18 Miscellaneous fixes +2.19 Updated files.c to use include file stat.h +2.20 Added -q flag for Mike Lesk +2.21 Added AWK rules and .w suffix to files.c +2.22 Added colon to the list of metacharacters +2.23 Macro substitutions on dependency lines. + Redid argument and macro setting. + Close files before exec'ing. + Print > at beginning of command lines. + No printing of commands beginnng with @. +2.24 Parametrized propt sequence in doname.c (4/1/77) +2.25 Added $? facility +2.26 Fixed bug in macro expansion +2.27 Repaired interrupt handling +2.28 Repaired bug in -n +2.29 Repaired bug in file closing and $? string creation +2.30 Repaired bug in grammar about command lines +2.31 Added -k flag, modified doname.c and defs +2.32 Made "keepgoing" the default, added -S flag, + changed handling of funny characters internally +2.3 Small fixups to interrupt and quit handling. + Changed default back to -k. +2.34 Added .PRECIOUS rule for interrupts +2.35 Added references to include files (due to TLL) +2.36 Fixed bug in lex.c so = permitted in rules on :; line +2.37 Miscellaneous code cleanups +2.38 Sleep one second after each touch in -t mode +2.39 Extended string[] declaration in doname.c +2.40 Permit recursive macro references +2.41 Separated YYLMAX into INMAX and OUTMAX macros, specifying longest + input and output lines respectively. +2.42 Fixed bug involving :: lines without dependents +2.43 Main name is first name that contains a slash or doesn't + begin with a dot +2.44 Fixed bug involving $$ on command line +2.45 Changed files.c to put .f before .e, .r and to use f77 instead of fc. +2.46 Changed dosys.c to eliminate copying and to call execvp. +2.47 Changed files.c to add ".out" suffix and rules. +2.48 Changed misc.c to permit tabs preceding = in macro definition +2.49 Added reference to . Removed -lS references from files.c +2.50 General cleanup to reduce lint messages. (changes in declarations + and in uses of variables) +2.51 Further cleanup making use of new Yacc features. +2.52 +2.53 Changed handling of "touch" +2.54 Fixed bug involving comments in lexical analyzer. +2.55 Ignore commands that begin with a # are comments. +2.56 Added = to list of META characters (to permit shell commands) +2.57 Changed lookarch and getobj to fix bugs. +2.58 Fixed interrupt handling. +2.59 Changed references to sprintf to accomodate new function definition + Also fixed extern declarations. +2.60 Limited the number of open directories. +*/ diff --git a/usr/src/cmd/make/main.c b/usr/src/cmd/make/main.c new file mode 100644 index 0000000000..325c24e220 --- /dev/null +++ b/usr/src/cmd/make/main.c @@ -0,0 +1,370 @@ +# include "defs" +/* +command make to update programs. +Flags: 'd' print out debugging comments + 'p' print out a version of the input graph + 's' silent mode--don't print out commands + 'f' the next argument is the name of the description file; + "makefile" is the default + 'i' ignore error codes from the shell + 'S' stop after any command fails (normally do parallel work) + 'n' don't issue, just print, commands + 't' touch (update time of) files but don't issue command + 'q' don't do anything, but check if object is up to date; + returns exit code 0 if up to date, -1 if not +*/ + +struct nameblock *mainname ; +struct nameblock *firstname; +struct lineblock *sufflist; +struct varblock *firstvar; +struct pattern *firstpat ; +struct opendir *firstod; + +#include +int sigivalue = 0; +int sigqvalue = 0; +int waitpid = 0; + +int dbgflag = NO; +int prtrflag = NO; +int silflag = NO; +int noexflag = NO; +int keepgoing = NO; +int noruleflag = NO; +int touchflag = NO; +int questflag = NO; +int ndocoms = NO; +int ignerr = NO; /* default is to stop on error */ +int okdel = YES; +int inarglist; +#ifdef pwb +char *prompt = ">"; /* other systems -- pick what you want */ +#else +char *prompt = ""; /* other systems -- pick what you want */ +#endif +int nopdir = 0; +char junkname[20]; +char funny[128]; + +main(argc,argv) +int argc; +char *argv[]; +{ +register struct nameblock *p; +int i, j; +int descset, nfargs; +TIMETYPE tjunk; +char c, *s; +static char onechar[2] = "X"; +#ifdef unix +int intrupt(); + + + +#endif + +#ifdef METERFILE +meter(METERFILE); +#endif + +descset = 0; + +funny['\0'] = (META | TERMINAL); +for(s = "=|^();&<>*?[]:$`'\"\\\n" ; *s ; ++s) + funny[*s] |= META; +for(s = "\n\t :;&>|" ; *s ; ++s) + funny[*s] |= TERMINAL; + + +inarglist = 1; +for(i=1; i= argc-1) + fatal("No description argument after -f flag"); + if( rddescf(argv[i+1]) ) + fatal1("Cannot open %s", argv[i+1]); + argv[i+1] = 0; + ++descset; + break; + + default: + onechar[0] = c; /* to make lint happy */ + fatal1("Unknown flag argument %s", onechar); + } + + argv[i] = 0; + } + +if( !descset ) +#ifdef unix + if( rddescf("makefile") ) rddescf("Makefile"); +#endif +#ifdef gcos + rddescf("makefile"); +#endif + +if(prtrflag) printdesc(NO); + +if( srchname(".IGNORE") ) ++ignerr; +if( srchname(".SILENT") ) silflag = 1; +if(p=srchname(".SUFFIXES")) sufflist = p->linep; +if( !sufflist ) fprintf(stderr,"No suffix list.\n"); + +#ifdef unix +sigivalue = (int) signal(SIGINT, SIG_IGN) & 01; +sigqvalue = (int) signal(SIGQUIT, SIG_IGN) & 01; +enbint(intrupt); +#endif + +nfargs = 0; + +for(i=1; ivarval) && exists(p)>0 && !isprecious(p) ) + { + fprintf(stderr, "\n*** %s removed.", p); + unlink(p); + } + +if(junkname[0]) + unlink(junkname); +fprintf(stderr, "\n"); +exit(2); +} + + + + +isprecious(p) +char *p; +{ +register struct lineblock *lp; +register struct depblock *dp; +register struct nameblock *np; + +if(np = srchname(".PRECIOUS")) + for(lp = np->linep ; lp ; lp = lp->nxtlineblock) + for(dp = lp->depp ; dp ; dp = dp->nxtdepblock) + if(! unequal(p, dp->depname->namep)) + return(YES); + +return(NO); +} + + +enbint(k) +int (*k)(); +{ +if(sigivalue == 0) + signal(SIGINT,k); +if(sigqvalue == 0) + signal(SIGQUIT,k); +} +#endif + +extern char *builtin[]; + +char **linesptr = builtin; + +FILE * fin; +int firstrd = 0; + + +rddescf(descfile) +char *descfile; +{ +FILE * k; + +/* read and parse description */ + +if( !firstrd++ ) + { + if( !noruleflag ) + rdd1( (FILE *) NULL); + +#ifdef pwb + { + char *nlog, s[100]; + nlog = logdir(); + if ( (k=fopen( concat(nlog,"/makecomm",s), "r")) != NULL) + rdd1(k); + else if ( (k=fopen( concat(nlog,"/Makecomm",s), "r")) != NULL) + rdd1(k); + + if ( (k=fopen("makecomm", "r")) != NULL) + rdd1(k); + else if ( (k=fopen("Makecomm", "r")) != NULL) + rdd1(k); + } +#endif + + } +if(! unequal(descfile, "-")) + return( rdd1(stdin) ); + +if( (k = fopen(descfile,"r")) != NULL) + return( rdd1(k) ); + +return(1); +} + + + + +rdd1(k) +FILE * k; +{ +extern int yylineno; +extern char *zznextc; + +fin = k; +yylineno = 0; +zznextc = 0; + +if( yyparse() ) + fatal("Description file error"); + +if(fin != NULL) + fclose(fin); + +return(0); +} + +printdesc(prntflag) +int prntflag; +{ +struct nameblock *p; +struct depblock *dp; +struct varblock *vp; +struct opendir *od; +struct shblock *sp; +struct lineblock *lp; + +#ifdef unix +if(prntflag) + { + printf("Open directories:\n"); + for(od = firstod ; od ; od = od->nxtopendir) + printf("\t%d: %s\n", fileno(od->dirfc), od->dirn); + } +#endif + +if(firstvar != 0) printf("Macros:\n"); +for(vp = firstvar; vp ; vp = vp->nxtvarblock) + printf("\t%s = %s\n" , vp->varname , vp->varval); + +for(p = firstname; p; p = p->nxtnameblock) + { + printf("\n\n%s",p->namep); + if(p->linep != 0) printf(":"); + if(prntflag) printf(" done=%d",p->done); + if(p==mainname) printf(" (MAIN NAME)"); + for(lp = p->linep ; lp ; lp = lp->nxtlineblock) + { + if( dp = lp->depp ) + { + printf("\n depends on:"); + for(; dp ; dp = dp->nxtdepblock) + if(dp->depname != 0) + printf(" %s ", dp->depname->namep); + } + + if(sp = lp->shp) + { + printf("\n commands:\n"); + for( ; sp!=0 ; sp = sp->nxtshblock) + printf("\t%s\n", sp->shbp); + } + } + } +printf("\n"); +fflush(stdout); +} diff --git a/usr/src/cmd/make/misc.c b/usr/src/cmd/make/misc.c new file mode 100644 index 0000000000..1c10ab9718 --- /dev/null +++ b/usr/src/cmd/make/misc.c @@ -0,0 +1,337 @@ +#include "defs" + +FSTATIC struct nameblock *hashtab[HASHSIZE]; +FSTATIC int nhashed = 0; + + +/* simple linear hash. hash function is sum of + characters mod hash table size. +*/ +hashloc(s) +char *s; +{ +register int i; +register int hashval; +register char *t; + +hashval = 0; + +for(t=s; *t!='\0' ; ++t) + hashval += *t; + +hashval %= HASHSIZE; + +for(i=hashval; + hashtab[i]!=0 && unequal(s,hashtab[i]->namep); + i = (i+1)%HASHSIZE ) ; + +return(i); +} + + +struct nameblock *srchname(s) +char *s; +{ +return( hashtab[hashloc(s)] ); +} + + + +struct nameblock *makename(s) +char *s; +{ +/* make a fresh copy of the string s */ + +char *copys(); +register struct nameblock *p; + +if(nhashed++ > HASHSIZE-3) + fatal("Hash table overflow"); + +p = ALLOC(nameblock); +p->nxtnameblock = firstname; +p->namep = copys(s); +p->linep = 0; +p->done = 0; +p->septype = 0; +p->modtime = 0; + +firstname = p; +if(mainname == NULL) + if(s[0]!='.' || hasslash(s) ) + mainname = p; + +hashtab[hashloc(s)] = p; + +return(p); +} + + + +hasslash(s) +char *s; +{ +for( ; *s ; ++s) + if(*s == '/') + return(YES); +return(NO); +} + + + +char *copys(s) +register char *s; +{ +char *calloc(); +register char *t, *t0; + +t = t0 = calloc( strlen(s)+1 , sizeof(char) ); +while(*t++ = *s++) + ; +return(t0); +} + + + +char *concat(a,b,c) /* c = concatenation of a and b */ +register char *a,*b; +char *c; +{ +register char *t; +t = c; + +while(*t = *a++) t++; +while(*t++ = *b++); +return(c); +} + + + +suffix(a,b,p) /* is b the suffix of a? if so, set p = prefix */ +register char *a,*b,*p; +{ +char *a0,*b0; +a0 = a; +b0 = b; + +while(*a++); +while(*b++); + +if( (a-a0) < (b-b0) ) return(0); + +while(b>b0) + if(*--a != *--b) return(0); + +while(a0 100) + fatal("infinitely recursive macro?"); +if(a!=0) while(*a) + { + if(*a != '$') *b++ = *a++; + else if(*++a=='\0' || *a=='$') + *b++ = *a++; + else { + s = vname; + if( *a=='(' || *a=='{' ) + { + closer = ( *a=='(' ? ')' : '}'); + ++a; + while(*a == ' ') ++a; + while(*a!=' ' && *a!=closer && *a!='\0') *s++ = *a++; + while(*a!=closer && *a!='\0') ++a; + if(*a == closer) ++a; + } + else *s++ = *a++; + + *s = '\0'; + if( (vbp = varptr(vname)) ->varval != 0) + { + b = subst(vbp->varval, b); + vbp->used = YES; + } + } + } + +*b = '\0'; +--depth; +return(b); +} + + +setvar(v,s) +char *v, *s; +{ +struct varblock *varptr(), *p; + +p = varptr(v); +if(p->noreset == 0) + { + p->varval = s; + p->noreset = inarglist; + if(p->used && unequal(v,"@") && unequal(v,"*") + && unequal(v,"<") && unequal(v,"?") ) + fprintf(stderr, "Warning: %s changed after being used\n",v); + } +} + + +eqsign(a) /*look for arguments with equal signs but not colons */ +char *a; +{ +register char *s, *t; + +while(*a == ' ') ++a; +for(s=a ; *s!='\0' && *s!=':' ; ++s) + if(*s == '=') + { + for(t = a ; *t!='=' && *t!=' ' && *t!='\t' ; ++t ); + *t = '\0'; + + for(++s; *s==' ' || *s=='\t' ; ++s); + setvar(a, copys(s)); + return(YES); + } + +return(NO); +} + + +struct varblock *varptr(v) +char *v; +{ +register struct varblock *vp; + +for(vp = firstvar; vp ; vp = vp->nxtvarblock) + if(! unequal(v , vp->varname)) + return(vp); + +vp = ALLOC(varblock); +vp->nxtvarblock = firstvar; +firstvar = vp; +vp->varname = copys(v); +vp->varval = 0; +return(vp); +} + + +fatal1(s, t) +char *s, *t; +{ +char buf[100]; +fatal( sprintf(buf, s, t) ); +} + + + +fatal(s) +char *s; +{ +if(s) fprintf(stderr, "Make: %s. Stop.\n", s); +else fprintf(stderr, "\nStop.\n"); +#ifdef unix +fflush(stdout); +_exit(1); +#endif +#ifdef gcos +exit(0); +#endif +} + + + +yyerror(s) +char *s; +{ +char buf[50]; +extern int yylineno; + +fatal( sprintf(buf, "line %d: %s", yylineno, s) ); +} + + + +struct chain *appendq(head, tail) +struct chain *head; +char *tail; +{ +register struct chain *p, *q; + +p = ALLOC(chain); +p->datap = tail; + +if(head) + { + for(q = head ; q->nextp ; q = q->nextp) + ; + q->nextp = p; + return(head); + } +else + return(p); +} + + + + + +char *mkqlist(p) +struct chain *p; +{ +register char *qbufp, *s; +static char qbuf[QBUFMAX]; + +if(p == NULL) + { + qbuf[0] = '\0'; + return; + } + +qbufp = qbuf; + +for( ; p ; p = p->nextp) + { + s = p->datap; + if(qbufp+strlen(s) > &qbuf[QBUFMAX-3]) + { + fprintf(stderr, "$? list too long\n"); + break; + } + while (*s) + *qbufp++ = *s++; + *qbufp++ = ' '; + } +*--qbufp = '\0'; +return(qbuf); +} -- 2.20.1