commit 4625855

shrub  ·  2026-04-26 21:16:18 +0000 UTC
parent 4625855
initial
16 files changed,  +2176, -0
A defs
A gcos.c
A gram.y
A lex.c
A main.c
A misc.c
A pwb.c
A pwinfo
A rc
A readme
+32, -0
 1@@ -0,0 +1,32 @@
 2+# Description file for the Make command
 3+.POSIX:
 4+CC = cc
 5+CFLAGS = -std=c89 -w -O2 -Dpwb -Dunix
 6+YACC   = byacc
 7+
 8+OBJ = version.o main.o doname.o misc.o files.o dosys.o pwb.o gram.o
 9+
10+make: $(OBJ)
11+	$(CC) $(CFLAGS) $(OBJ) -o make
12+
13+$(OBJ): defs
14+
15+gram.o: gram.y lex.c
16+	$(YACC) gram.y
17+	$(CC) $(CFLAGS) -c y.tab.c -o gram.o
18+	rm -f y.tab.c
19+
20+.c.o:
21+	$(CC) -c $(CFLAGS) $<
22+
23+FILES = Makefile pwinfo pr_make.sh rc version.c defs main.c doname.c \
24+	misc.c files.c dosys.c gram.y lex.c gcos.c pwb.c
25+
26+install: make
27+	cp make /bin/pwmake
28+
29+arch:
30+	tar czf make.tar.gz $(FILES)
31+
32+clean:
33+	-rm -f *.o y.tab.c make
A defs
+125, -0
  1@@ -0,0 +1,125 @@
  2+#include <stdio.h>
  3+#include <signal.h>
  4+
  5+#define pwb
  6+
  7+#define SHELLCOM "/bin/sh"
  8+#define TIMETYPE long int
  9+
 10+#ifdef gcos
 11+#undef TIMETYPE
 12+#define TIMETYPE int
 13+#endif
 14+
 15+/* define FSTATIC to be static on systems with C compilers
 16+   supporting file-static; otherwise define it to be null
 17+*/
 18+#define FSTATIC static
 19+
 20+#define HASHSIZE 255
 21+#define NLEFTS 40
 22+#define NCHARS 500
 23+#define NINTS  250
 24+#define YYLMAX 400
 25+
 26+#define ALLDEPS  1
 27+#define SOMEDEPS 2
 28+
 29+
 30+extern int sigivalue;
 31+extern int sigqvalue;
 32+extern int dbgflag;
 33+extern int prtrflag;
 34+extern int silflag;
 35+extern int noexflag;
 36+extern int noruleflag;
 37+extern int touchflag;
 38+extern int questflag;
 39+extern int ndocoms;
 40+extern int ignerr;
 41+extern int okdel;
 42+extern int inarglist;
 43+extern char *prompt;
 44+
 45+
 46+
 47+struct nameblock
 48+	{
 49+	struct nameblock *nextp;
 50+	char *namep;
 51+	struct lineblock *linep;
 52+	int done;
 53+	int septype;
 54+	TIMETYPE modtime;
 55+	};
 56+
 57+extern struct nameblock *mainname ;
 58+extern struct nameblock *firstname;
 59+
 60+struct lineblock
 61+	{
 62+	struct lineblock *nextp;
 63+	struct depblock *depp;
 64+	struct shblock *shp;
 65+	};
 66+extern struct lineblock *sufflist;
 67+
 68+struct depblock
 69+	{
 70+	struct depblock *nextp;
 71+	struct nameblock *depname;
 72+	};
 73+
 74+struct shblock
 75+	{
 76+	struct shblock *nextp;
 77+	char *shbp;
 78+	};
 79+
 80+struct varblock
 81+	{
 82+	struct varblock *nextp;
 83+	char *varname;
 84+	char *varval;
 85+	int noreset:1;
 86+	int used:1;
 87+	};
 88+extern struct varblock *firstvar;
 89+
 90+struct pattern
 91+	{
 92+	struct pattern *nextp;
 93+	char *patval;
 94+	};
 95+extern struct pattern *firstpat;
 96+
 97+struct	opendir
 98+	{
 99+	struct opendir *nextp;
100+	FILE * dirfc;
101+	char *dirn;
102+	};
103+extern struct opendir *firstod;
104+
105+
106+struct chain
107+	{
108+	struct chain *nextp;
109+	char *datap;
110+	};
111+
112+extern void  *intalloc(int);
113+extern char  *copys(char *);
114+extern char  *concat(char *, char *, char *);
115+extern TIMETYPE exists(char *);
116+extern TIMETYPE prestime(void);
117+extern struct nameblock *srchname(char *);
118+extern struct nameblock *makename(char *);
119+extern struct varblock  *varptr(char *);
120+extern struct depblock  *srchdir(char *, int, struct depblock *);
121+extern void   disint(void);
122+extern void   intrupt(int);
123+extern void   enbint(void (*)(int));
124+extern char  *logdir(void);
125+extern void   pexinit(void);
126+extern void   pexec(char *, char **);
+270, -0
  1@@ -0,0 +1,270 @@
  2+#include "defs"
  3+
  4+void docom(struct shblock *);
  5+void expand(struct depblock *);
  6+
  7+/*  BASIC PROCEDURE.  RECURSIVE.  */
  8+
  9+/*
 10+p->done = 0   don't know what to do yet
 11+p->done = 1   file in process of being updated
 12+p->done = 2   file already exists in current state
 13+*/
 14+
 15+TIMETYPE doname(p,reclevel)
 16+struct nameblock *p;
 17+int reclevel;
 18+{
 19+int okdel1;
 20+int didwork;
 21+TIMETYPE td, td1, tdep, ptime, ptime1, prestime(), exists();
 22+struct depblock *q, *qtemp, *srchdir(), *suffp, *suffp1;
 23+struct nameblock *p1, *p2, *srchname();
 24+struct shblock *implcom, *explcom;
 25+struct lineblock *lp, *lp1, *lp2;
 26+char *concat(),sourcename[100],prefix[100],temp[100],concsuff[20];
 27+char *pnamep, *p1namep;
 28+struct chain *qchain;
 29+
 30+if(p == 0) return(0);
 31+
 32+if(dbgflag)
 33+	{
 34+	printf("doname(%s,%d)\n",p->namep,reclevel);
 35+	fflush(stdout);
 36+	}
 37+
 38+if(p->done > 0)  return(p->modtime);
 39+
 40+tdep = 0;
 41+implcom = 0;
 42+explcom = 0;
 43+ptime = exists(p->namep);
 44+ptime1 = 0;
 45+didwork = 0;
 46+p->done = 1;	/* avoid infinite loops */
 47+
 48+qchain = 0;
 49+
 50+/* Expand any names that have embedded metacharaters */
 51+
 52+for(lp = p->linep ; lp!=0 ; lp = lp->nextp)
 53+	for(q=lp->depp ; q!=0 ; q=qtemp )
 54+		{
 55+		qtemp = q->nextp;
 56+		expand(q);
 57+		}
 58+
 59+/* make sure all dependents are up to date */
 60+
 61+for(lp = p->linep ; lp!=0 ; lp = lp->nextp)
 62+	{
 63+	td = 0;
 64+	for(q = lp->depp ; q!=0 ; q=q->nextp)
 65+		{
 66+		td1 = doname(q->depname,reclevel+1);
 67+		if(dbgflag)
 68+		    printf("TIME(%s)=%ld\n", q->depname->namep, td1);
 69+		if(td1 > td) td = td1;
 70+		if(ptime < td1)
 71+			appendq(&qchain, q->depname->namep);
 72+		}
 73+	if(p->septype == SOMEDEPS)
 74+		{
 75+		if(lp->shp!=0)
 76+		     if( ptime<td || (ptime==0 && td==0) )
 77+			{
 78+			okdel1 = okdel;
 79+			okdel = 0;
 80+			setvar("@", p->namep);
 81+			setvar("?", mkqlist(qchain) );
 82+			qchain = 0;
 83+			if( !questflag )
 84+				docom(lp->shp);
 85+			setvar("@", 0);
 86+			okdel = okdel1;
 87+			ptime1 = prestime();
 88+			++didwork;
 89+			}
 90+		}
 91+
 92+	else	{
 93+		if(lp->shp != 0)
 94+			if(explcom)
 95+				fprintf(stderr, "Too many command lines for `%s'\n",
 96+					p->namep);
 97+			else	explcom = lp->shp;
 98+
 99+		if(td > tdep) tdep = td;
100+		}
101+	}
102+
103+/* Look for implicit dependents, using suffix rules */
104+
105+for(lp=sufflist ; lp!=0 ; lp = lp->nextp)
106+    for(suffp = lp->depp ; suffp!=0 ; suffp = suffp->nextp)
107+	{
108+	pnamep = suffp->depname->namep;
109+	if(suffix(p->namep , pnamep , prefix))
110+		{
111+		srchdir( concat(prefix,"*",temp) , 0,0);
112+		for(lp1 = sufflist ; lp1!=0 ; lp1 = lp1->nextp)
113+		    for(suffp1=lp1->depp ; suffp1!=0 ; suffp1 = suffp1->nextp)
114+			{
115+			p1namep = suffp1->depname->namep;
116+			if( (p1=srchname(concat(p1namep, pnamep ,concsuff))) &&
117+			    (p2=srchname(concat(prefix, p1namep ,sourcename))) )
118+				{
119+				td = doname(p2,reclevel+1);
120+				if(ptime < td)
121+					appendq(&qchain, p2->namep);
122+if(dbgflag) printf("TIME(%s)=%ld\n", p2->namep, td);
123+				if(td > tdep) tdep = td;
124+				setvar("*", prefix);
125+				setvar("<", copys(sourcename));
126+				for(lp2=p1->linep ; lp2!=0 ; lp2 = lp2->nextp)
127+					if(implcom = lp2->shp) break;
128+				goto endloop;
129+				}
130+			}
131+		}
132+	}
133+
134+endloop:
135+
136+
137+if(ptime<tdep || (ptime==0 && tdep==0) )
138+	{
139+	ptime = (tdep>0 ? tdep : prestime() );
140+	setvar("@", p->namep);
141+	setvar("?", mkqlist(qchain) );
142+	if(explcom)  docom(explcom);
143+	else if(implcom) docom(implcom);
144+	else if(p->septype == 0)
145+		if(p1=srchname(".DEFAULT"))
146+			{
147+			setvar("<", p->namep);
148+			for(lp2=p1->linep ; lp2!=0 ; lp2 = lp2->nextp)
149+				if(implcom = lp2->shp)
150+					{
151+					docom(implcom);
152+					break;
153+					}
154+			}
155+		else	{
156+			fprintf(stderr," Don't know how to make %s", p->namep);
157+			fatal("");
158+			}
159+
160+	setvar("@", 0);
161+	if( (ptime = exists(p->namep)) == 0)
162+		ptime = prestime();
163+	}
164+
165+else if(!questflag && reclevel==0  &&  didwork==0)
166+	printf("`%s' is up to date.\n", p->namep);
167+
168+if(questflag && reclevel==0)
169+	exit(ndocoms>0 ? -1 : 0);
170+
171+p->done = 2;
172+if(ptime1 > ptime) ptime = ptime1;
173+p->modtime = ptime;
174+return(ptime);
175+}
176+
177+void docom(q)
178+struct shblock *q;
179+{
180+char *s;
181+struct varblock *varptr();
182+int status;
183+int ign, nopr;
184+char string[400];
185+
186+++ndocoms;
187+if(questflag)
188+	return;
189+
190+if(touchflag)
191+	{
192+	s = varptr("@")->varval;
193+	if(!silflag)
194+		printf("touch(%s)\n", s);
195+	if(!noexflag)
196+		touch(s);
197+	}
198+
199+else for( status = 0; q!=0 ; q = q->nextp )
200+	{
201+	subst(q->shbp,string);
202+
203+	ign = ignerr;
204+	nopr = 0;
205+	for(s = string ; *s=='-' || *s=='@' ; ++s)
206+		if(*s == '-')  ign = 1;
207+		else nopr = 1;
208+
209+	status |= docom1(s, ign, nopr);
210+
211+	}
212+}
213+
214+
215+
216+docom1(comstring, nohalt, noprint)
217+char *comstring;
218+int nohalt, noprint;
219+{
220+int status;
221+
222+if(comstring[0] == '\0') return(0);
223+
224+if(!silflag && (!noprint || noexflag) )
225+	{
226+	printf("%s%s\n", (noexflag ? "" : prompt), comstring);
227+	fflush(stdout);
228+	}
229+
230+if(noexflag) return(0);
231+
232+if( status = dosys(comstring, nohalt) )
233+	if (!nohalt)
234+		{
235+		printf("*** Error code %d", status );
236+		fatal(0);
237+		}
238+
239+return(status);
240+}
241+
242+
243+/*
244+   If there are any Shell meta characters in the name,
245+   expand into a list, after searching directory
246+*/
247+
248+void expand(q)
249+struct depblock *q;
250+{
251+register char *s;
252+char *s1;
253+struct depblock *p, *srchdir();
254+
255+s1 = q->depname->namep;
256+for(s=s1 ; ;) switch(*s++)
257+	{
258+	case '\0':
259+		return;
260+
261+	case '*':
262+	case '?':
263+	case '[':
264+		if(p = srchdir(s1 , 1 , q->nextp) )
265+			{
266+			q->nextp = p;
267+			q->depname = 0;
268+			}
269+		return;
270+	}
271+}
+136, -0
  1@@ -0,0 +1,136 @@
  2+# include "defs"
  3+#include <unistd.h>
  4+
  5+dosys(comstring,nohalt)
  6+char *comstring;
  7+int nohalt;
  8+{
  9+int status;
 10+
 11+if(metas(comstring))
 12+	status = doshell(comstring,nohalt);
 13+else	status = doexec(comstring);
 14+
 15+return(status>>8);
 16+}
 17+
 18+
 19+
 20+metas(s)   /* Are there are any  Shell meta-characters? */
 21+char *s;
 22+{
 23+for(;;) switch(*s++)
 24+	{
 25+	case '|':   case '^':
 26+	case '(':   case ')':
 27+	case ';':   case '&':
 28+	case '<':   case '>':
 29+	case '*':   case '?':
 30+	case '[':   case ']':
 31+	case '\\':  case '\n':
 32+	case '\'':  case '"':
 33+	case '`':   case '$':
 34+	case ':':
 35+		return(1);
 36+
 37+	case '\0':
 38+		return(0);
 39+	};
 40+}
 41+
 42+doshell(comstring,nohalt)
 43+char *comstring;
 44+int nohalt;
 45+{
 46+if(fork() == 0)
 47+	{
 48+	enbint(SIG_DFL);
 49+	doclose();
 50+
 51+	if( execl(SHELLCOM, "sh", "-c", comstring, 0) )
 52+		fatal("Couldn't load Shell");
 53+	}
 54+
 55+return( await() );
 56+}
 57+
 58+
 59+
 60+
 61+await()
 62+{
 63+int status;
 64+
 65+disint();
 66+wait(&status);
 67+enbint(intrupt);
 68+return(status);
 69+}
 70+
 71+
 72+
 73+
 74+
 75+
 76+doclose()	/* Close open directory files before exec'ing */
 77+{
 78+register struct opendir *od;
 79+for (od = firstod; od != 0; od = od->nextp)
 80+	if (od->dirfc != NULL)
 81+		fclose(od->dirfc);
 82+}
 83+
 84+
 85+
 86+
 87+doexec(str)
 88+char *str;
 89+{
 90+register char *s, *t;
 91+char *argv[100], pool[1000];
 92+int status;
 93+int argc;
 94+
 95+
 96+argc = 0;
 97+s = pool;
 98+
 99+for(t=str ; *t!='\0' ; )
100+	{
101+	while(*t==' '|| *t=='\t') ++t;
102+	if(*t == '\0') break;
103+
104+	argv[argc++] = s;
105+	while(*t!=' '  && *t!='\t' && *t!='\0') *s++ = *t++;
106+	*s++ = '\0';
107+	}
108+
109+if(argc == 0)   /* no command */
110+	return(-1);
111+argv[argc] = 0;
112+
113+if(fork() == 0)
114+	{
115+	enbint(SIG_DFL);
116+	doclose();
117+
118+	pexec(argv[0], argv);
119+	fprintf(stderr,  "*** Cannot load %s",argv[0]);
120+	fatal("");
121+	}
122+
123+return( await() );
124+}
125+
126+
127+ char junkname[16];
128+
129+touch(s)
130+char *s;
131+{
132+if(junkname[0] == 0)
133+	sprintf(junkname,  "MAKEJUNK%d", getpid() );
134+
135+link(s, junkname);
136+unlink(junkname);
137+}
+236, -0
  1@@ -0,0 +1,236 @@
  2+/* UNIX DEPENDENT PROCEDURES */
  3+
  4+#include <sys/stat.h>
  5+#include <dirent.h>
  6+#include <stdlib.h>
  7+
  8+/* DEFAULT RULES FOR UNIX */
  9+
 10+char *builtin[] =
 11+	{
 12+	".SUFFIXES : .o .c .e .r .f .y .yr .ye .l .s .w .t .h .z .x",
 13+	"YACC=yacc",
 14+	"YACCR=yacc -r",
 15+	"YACCE=yacc -e",
 16+	"YFLAGS=",
 17+	"LEX=lex",
 18+	"LFLAGS=",
 19+	"CC=cc",
 20+	"AS=as -",
 21+	"CFLAGS=",
 22+	"RC=ec",
 23+	"RFLAGS=",
 24+	"EC=ec",
 25+	"EFLAGS=",
 26+	"FFLAGS=",
 27+	"CAWK=awk -c -f",
 28+	"SCOMP=scomp",
 29+	"SCFLAGS=",
 30+	"CMDICT=cmdict",
 31+	"CMFLAGS=",
 32+	".c.o :",
 33+	"\t$(CC) $(CFLAGS) -c $<",
 34+	".e.o .r.o .f.o :",
 35+	"\t$(EC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $<",
 36+	".s.o :",
 37+	"\t$(AS) -o $@ $<",
 38+	".y.o :",
 39+	"\t$(YACC) $(YFLAGS) $<",
 40+	"\t$(CC) $(CFLAGS) -c y.tab.c",
 41+	"\trm y.tab.c",
 42+	"\tmv y.tab.o $@",
 43+	".yr.o:",
 44+	"\t$(YACCR) $(YFLAGS) $<",
 45+	"\t$(RC) $(RFLAGS) -c -2 y.tab.r",
 46+	"\trm y.tab.r",
 47+	"\tmv y.tab.o $@",
 48+	".ye.o :",
 49+	"\t$(YACCE) $(YFLAGS) $<",
 50+	"\t$(EC) $(RFLAGS) -c -2 y.tab.e",
 51+	"\trm y.tab.e",
 52+	"\tmv y.tab.o $@",
 53+	".l.o :",
 54+	"\t$(LEX) $(LFLAGS) $<",
 55+	"\t$(CC) $(CFLAGS) -c lex.yy.c",
 56+	"\trm lex.yy.c",
 57+	"\tmv lex.yy.o $@",
 58+	".y.c :",
 59+	"\t$(YACC) $(YFLAGS) $<",
 60+	"\tmv y.tab.c $@",
 61+	".l.c :",
 62+	"\t$(LEX) $<",
 63+	"\tmv lex.yy.c $@",
 64+	".yr.r:",
 65+	"\t$(YACCR) $(YFLAGS) $<",
 66+	"\tmv y.tab.r $@",
 67+	".ye.e :",
 68+	"\t$(YACCE) $(YFLAGS) $<",
 69+	"\tmv y.tab.e $@",
 70+	".w.c:",
 71+	"\t$(CAWK) $<",
 72+	"\tmv yy.awk.c $@",
 73+	".w.o:",
 74+	"\t$(CAWK) $<",
 75+	"\t$(CC) $(CFLAGS) -c yy.awk.c",
 76+	"\trm yy.awk.c",
 77+	"\tmv yy.awk.o $@",
 78+	".t.o:",
 79+	"\t$(SCOMP) $(SCFLAGS) -c $<",
 80+	".t.c:",
 81+	"\t$(SCOMP) $(SCFLAGS) -t $<",
 82+	".h.z .t.z:",
 83+	"\t$(CMDICT) $(CMFLAGS) $<",
 84+	".h.x .t.x:",
 85+	"\t$(CMDICT) $(CMFLAGS) -x $<",
 86+	0 };
 87+
 88+#include "defs"
 89+
 90+
 91+TIMETYPE exists(filename)
 92+char *filename;
 93+{
 94+struct stat buf;
 95+
 96+if(stat(filename,&buf) < 0)
 97+	return(0);
 98+else	return(buf.st_mtime);
 99+}
100+
101+
102+TIMETYPE prestime()
103+{
104+long int t;
105+time(&t);
106+return(t);
107+}
108+
109+
110+
111+struct depblock *srchdir(pat, mkchain, nextdbl)
112+
113+char *pat; /* pattern to be matched in directory */
114+int mkchain;  /* nonzero if results to be remembered */
115+struct depblock *nextdbl;  /* final value for chain */
116+{
117+DIR *dirf;
118+struct dirent *entry;
119+char *dirname, *dirpref, *endir, *filepat, *p, temp[100];
120+char fullname[100], *copys();
121+struct nameblock *q, *srchname(), *makename();
122+struct depblock *thisdbl;
123+struct pattern *patp;
124+
125+thisdbl = 0;
126+
127+if(mkchain == 0)
128+	for(patp=firstpat ; patp!=0 ; patp = patp->nextp)
129+		if(equals(pat, patp->patval)) return(0);
130+
131+patp = intalloc(sizeof(*patp));
132+patp->nextp = firstpat;
133+firstpat = patp;
134+patp->patval = copys(pat);
135+
136+endir = 0;
137+
138+for(p=pat; *p!='\0'; ++p)
139+	if(*p=='/') endir = p;
140+
141+if(endir==0)
142+	{
143+	dirname = ".";
144+	dirpref = "";
145+	filepat = pat;
146+	}
147+else	{
148+	dirname = pat;
149+	*endir = '\0';
150+	dirpref = concat(dirname, "/", temp);
151+	filepat = endir+1;
152+	}
153+
154+dirf = opendir(dirname);
155+
156+if(dirf == NULL)
157+	{
158+	fprintf(stderr, "Directory %s: ", dirname);
159+	fatal("Cannot open");
160+	}
161+
162+while( (entry = readdir(dirf)) != NULL )
163+	{
164+	if(entry->d_ino == 0) continue;
165+	if( amatch(entry->d_name, filepat) )
166+		{
167+		concat(dirpref, entry->d_name, fullname);
168+		if( (q=srchname(fullname)) == 0)
169+			q = makename(copys(fullname));
170+		if(mkchain)
171+			{
172+			thisdbl = intalloc(sizeof(*thisdbl));
173+			thisdbl->nextp = nextdbl;
174+			thisdbl->depname = q;
175+			nextdbl = thisdbl;
176+			}
177+		}
178+	}
179+
180+closedir(dirf);
181+
182+if(endir != 0)  *endir = '/';
183+
184+return(thisdbl);
185+}
186+
187+/* stolen from glob through find */
188+
189+amatch(s, p)
190+char *s, *p;
191+{
192+	register int cc, scc, k;
193+	int c, lc;
194+
195+	scc = *s;
196+	lc = 077777;
197+	switch (c = *p) {
198+
199+	case '[':
200+		k = 0;
201+		while (cc = *++p) {
202+			switch (cc) {
203+
204+			case ']':
205+				if (k)
206+					return(amatch(++s, ++p));
207+				else
208+					return(0);
209+
210+			case '-':
211+				k |= lc <= scc & scc <= (cc=p[1]);
212+			}
213+			if (scc==(lc=cc)) k++;
214+		}
215+		return(0);
216+
217+	case '?':
218+	caseq:
219+		if(scc) return(amatch(++s, ++p));
220+		return(0);
221+	case '*':
222+		return(umatch(s, ++p));
223+	case 0:
224+		return(!scc);
225+	}
226+	if (c==scc) goto caseq;
227+	return(0);
228+}
229+
230+umatch(s, p)
231+char *s, *p;
232+{
233+	if(*p==0) return(1);
234+	while(*s)
235+		if (amatch(s++,p)) return(1);
236+	return(0);
237+}
A gcos.c
+331, -0
  1@@ -0,0 +1,331 @@
  2+/* GCOS DEPENDENT PROCEDURES */
  3+
  4+
  5+/* DEFAULT RULES FOR GCOS */
  6+
  7+char *builtin[]
  8+	{
  9+	".SUFFIXES : .d .c .y .lib",
 10+	".d.c:",
 11+	"\t./dtgen $<",
 12+	".y.c:",
 13+	"\t./yacc $<",
 14+	"\tcopy y.tab.c; /$@",
 15+	".y.lib:",
 16+	"\t./yacc $<",
 17+	"\t./cc y.tab.c r=$@",
 18+	".c.lib:",
 19+	"\t./cc $< r=$@",
 20+	0 };
 21+
 22+# define MAXCSIZE 500
 23+# define YZERO 60
 24+
 25+int gtcalled 0;
 26+
 27+/* all kinds of static declarations that must be used.. */
 28+
 29+static double day { 64*1000*60*60*24 };  /* length of day in clock ticks */
 30+
 31+struct { int lhs:18, rhs:18; };
 32+struct catb {
 33+	int words[6],
 34+	name1, name2,
 35+	passw1, passw2,
 36+	word10, word11,
 37+	datcreat, datmod,  datused,
 38+	stuff[6],
 39+	jjjj:18, tused:18;
 40+	};
 41+struct { int :3, slot:18; };  /* slot where time from cat. block fits */
 42+
 43+struct catdesc {
 44+	int cat1, cat2, cpass1, cpass2,
 45+	    file1, file2, filep1, filep2,
 46+	    endmark; };
 47+
 48+extern int _q_reg, _a_reg;
 49+
 50+
 51+# define A10(x,y) 10*x + y
 52+
 53+/*	interpret the mm/dd/yy format */
 54+
 55+struct d9 { int	:5, m1:4, :5, m2:4, :9,
 56+		:5, d1:4, :5, d2:4, :9,
 57+		:5, y1:4, :5, y2:4  ;};
 58+
 59+struct d6 { int	:2, m61:4, :2, m62:4,
 60+		:2, d61:4, :2, d62:4,
 61+		:2, y61:4, :2, y62:4; };
 62+
 63+static day6( d6word ){ /* return the day number of a word in bci format */
 64+	int m, y, d;
 65+
 66+	y = A10( d6word.y61, d6word.y62 );
 67+	m = A10( d6word.m61, d6word.m62 );
 68+	d = A10( d6word.d61, d6word.d62 );
 69+
 70+	return( d + 31*( m + 12*(y-YZERO) ) );
 71+	}
 72+
 73+static day9( p ) register int *p; {
 74+
 75+	int m, y, d;
 76+
 77+	y = A10( p->y1, p->y2 );
 78+	m = A10( p->m1, p->m2 );
 79+	d = A10( p->d1, p->d2 );
 80+
 81+	return( d + 31*( m + 12*(y-YZERO) ) );
 82+	}
 83+
 84+
 85+static int dfold( dayno, timeno ){
 86+	int kk;
 87+	kk = ( day*dayno + timeno) / 32768.;
 88+	}
 89+
 90+int prestime(){
 91+	int date[2];
 92+	drldrl( 021, date );
 93+	return( dfold( day9(date), _q_reg ) );
 94+	}
 95+
 96+
 97+
 98+# define DODRL ar[0] = status; ar[1] = &b.cat1; drldrl(30,sp1,sp2); p=ar[0]<<18;
 99+
100+static struct { int fn1, fn2;  int ftm; } fbb[MAXCSIZE];
101+static int catsiz;
102+
103+getcat() {
104+
105+	register i, *p, j;
106+	int asname[4];
107+	struct catdesc b;
108+	int sp1, sp2, temp;
109+	int ar[2], status[2];
110+	int filbuf[380];
111+
112+	gtcalled = 1;
113+
114+	sp1 = ar;
115+	sp1 =>> 18;
116+	sp2 = filbuf;
117+	sp2 =>>18;
118+	sp2.lhs = 19;
119+
120+	b.cat1 = b.cat2 = b.file1 = -1;
121+	b.cpass1 = b.cpass2 = 0202020202020;
122+
123+	DODRL
124+	sp2.lhs++;
125+	for( i=0; p!=0 && i<MAXCSIZE; ++i ){
126+
127+		fbb[i].fn1 = b.file1 = p->name1;
128+		fbb[i].fn2 = b.file2 = p->name2;
129+		b.filep1 = p->passw1;
130+		b.filep2 = p->passw2;
131+		b.endmark = -1;
132+		temp = 0;
133+		temp.slot = p->tused;
134+		fbb[i].ftm = dfold( day6(p->datmod), temp );
135+		DODRL
136+		}
137+	catsiz = i;
138+	}
139+
140+ exists( cp ) char *cp; {
141+	char *s, name[13];
142+	int i, *p, bcd[2];
143+
144+/*
145+   cheat about names with slashes -- try opening;
146+   if it is openable, it exists, and assume it was made
147+   at t=1 (long time ago); otherwise, assume it
148+   does not exist
149+*/
150+
151+for(s=cp ; *s ; ++s)
152+	if(*s == '/')
153+		if(i = copen(cp,'r') < 0)
154+			return(0);
155+		else	{
156+			cclose(i);
157+			return(1);
158+			}
159+
160+if(gtcalled == 0)  getcat();
161+
162+	p = name;
163+	for( i=0; *cp; ++i ) name[i] = *cp++;
164+	while( i<12 ) name[i++] = ' ';
165+	f9to6( *p, bcd[0], 12 );
166+	for ( i=0; i<catsiz; ++i ){
167+		if( fbb[i].fn1 == bcd[0] && fbb[i].fn2 == bcd[1] )
168+			return( fbb[i].ftm );
169+		}
170+	return( 0 );
171+	}
172+
173+
174+#include "defs"
175+
176+static char n13[13];
177+static char *n13end &n13[12];
178+
179+
180+
181+struct depblock *srchdir(pat, mkchain, nextdbl)
182+
183+char *pat; /* pattern to be matched in directory */
184+int mkchain;  /* nonzero if results to be remembered */
185+struct depblock *nextdbl;  /* final value for chain */
186+{
187+int dirf;
188+int i, nread;
189+char *dirname, *dirpref, *endir, *filepat, *p, temp[100];
190+char fullname[100], *p1, *p2, *copys();
191+struct nameblock *q, *srchname(), *makename();
192+struct depblock *thisdbl;
193+struct opendir *od;
194+struct pattern *patp;
195+int *intp1, *intp2;
196+
197+if(gtcalled == 0)  getcat();
198+thisdbl=0;
199+
200+if(mkchain == 0)
201+	for(patp=firstpat ; patp!=0 ; patp = patp->nextp)
202+		if(equals(pat, patp->patval)) return(0);
203+
204+patp = intalloc(sizeof(*patp));
205+patp->nextp = firstpat;
206+firstpat = patp;
207+patp->patval = copys(pat);
208+
209+endir = 0;
210+
211+for(p=pat; *p!='\0'; ++p)
212+	if(*p=='/') endir = p;
213+
214+if(endir==0)
215+	{
216+	dirname = "";
217+	dirpref = "";
218+	filepat = pat;
219+	}
220+else	{
221+fatal("File name has an embedded slash");
222+	dirname = pat;
223+	*endir = '\0';
224+	dirpref = concat(dirname, "/", temp);
225+	filepat = endir+1;
226+	}
227+
228+for(i=0;i<catsiz;++i)
229+	{
230+	intp1 = &fbb[i].fn1;
231+	intp2 = n13;
232+	f6to9(*intp1, *intp2, 12);
233+	for(p1=n13; p1<n13end && *p1!=' ' ; ++p1) 
234+		if('A'<=*p1 && *p1<='Z') *p1 =+ ('a'-'A');
235+		*p1 = '\0';
236+
237+	if( amatch(n13,filepat) )
238+		{
239+		concat(dirpref,n13,fullname);
240+		if( (q=srchname(fullname)) ==0)
241+			q = makename(copys(fullname));
242+		if(mkchain)
243+			{
244+			thisdbl = intalloc(sizeof(*thisdbl));
245+			thisdbl->nextp = nextdbl;
246+			thisdbl->depname = q;
247+			nextdbl = thisdbl;
248+			}
249+		}
250+	}
251+
252+if(endir != 0)  *endir = '/';
253+
254+return(thisdbl);
255+}
256+
257+/* stolen from glob through find */
258+
259+amatch(s, p)
260+char *s, *p;
261+{
262+	register int cc, scc, k;
263+	int c, lc;
264+
265+	scc = *s;
266+	lc = 077777;
267+	switch (c = *p) {
268+
269+	case '[':
270+		k = 0;
271+		while (cc = *++p) {
272+			switch (cc) {
273+
274+			case ']':
275+				if (k)
276+					return(amatch(++s, ++p));
277+				else
278+					return(0);
279+
280+			case '-':
281+				k =| lc <= scc & scc <= (cc=p[1]);
282+			}
283+			if (scc==(lc=cc)) k++;
284+		}
285+		return(0);
286+
287+	case '?':
288+	caseq:
289+		if(scc) return(amatch(++s, ++p));
290+		return(0);
291+	case '*':
292+		return(umatch(s, ++p));
293+	case 0:
294+		return(!scc);
295+	}
296+	if (c==scc) goto caseq;
297+	return(0);
298+}
299+
300+umatch(s, p)
301+char *s, *p;
302+{
303+	if(*p==0) return(1);
304+	while(*s)
305+		if (amatch(s++,p)) return(1);
306+	return(0);
307+}
308+
309+
310+
311+dosys(comstring,nohalt)
312+char *comstring;
313+int nohalt;
314+{
315+char *p;
316+
317+for(p=comstring ; *p!='\0' ; ++p);
318+if( p-comstring > 80)
319+	fatal("Command string longer than 80 characters");
320+
321+system(comstring);
322+
323+return(0);
324+}
325+
326+
327+touch(s)
328+char *s;
329+{
330+fprintf(stderr, "touch not yet implemented on GCOS\n");
331+cexit(2);
332+}
A gram.y
+107, -0
  1@@ -0,0 +1,107 @@
  2+%{
  3+#include "defs"
  4+#define YYSTYPE void *
  5+%}
  6+%term NAME SHELLINE START MACRODEF COLON DOUBLECOLON GREATER
  7+
  8+
  9+%%
 10+
 11+%{
 12+struct depblock *pp;
 13+FSTATIC struct shblock *prevshp;
 14+
 15+FSTATIC struct nameblock *lefts[NLEFTS];
 16+struct nameblock *leftp;
 17+FSTATIC int nlefts;
 18+
 19+struct lineblock *lp, *lpp;
 20+FSTATIC struct depblock *prevdep;
 21+FSTATIC int sepc;
 22+%}
 23+
 24+
 25+file:
 26+	| file comline
 27+	;
 28+
 29+comline:  START
 30+	| MACRODEF
 31+	| START namelist deplist shellist = {
 32+	    while( --nlefts >= 0)
 33+		{
 34+		leftp = lefts[nlefts];
 35+		if(leftp->septype == 0)
 36+			leftp->septype = sepc;
 37+		else if(leftp->septype != sepc)
 38+			fprintf(stderr, "Inconsistent rules lines for `%s'\n",
 39+				leftp->namep);
 40+		else if(sepc==ALLDEPS && *(leftp->namep)!='.' && $4!=0)
 41+			{
 42+			for(lp=leftp->linep; lp->nextp!=0; lp=lp->nextp)
 43+			    if(lp->shp)
 44+				fprintf(stderr, "Multiple rules lines for `%s'\n",
 45+				    leftp->namep);
 46+			}
 47+
 48+		lp = intalloc(sizeof(*lp));
 49+		lp->nextp = 0;
 50+		lp->depp = $3;
 51+		lp->shp = $4;
 52+
 53+		if(equals(leftp->namep, ".SUFFIXES") && $3==0)
 54+			leftp->linep = 0;
 55+		else if(leftp->linep == 0)
 56+			leftp->linep = lp;
 57+		else	{
 58+			for(lpp = leftp->linep; lpp->nextp!=0;
 59+				lpp = lpp->nextp) ;
 60+				if(sepc == ALLDEPS)
 61+					lpp->shp = 0;
 62+			lpp->nextp = lp;
 63+			}
 64+		}
 65+	}
 66+	| error
 67+	;
 68+
 69+namelist: NAME	= { lefts[0] = $1; nlefts = 1; }
 70+	| namelist NAME	= { lefts[nlefts++] = $2;
 71+	    	if(nlefts>NLEFTS) fatal("Too many lefts"); }
 72+	;
 73+
 74+deplist:	= { fatal("Must be a separator on rules line"); }
 75+	| dlist
 76+	;
 77+
 78+dlist:  sepchar	= { prevdep = 0;  $$ = 0; }
 79+	| dlist NAME	= {
 80+			  pp = intalloc(sizeof(*pp));
 81+			  pp->nextp = 0;
 82+			  pp->depname = $2;
 83+			  if(prevdep == 0) $$ = pp;
 84+			  else  prevdep->nextp = pp;
 85+			  prevdep = pp;
 86+			  }
 87+	;
 88+
 89+sepchar:  COLON 	= { sepc = ALLDEPS; }
 90+	| DOUBLECOLON	= { sepc = SOMEDEPS; }
 91+	;
 92+
 93+shellist:	= {$$ = 0; }
 94+	| shlist = { $$ = $1; }
 95+	;
 96+
 97+shlist:	SHELLINE   = { $$ = $1;  prevshp = $1; }
 98+	| shlist SHELLINE = { $$ = $1;
 99+			prevshp->nextp = $2;
100+			prevshp = $2;
101+			}
102+	;
103+
104+%%
105+
106+
107+
108+# include "lex.c"
A lex.c
+183, -0
  1@@ -0,0 +1,183 @@
  2+#define W(x) (x==' ' || x=='\t' || x=='\n')
  3+#define L(x) ('a'<=x&&x<='z')||('A'<=x&&x<='Z')
  4+#define D(x) ('0'<=x&&x<='9')
  5+#define S(x) (x=='/'||x=='.'||x=='?'||x=='*'||x=='['||x=='-'||x==']'||x=='_')
  6+#define NONTERM(x) (x!='\0'&&x!='\n'&&x!=' '&&x!='\t'&&x!=':'&&x!=';'&&x!='&'&&x!='>')
  7+
  8+char *zznextc;	/* zero if need another line; otherwise points to next char */
  9+int yylineno;
 10+extern FILE *fin;
 11+
 12+yylex()
 13+{
 14+register char *p;
 15+register char *q;
 16+char word[YYLMAX];
 17+
 18+if(zznextc == 0)
 19+	return( nextlin() );
 20+
 21+while(W(*zznextc)) ++zznextc;
 22+
 23+if(*zznextc == '\0')
 24+	return( nextlin() );
 25+
 26+if(*zznextc == ':')
 27+	{
 28+	if(*++zznextc == ':')
 29+		{
 30+		++zznextc;
 31+		return(DOUBLECOLON);
 32+		}
 33+	else	return(COLON);
 34+	}
 35+
 36+if(*zznextc == '>')
 37+	{
 38+	++zznextc;
 39+	return(GREATER);
 40+	}
 41+
 42+if(*zznextc == ';')
 43+	return( retsh(zznextc) );
 44+
 45+p = zznextc;
 46+q = word;
 47+
 48+while(NONTERM(*p))
 49+	*q++ = *p++;
 50+
 51+if(p != zznextc)
 52+	{
 53+	*q = '\0';
 54+	if((yylval=srchname(word))==0)
 55+		yylval = makename(word);
 56+	zznextc = p;
 57+	return(NAME);
 58+	}
 59+
 60+else	{
 61+	fprintf(stderr,"Bad character %c (octal %o), line %d",
 62+		*zznextc,*zznextc,yylineno);
 63+	fatal("");
 64+	}
 65+return(0);	/* never executed */
 66+}
 67+
 68+
 69+
 70+
 71+
 72+retsh(q)
 73+char *q;
 74+{
 75+register char *p;
 76+struct shblock *sp;
 77+char *copys();
 78+
 79+for(p=q+1 ; *p==' '||*p=='\t' ; ++p)  ;
 80+
 81+sp = intalloc(sizeof(*sp));
 82+sp->nextp = 0;
 83+sp->shbp = (fin == NULL ? p : copys(p) );
 84+yylval = sp;
 85+zznextc = 0;
 86+return(SHELLINE);
 87+}
 88+
 89+nextlin()
 90+{
 91+static char yytext[YYLMAX];
 92+static char *yytextl = yytext+YYLMAX;
 93+char *text, templin[YYLMAX];
 94+register char c;
 95+register char *p, *t;
 96+char lastch, *lastchp;
 97+extern char **linesptr;
 98+int incom;
 99+
100+incom = 0;
101+zznextc = 0;
102+
103+if(fin == NULL)
104+	{
105+	char *src;
106+	if( (src = *linesptr++) == 0)
107+		return(0);
108+	++yylineno;
109+	for(p=yytext; p<yytextl && (*p = *src++); ++p) ;
110+	*p = '\0';
111+	text = yytext;
112+	}
113+
114+else	{
115+	for(p=yytext ; ; ++p)
116+		{
117+		if(p > yytextl) fatal("line too long");
118+		*p = getc(fin);
119+		if(*p == EOF)
120+			{
121+			*p = '\0';
122+			return(0);
123+			}
124+		else if(*p == ';') ++incom;
125+		else if (*p=='#' && !incom && yytext[0]!='\t')
126+			*p = '\0';
127+		else if (*p == '\n')
128+			{
129+			++yylineno;
130+			if(p==text || p[-1]!='\\') break;
131+			p[-1] = ' ';
132+			while( (*p=getc(fin))=='\t' || *p==' ' || *p=='\n') 
133+				if(*p == '\n') ++yylineno;
134+
135+			if(*p == EOF)
136+				{
137+				*p = '\0';
138+				return(0);
139+				}
140+			}
141+		}
142+	*p = '\0';
143+	text = yytext;
144+	}
145+
146+c = text[0];
147+
148+if(c == '\t')   return( retsh(text) );
149+
150+if(L(c)||D(c)||c==' '||c=='.')
151+	for(p=text+1; *p!='\0'; )
152+		if(*p++ == '=')
153+			{
154+			eqsign(text);
155+			return(MACRODEF);
156+			}
157+
158+/* substtitute for macros on dependency line up to the semicolon if any */
159+
160+for(t = yytext ; *t!='\0' && *t!=';' ; ++t)
161+	;
162+
163+lastchp = t;
164+lastch = *t;
165+*t = '\0';
166+
167+subst(yytext, templin);		/* Substitute for macros on dependency lines */
168+
169+if(lastch)
170+	{
171+	for(t = templin ; *t ; ++t)
172+		;
173+	*t = lastch;
174+	while( *++t = *++lastchp ) ;
175+	}
176+
177+p = templin;
178+t = yytext;
179+while( *t++ = *p++ )
180+	;
181+
182+zznextc = text;
183+return(START);
184+}
A main.c
+329, -0
  1@@ -0,0 +1,329 @@
  2+# include "defs"
  3+#include <unistd.h>
  4+/*
  5+command make to update programs.
  6+Flags:	'd'  print out debugging comments
  7+	'p'  print out a version of the input graph
  8+	's'  silent mode--don't print out commands
  9+	'f'  the next argument is the name of the description file;
 10+	     "makefile" is the default
 11+	'i'   ignore error codes from the shell
 12+	'n'   don't issue, just print, commands
 13+	't'   touch (update time of) files but don't issue command
 14+	'q'   don't do anything, but check if object is up to date;
 15+	      returns exit code 0 if up to date, -1 if not
 16+*/
 17+
 18+struct nameblock *mainname ;
 19+struct nameblock *firstname;
 20+struct lineblock *sufflist;
 21+struct varblock *firstvar;
 22+struct pattern *firstpat ;
 23+struct opendir *firstod;
 24+
 25+int sigivalue = 0;
 26+int sigqvalue = 0;
 27+int dbgflag = 0;
 28+int prtrflag = 0;
 29+int silflag = 0;
 30+int noexflag = 0;
 31+int noruleflag = 0;
 32+int touchflag = 0;
 33+int questflag = 0;
 34+int ndocoms = 0;
 35+int ignerr = 0;    /* default is to stop on error */
 36+int okdel = 1;
 37+int inarglist;
 38+char *prompt = ">";	/* other systems -- pick what you want */
 39+
 40+main(argc,argv)
 41+int argc;
 42+char **argv;
 43+{
 44+struct nameblock *p, *makename(), *srchname();
 45+int i, j;
 46+int descset, nfargs;
 47+char c, *s;
 48+#ifdef unix
 49+void intrupt(int);
 50+#endif
 51+
 52+pexinit();
 53+descset = 0;
 54+
 55+inarglist = 1;
 56+for(i=1; i<argc; ++i)
 57+	if(argv[i]!=0 && argv[i][0]!='-' && eqsign(argv[i]))
 58+		argv[i] = 0;
 59+
 60+setvar("$","$");
 61+inarglist = 0;
 62+
 63+for(i=1; i<argc; ++i)
 64+    if(argv[i]!=0 && argv[i][0]=='-')
 65+	{
 66+	for(j=1 ; (c=argv[i][j])!='\0' ; ++j)  switch(c)
 67+		{
 68+		case 'd':
 69+			dbgflag = 1;
 70+			break;
 71+
 72+		case 'p':
 73+			prtrflag = 1;
 74+			break;
 75+
 76+		case 's':
 77+			silflag = 1;
 78+			break;
 79+
 80+		case 'i':
 81+			ignerr = 1;
 82+			break;
 83+
 84+		case 'n':
 85+			noexflag = 1;
 86+			break;
 87+
 88+		case 'r':
 89+			noruleflag = 1;
 90+			break;
 91+
 92+		case 't':
 93+			touchflag = 1;
 94+			break;
 95+
 96+		case 'q':
 97+			questflag = 1;
 98+			break;
 99+
100+		case 'f':
101+			if(i >= argc-1)
102+			  fatal("No description argument after -f flag");
103+			if( rddescf(argv[i+1]) )
104+				{
105+				fprintf(stderr,"Cannot open %s",argv[i+1]);
106+				fatal("");
107+				}
108+			argv[i+1] = 0;
109+			++descset;
110+			break;
111+
112+		default:
113+			fprintf(stderr,"Unknown flag argument %c", c);
114+			fatal("");
115+		}
116+
117+	argv[i] = 0;
118+	}
119+
120+if( !descset )
121+#ifdef unix
122+	if( rddescf("makefile") )  rddescf("Makefile");
123+#endif
124+#ifdef gcos
125+	rddescf("makefile");
126+#endif
127+
128+if(prtrflag) printdesc(0);
129+
130+if( srchname(".IGNORE") ) ++ignerr;
131+if( srchname(".SILENT") ) silflag = 1;
132+if(p=srchname(".SUFFIXES")) sufflist = p->linep;
133+if( !sufflist ) fprintf(stderr,"No suffix list.\n");
134+
135+#ifdef unix
136+sigivalue = (signal(SIGINT,  SIG_IGN) == SIG_IGN) ? 1 : 0;
137+sigqvalue = (signal(SIGQUIT, SIG_IGN) == SIG_IGN) ? 1 : 0;
138+enbint(intrupt);
139+#endif
140+
141+nfargs = 0;
142+
143+for(i=1; i<argc; ++i)
144+	if((s=argv[i]) != 0)
145+		{
146+		if((p=srchname(s)) == 0)
147+			{
148+			p = makename(s);
149+/*
150+			fprintf(stderr,"Warning: %s not in description.\n",s);
151+*/
152+			}
153+		++nfargs;
154+		doname(p,0);
155+		if(dbgflag) printdesc(1);
156+		}
157+
158+/*
159+If no file arguments have been encountered, make the first
160+name encountered that doesn't start with a dot
161+*/
162+
163+if(nfargs == 0)
164+	if(mainname == 0)
165+		fatal("No arguments or description file");
166+	else	{
167+		doname(mainname,0);
168+		if(dbgflag) printdesc(1);
169+		}
170+
171+exit(0);
172+}
173+
174+
175+
176+#ifdef unix
177+void intrupt(int sig)
178+{
179+struct varblock *varptr();
180+char *p;
181+
182+if( okdel &&  (p=varptr("@")->varval) && exists(p)>0 && !noexflag && !touchflag )
183+	{
184+	fprintf(stderr, "\n***  %s removed.", p);
185+	unlink(p);
186+	}
187+
188+fprintf(stderr, "\n");
189+exit(2);
190+}
191+
192+
193+
194+void disint()
195+{
196+signal(SIGINT,  SIG_IGN);
197+signal(SIGQUIT, SIG_IGN);
198+}
199+
200+
201+
202+void enbint(k)
203+void (*k)(int);
204+{
205+if(sigivalue == 0)
206+	signal(SIGINT,k);
207+if(sigqvalue == 0)
208+	signal(SIGQUIT,k);
209+}
210+#endif
211+
212+extern char *builtin[];
213+
214+char **linesptr = builtin;
215+
216+FILE * fin;
217+int firstrd = 0;
218+
219+
220+rddescf(descfile)
221+char *descfile;
222+{
223+extern int yylineno;
224+extern char *zznextc;
225+FILE * k;
226+
227+/* read and parse description */
228+
229+if( !firstrd++ )
230+	{
231+	if( !noruleflag )
232+		rdd1(NULL);
233+
234+#ifdef pwb
235+		{
236+		char *nlog, s[100];
237+		nlog = logdir();
238+		if ( (k=fopen( concat(nlog,"/makecomm",s), "r")) != NULL)
239+			rdd1(k);
240+		else if ( (k=fopen( concat(nlog,"/Makecomm",s), "r")) != NULL)
241+			rdd1(k);
242+
243+		if ( (k=fopen("makecomm", "r")) != NULL)
244+			rdd1(k);
245+		else if ( (k=fopen("Makecomm", "r")) != NULL)
246+			rdd1(k);
247+		}
248+#endif
249+
250+	}
251+if(equals(descfile, "-"))
252+	return( rdd1(stdin) );
253+
254+if( (k = fopen(descfile,"r")) != NULL)
255+	return( rdd1(k) );
256+
257+return(1);
258+}
259+
260+
261+
262+
263+rdd1(k)
264+FILE * k;
265+{
266+extern int yylineno;
267+extern char *zznextc;
268+fin = k;
269+yylineno = 0;
270+zznextc = 0;
271+
272+if( yyparse() )
273+	fatal("Description file error");
274+
275+if(fin != NULL)
276+	fclose(fin);
277+
278+return(0);
279+}
280+
281+printdesc(prntflag)
282+int prntflag;
283+{
284+struct nameblock *p;
285+struct depblock *dp;
286+struct varblock *vp;
287+struct opendir *od;
288+struct shblock *sp;
289+struct lineblock *lp;
290+
291+#ifdef unix
292+if(prntflag)
293+	{
294+	printf("Open directories:\n");
295+	for(od=firstod; od!=0; od = od->nextp)
296+		printf("\t%d: %s\n", fileno(od->dirfc), od->dirn);
297+	}
298+#endif
299+
300+if(firstvar != 0) printf("Macros:\n");
301+for(vp=firstvar; vp!=0; vp=vp->nextp)
302+	printf("\t%s = %s\n" , vp->varname , vp->varval);
303+
304+for(p=firstname; p!=0; p = p->nextp)
305+	{
306+	printf("\n\n%s",p->namep);
307+	if(p->linep != 0) printf(":");
308+	if(prntflag) printf("  done=%d",p->done);
309+	if(p==mainname) printf("  (MAIN NAME)");
310+	for(lp = p->linep ; lp!=0 ; lp = lp->nextp)
311+		{
312+		if( dp = lp->depp )
313+			{
314+			printf("\n depends on:");
315+			for(; dp!=0 ; dp = dp->nextp)
316+				if(dp->depname != 0)
317+					printf(" %s ", dp->depname->namep);
318+			}
319+
320+		if(sp = lp->shp)
321+			{
322+			printf("\n commands:\n");
323+			for( ; sp!=0 ; sp = sp->nextp)
324+				printf("\t%s\n", sp->shbp);
325+			}
326+		}
327+	}
328+printf("\n");
329+fflush(stdout);
330+}
A misc.c
+313, -0
  1@@ -0,0 +1,313 @@
  2+#include "defs"
  3+#include <stdlib.h>
  4+#include <string.h>
  5+
  6+
  7+FSTATIC char *nextchar = 0;
  8+FSTATIC char *lastchar = 0;
  9+
 10+FSTATIC struct nameblock *hashtab[HASHSIZE];
 11+FSTATIC int nhashed = 0;
 12+
 13+
 14+/* simple linear hash.  hash function is sum of
 15+   characters mod hash table size.
 16+*/
 17+hashloc(s)
 18+char *s;
 19+{
 20+register int i;
 21+register int hashval;
 22+register char *t;
 23+
 24+hashval = 0;
 25+
 26+for(t=s; *t!='\0' ; ++t)
 27+	hashval += *t;
 28+
 29+hashval %= HASHSIZE;
 30+
 31+for(i=hashval;
 32+	hashtab[i]!=0 && equals(s,hashtab[i]->namep)==0;
 33+	i = (i+1)%HASHSIZE ) ;
 34+
 35+return(i);
 36+}
 37+
 38+
 39+struct nameblock *srchname(s)
 40+char *s;
 41+{
 42+return( hashtab[hashloc(s)] );
 43+}
 44+
 45+
 46+
 47+struct nameblock *makename(s)
 48+char *s;
 49+{
 50+/* make a fresh copy of the string s */
 51+
 52+char *copys();
 53+register struct nameblock *p;
 54+
 55+if(nhashed++ > HASHSIZE-3)
 56+	fatal("Hash table overflow");
 57+
 58+p = intalloc(sizeof(*p));
 59+p->nextp = firstname;
 60+p->namep = copys(s);
 61+p->linep = 0;
 62+p->done = 0;
 63+p->septype = 0;
 64+p->modtime = 0;
 65+
 66+firstname = p;
 67+if(mainname==0 && s[0]!='.') mainname = p;
 68+
 69+hashtab[hashloc(s)] = p;
 70+
 71+return(p);
 72+}
 73+
 74+
 75+
 76+char *copys(s)
 77+register char *s;
 78+{
 79+register char *t;
 80+
 81+for(t=s; *t++ ; );
 82+if( (t-s) >= (lastchar-nextchar) )
 83+	{
 84+	if( (nextchar=calloc(NCHARS,sizeof(*t))) == NULL)
 85+		fatal("Cannot allocate memory");
 86+	lastchar = nextchar + NCHARS;
 87+	}
 88+
 89+t = nextchar;
 90+while(*nextchar++ = *s++);
 91+return(t);
 92+}
 93+
 94+equals(a,b)
 95+register char *a,*b;
 96+{
 97+while(*a == *b)
 98+	if(*a == '\0') return(1);
 99+	else {++a; ++b;}
100+
101+return(0);
102+}
103+
104+
105+char *concat(a,b,c)   /* c = concatenation of a and b */
106+register char *a,*b;
107+char *c;
108+{
109+register char *t;
110+t = c;
111+
112+while(*t = *a++) t++;
113+while(*t++ = *b++);
114+return(c);
115+}
116+
117+suffix(a,b,p)  /* is b the suffix of a?  if so, set p = prefix */
118+register char *a,*b,*p;
119+{
120+char *a0,*b0;
121+a0 = a;
122+b0 = b;
123+
124+while(*a++);
125+while(*b++);
126+
127+if( (a-a0) < (b-b0) ) return(0);
128+
129+while(b>b0)
130+	if(*--a != *--b) return(0);
131+
132+while(a0<a) *p++ = *a0++;
133+*p = '\0';
134+
135+return(1);
136+}
137+
138+
139+
140+void *intalloc(n)
141+int n;
142+{
143+void *p;
144+if( (p = calloc(1, n)) == NULL )
145+	fatal("Cannot allocate memory");
146+return(p);
147+}
148+
149+/* copy string a into b, substituting for arguments */
150+char *subst(a,b)
151+register char *a,*b;
152+{
153+register char *s;
154+char vname[100];
155+struct varblock *varptr(), *vbp;
156+char *copstr();
157+char closer;
158+
159+if(a!=0)  while(*a)
160+	{
161+	if(*a != '$') *b++ = *a++;
162+	else if (*++a == '\0') *b++ = *a++;
163+	else	{
164+		s = vname;
165+		if( *a=='(' || *a=='{' )
166+			{
167+			closer = ( *a=='(' ? ')' : '}');
168+			++a;
169+			while(*a == ' ') ++a;
170+			while(*a!=' ' && *a!=closer && *a!='\0') *s++ = *a++;
171+			while(*a!=closer && *a!='\0') ++a;
172+			if(*a == closer) ++a;
173+			}
174+		else	*s++ = *a++;
175+
176+		*s = '\0';
177+		if( (vbp = varptr(vname)) ->varval != 0)
178+			{
179+			b = copstr(b, vbp->varval);
180+			vbp->used = 1;
181+			}
182+		}
183+	}
184+
185+*b++ = '\0';
186+return(b);
187+}
188+
189+/* copy s into t, return the location of the next
190+free character in s */
191+char *copstr(s,t)
192+char *s,*t;
193+{
194+while (*t) *s++ = *t++;
195+return(s);
196+}
197+
198+setvar(v,s)
199+char *v, *s;
200+{
201+struct varblock *varptr(), *p;
202+
203+p = varptr(v);
204+if(p->noreset == 0)
205+	{
206+	p->varval = s;
207+	p->noreset = inarglist;
208+	if(p->used && !equals(v,"@") && !equals(v,"*")
209+	    && !equals(v,"<") && !equals(v,"?") )
210+		fprintf(stderr, "Warning: %s changed after being used\n",v);
211+	}
212+}
213+
214+
215+eqsign(a)   /*look for arguments with equal signs but not colons */
216+char *a;
217+{
218+register char *s, *t;
219+
220+while(*a == ' ') ++a;
221+for(s=a  ;   *s!='\0' && *s!=':'  ; ++s)
222+	if(*s == '=')
223+		{
224+		for(t=a ; *t!='=' && *t!=' ' ;  ++t );
225+		*t = '\0';
226+
227+		for(++s; *s==' ' || *s=='\t' ; ++s);
228+		setvar(a, copys(s));
229+		return(1);
230+		}
231+
232+return(0);
233+}
234+
235+
236+struct varblock *varptr(v)
237+char *v;
238+{
239+register struct varblock *vp;
240+
241+for(vp=firstvar; vp!=0 ; vp = vp->nextp)
242+	if(equals(v , vp->varname)) return(vp);
243+
244+vp = intalloc(sizeof(*vp));
245+vp->nextp = firstvar;
246+firstvar = vp;
247+vp->varname = copys(v);
248+vp->varval = 0;
249+return(vp);
250+}
251+
252+
253+fatal(s)
254+char *s;
255+{
256+if(s) fprintf(stderr, "%s.  Stop.\n", s);
257+else fprintf(stderr, "\nStop.\n");
258+#ifdef unix
259+exit(1);
260+#endif
261+#ifdef gcos
262+exit(0);
263+#endif
264+}
265+
266+
267+
268+yyerror(s)
269+char *s;
270+{
271+char buf[50];
272+extern int yylineno;
273+
274+sprintf(buf, "line %d: %s", yylineno, s);
275+fatal(buf);
276+}
277+
278+
279+
280+appendq(head,tail)
281+struct chain **head;
282+char *tail;
283+{
284+struct chain *p;
285+p = intalloc(sizeof(*p));
286+p->datap = tail;
287+p->nextp = 0;
288+while(*head) head = &(*head)->nextp;
289+*head = p;
290+}
291+
292+
293+
294+
295+char *mkqlist(p)
296+struct chain *p;
297+{
298+register char *qbufp, *s;
299+static char qbuf[300];
300+
301+qbufp = qbuf;
302+
303+for( ; p ; p = p->nextp)
304+	{
305+	s = p->datap;
306+	if (qbufp+strlen(s)+2 >= &qbuf[300])
307+		break;
308+	*qbufp++ = ' ';
309+	while (*s)
310+		*qbufp++ = *s++;
311+	}
312+*qbufp = '\0';
313+return(qbuf);
314+}
+3, -0
1@@ -0,0 +1,3 @@
2+(date; pwd; ls -l) | pr $1
3+if -w gram.c rm  gram.c
4+pr $1 pr_make.sh pwinfo Makefile defs *.[cy]
A pwb.c
+21, -0
 1@@ -0,0 +1,21 @@
 2+/* PWB libPW replacement */
 3+
 4+#include <stdlib.h>
 5+#include <unistd.h>
 6+
 7+void pexinit()
 8+{
 9+}
10+
11+void pexec(path, argv)
12+char *path;
13+char **argv;
14+{
15+execvp(path, argv);
16+}
17+
18+char *logdir()
19+{
20+char *home = getenv("HOME");
21+return(home ? home : ".");
22+}
A pwinfo
+13, -0
 1@@ -0,0 +1,13 @@
 2+Differences between PW make & original make:
 3+-  If exit status is ignored for an executed command,
 4+   a warning is not printed if the command returns a non-zero status.
 5+   The original prints such a warning.
 6+-  When the command is printed prior to execution,
 7+   the command name is prefixed with ">";  this makes the commands stand out.
 8+-  Has builtin suffix rules for LEAP script .t-.o files, and .z-.h files.
 9+-  After reading internal "makerules" file,
10+   but before reading the local "makefile" file,
11+   PW version reads "makecomm"/"Makecomm"in login directory,
12+   and then in local directory.
13+   "makecomm" is useful for defining "common" macro names.
14+-  PW version exec's commands by using pexec(), which uses the .path file.
A rc
+6, -0
1@@ -0,0 +1,6 @@
2+byacc gram.y
3+mv y.tab.c gram.c
4+cc -std=gnu89 -w -O2 -Dpwb -Dunix version.c main.c doname.c misc.c files.c dosys.c pexec.c gram.c -o make
5+rm gram.c
6+strip make
7+echo 'To re-archive, use: "make arch"'
A readme
+9, -0
 1@@ -0,0 +1,9 @@
 2+pw make
 3+--------
 4+
 5+this is the 'make' utility from pwb/unix (1977). i have modified it so it will compile on modern systems.
 6+you can compile it with the 'rc' script or using the 'make' command you probably already have.
 7+you will need the 'byacc' implementation of yacc, or some compatible version. GNU bison will not work,
 8+as it is not backwards compatible with 70's yacc grammars.
 9+
10+
+62, -0
 1@@ -0,0 +1,62 @@
 2+char *xxxvers = "@(#)VERSION 3.1(PWB)     21 APRIL 1977\n" ;
 3+
 4+/*
 5+2.1 4/24/76	Base version
 6+
 7+2.2 4/26/76     Error found by SRB in overriding pattern rules;
 8+		corrected gram.y
 9+
10+2.3 4/27/76	Further correction for overriding pattern rules;
11+		corrected doname.c
12+
13+2.4		Removed .CLEAR name, added .IGNORE.
14+		A .SUFFIXES rule without dependents clears the list
15+
16+2.5		Stripped output
17+
18+2.6		Changed doshell to accomodate new shell.
19+
20+2.7		Following SRB's sugestion, added ${...} as
21+		alternate macro name
22+
23+2.8		Defined macros AS and DTGEN in files.c.
24+
25+2.9		Put in a fix to prevent removal of files
26+		upon interrupt in a  ::  rule.
27+
28+2.10		Fixed bugs involving messages for ::
29+		and closing standard input
30+
31+2.11		Changed time test from <= to <
32+		(equal times are considered in sync)
33+
34+2.12		Installed -t flag (touch and update time of
35+		files rather than issue commands)
36+		Fixed bug in dosys
37+
38+2.13		Fixed lex.c to allow sharps (#) in commands
39+
40+2.14		Added .DEFAULT rule
41+
42+2.15		Changed to <lS> I/O System (stdio.h)
43+
44+2.16		Removed references to double floats and macro HAVELONGS;
45+		committed to use of long ints for times.
46+2.17		Corrected metacharacter list in dosys.c.
47+2.18		Miscellaneous fixes
48+2.19		Updated files.c to use include file stat.h
49+2.20		Added -q flag for Mike Lesk
50+2.21		Added AWK rules and  .w  suffix to  files.c
51+2.22		Added colon to the list of metacharacters
52+2.23		Macro substitutions on dependency lines.
53+		Redid argument and macro setting.
54+		Close files before exec'ing.
55+		Print > at beginning of command lines.
56+		No printing of commands beginnng with @.
57+2.24	Parametrized propt sequence in doname.c (4/1/77)
58+2.25	Added $? facility
59+2.26	Fixed bug in macro expansion
60+2.27	Repaired interrupt handling
61+
62+3.1(PWB)  Use pexec(), add LEAP builtin rules - WDR 4/21/77.
63+*/