|
|
1.1 root 1: /*
2: * make -- maintain program groups
3: * td 80.09.17
4: * things done:
5: * 20-Oct-82 Made nextc properly translate "\\\n[ ]*" to ' '.
6: * 15-Jan-85 Made portable enough for z-8000, readable enough for
7: * human beings.
8: * 06-Nov-85 Added free(t) to make() to free used space.
9: * 07-Nov-85 Modified docmd() to call varexp() only if 'cmd'
10: * actually contains macros, for efficiency.
11: * 24-Feb-86 Minor fixes by rec to many things. Deferred
12: * macro expansion in actions until needed, deferred
13: * getmdate() until needed, added canonicalization in
14: * archive searches, allowed ${NAME} in actions for
15: * shell to expand, put macro definitions in malloc,
16: * entered environ into macros.
17: * 17-Oct-86 Very minor MS-DOS changes by steve: add _cmdname[],
18: * conditionalize archive code as #if COHERENT || GEMDOS.
19: * 8-Dec-86 Rec makes inpath() search current directory first,
20: * and allows : in dependency list under MSDOS && GEMDOS.
21: * 8-Feb-91 steve: fix comment handling, allow "\#", allow ${VAR}.
22: * Add docmd0() to make $< and $* work in Makefiles.
23: * 12-Feb-91 steve: add $SRCPATH source path searching.
24: * 1-Nov-91 steve: fix bug in nextc() to handle "\n\t\n" correctly
25: * 29-Sep-92 michael: fix problem with defining a rule that also
26: * exists in the ACTIONFILE.
27: * 08-Oct-92 michael: fix problem with making targets with no
28: * specified actions (empty productions).
29: */
30:
31: #include "make.h"
32:
33: #if MSDOS
34: char _cmdname[] = "make";
35: #endif
36:
37: char usage[] = "Usage: make [-deinpqrst] [-f file] [macro=value] [target]";
38: char nospace[] = "out of space";
39: char badmac[] = "bad macro name";
40: char incomp[] = "incomplete line at end of file";
41:
42: /* Command line flags. */
43: int iflag; /* ignore command errors */
44: int sflag; /* don't print command lines */
45: int rflag; /* don't read built-in rules */
46: int nflag; /* don't execute commands */
47: int tflag; /* touch files rather than run commands */
48: int qflag; /* zero exit status if file up to date */
49: int pflag; /* print macro defns, target descriptions */
50: int dflag; /* debug mode -- verbose printout */
51: int eflag; /* make environ macros protected */
52:
53: /* Globals. */
54: unsigned char backup[NBACKUP];
55: int defining; /* nonzero => do not expand macros */
56: int instring; /* Are we in the middle of a string? */
57: SYM *deflt;
58: char *deftarget;
59: FILE *fd;
60: int lastc;
61: int lineno;
62: MACRO *macro;
63: char macroname[NMACRONAME+1];
64: char *mvarval[4]; /* list of macro variable values */
65: int nbackup;
66: time_t now;
67: char *srcpath;
68: struct stat statbuf;
69: SYM *suffixes;
70: SYM *sym;
71: char tokbuf[NTOKBUF];
72: char *token;
73: int toklen;
74: char *tokp;
75: int inactionfile = 0;
76:
77: /* Forward function declarations. */
78: DEP *adddep();
79: SYM *dexists();
80: char *extend();
81: char *fpath();
82: TOKEN *listtoken();
83: SYM *lookup();
84: char *mexists();
85: char *mmalloc();
86: SYM *sexists();
87:
88: /* cry and die */
89: /* VARARGS */
90: die(s) char *s;
91: {
92: fflush(stdout);
93: fprintf(stderr, "make: %r\n", &s);
94: exit(ERROR);
95: }
96:
97: /* print lineno, cry and die */
98: /* VARARGS */
99: err(s) char *s;
100: {
101: fprintf(stderr, "make: %d: %r\n", lineno, &s);
102: exit(ERROR);
103: }
104:
105: /* Malloc nbytes and abort on failure */
106: char *
107: mmalloc(n) int n;
108: {
109: char *p;
110: if (p = malloc(n))
111: return p;
112: err(nospace);
113: }
114:
115: /* read characters from backup (where macros have been expanded) or from
116: * whatever the open file of the moment is. keep track of line #s.
117: */
118: readc()
119: {
120: if (nbackup!=0)
121: return(backup[--nbackup]);
122: if (lastc=='\n')
123: lineno++;
124: lastc=getc(fd);
125: return(lastc);
126: }
127:
128: /* put c into backup[] */
129: putback(c)
130: {
131: if (c==EOF)
132: return;
133: if (nbackup == NBACKUP)
134: err("macro definition too long");
135: backup[nbackup++]=c;
136: }
137:
138: /* put s into backup */
139: unreads(s) register char *s;
140: {
141: register char *t;
142:
143: t = &s[strlen(s)];
144: while (t > s)
145: putback(*--t);
146: }
147:
148: /* return a pointer to the macro definition assigned to macro name s.
149: * return NULL if the macro has not been defined.
150: */
151: char *
152: mexists(s) register char *s;
153: {
154: register MACRO *i;
155:
156: for (i = macro; i != NULL; i=i->next)
157: if (Streq(s, i->name))
158: return (i->value);
159:
160: return (NULL);
161: }
162:
163: /* install macro with name name and value value in macro[]. Overwrite an
164: * existing value if it is not protected.
165: */
166: define(name, value, protected) register char *name, *value; int protected;
167: {
168: register MACRO *i;
169:
170: if (dflag)
171: printf("define %s = %s\n", name, value);
172: for (i = macro; i != NULL; i=i->next)
173: if (Streq(name, i->name)) {
174: if (!i->protected) {
175: free(i->value);
176: i->value = value;
177: i->protected = protected;
178: } else if (dflag)
179: printf("... definition suppressed\n");
180: return;
181: }
182: i = (MACRO *)mmalloc(sizeof(*i));
183: i->name = name;
184: i->value = value;
185: i->protected = protected;
186: i->next = macro;
187: macro = i;
188: }
189:
190: /* Accept single letter user defined macros */
191: ismacro(c) register int c;
192: {
193: return ((c>='0'&&c<='9')
194: || (c>='a'&&c<='z')
195: || (c>='A'&&c<='Z'));
196: }
197:
198: /*
199: * Return the next character from the input file.
200: * Eat comments.
201: * Return EOS for newline not followed by an action.
202: * Return '\n' for newline followed by an action.
203: * If not in a macro definition or action specification,
204: * then expand macro in backup or complain about the name.
205: */
206: nextc()
207: {
208: register char *s;
209: register int c, endc;
210:
211: Again:
212: if ((c = readc()) == '\\') {
213: c = readc();
214: if (c == '\n') { /* escaped newline */
215: while ((c=readc())==' ' || c=='\t')
216: ; /* eat following whitespace */
217: putback(c);
218: return(' ');
219: } else if (c == '#')
220: return c; /* "\#" means literal '#' */
221: putback(c);
222: return '\\';
223: }
224: if ((c=='#') && !instring) {
225: do
226: c = readc();
227: while (c != '\n' && c != EOF);
228: }
229: if ((c=='"') || (c=='\''))
230: {
231: instring = !instring;
232: return c;
233: }
234: if (c == '\n') {
235: instring = 0;
236: Again2:
237: if ((c = readc()) != ' ' && c != '\t') {
238: putback(c);
239: if (c == '#')
240: goto Again; /* "\n# comment" */
241: return EOS; /* no action follows */
242: }
243: do
244: c = readc();
245: while (c == ' ' || c == '\t'); /* skip whitespace */
246: if (c == '\n')
247: goto Again2; /* "\n\t\n" */
248: putback(c);
249: if (c == '#')
250: goto Again; /* "\n\t# comment" */
251: return '\n'; /* action follows */
252: }
253: if (!defining && c=='$'){
254: c=readc();
255: if (c == '(' || c == '{') {
256: endc = (c == '(') ? ')' : '}';
257: s = macroname;
258: while (' ' < (c = readc()) && c < 0177 && c != endc)
259: if (s != ¯oname[NMACRONAME])
260: *s++=c;
261: if (c != endc)
262: err(badmac);
263: *s++ = '\0';
264: } else if (ismacro(c)) {
265: macroname[0]=c;
266: macroname[1]='\0';
267: } else
268: err(badmac);
269: if ((s=mexists(macroname))!=NULL)
270: unreads(s);
271: goto Again;
272: }
273:
274: return(c);
275: }
276:
277: /* Get a block of l0+l1 bytes copy s0 and s1 into it, and return a pointer to
278: * the beginning of the block.
279: */
280: char *
281: extend(s0, l0, s1, l1) char *s0, *s1; int l0, l1;
282: {
283: register char *t;
284:
285: if (s0 == NULL)
286: t = mmalloc(l1);
287: else {
288: if ((t = realloc(s0, l0 + l1)) == NULL)
289: err(nospace);
290: }
291: strncpy(t+l0, s1, l1);
292: return(t);
293: }
294:
295: /* Return 1 if c is EOS, EOF, or one of the characters in s */
296: delim(c, s) register char c; char *s;
297: {
298: return (c == EOS || c == EOF || index(s, c) != NULL);
299: }
300:
301: /* Prepare to copy a new token string into the token buffer; if the old value
302: * in token wasn't saved, tough matzohs.
303: */
304: starttoken()
305: {
306: token=NULL;
307: tokp=tokbuf;
308: toklen=0;
309: }
310:
311: /* Put c in the token buffer; if the buffer is full, copy its contents into
312: * token and start agin at the beginning of the buffer.
313: */
314: addtoken(c)
315: {
316: if (tokp==&tokbuf[NTOKBUF]){
317: token=extend(token, toklen-NTOKBUF, tokbuf, NTOKBUF);
318: tokp=tokbuf;
319: }
320: *tokp++=c;
321: toklen++;
322: }
323:
324: /* mark the end of the token in the buffer and save it in token. */
325: endtoken()
326: {
327: addtoken('\0');
328: token=extend(token, toklen-(tokp-tokbuf), tokbuf, tokp-tokbuf);
329: }
330:
331: /* Install value at the end of the token list which begins with next; return
332: * a pointer to the beginning of the list, which is the one just installed if
333: * next was NULL.
334: */
335: TOKEN *
336: listtoken(value, next) char *value; TOKEN *next;
337: {
338: register TOKEN *p;
339: register TOKEN *t;
340:
341: t=(TOKEN *)mmalloc(sizeof *t); /*Necessaire ou le contraire?*/
342: t->value=value;
343: t->next=NULL;
344: if (next==NULL)
345: return(t);
346: for(p=next;p->next!=NULL;p=p->next);
347: p->next=t;
348: return(next);
349: }
350:
351: /* Free the overhead of a token list */
352: TOKEN *
353: freetoken(t) register TOKEN *t;
354: {
355: register TOKEN *tp;
356: while (t != NULL) {
357: tp = t->next;
358: free(t);
359: t = tp;
360: }
361: return t;
362: }
363:
364: /* Read macros, dependencies, and actions from the file with name file, or
365: * from whatever file is already open. The first string of tokens is saved
366: * in a list pointed to by tp; if it was a macro, the definition goes in
367: * token, and we install it in macro[]; if tp points to a string of targets,
368: * its depedencies go in a list pointed to by dp, and the action to recreate
369: * it in token, and the whole shmear is installed.
370: */
371: input(file) char *file;
372: {
373: TOKEN *tp = NULL, *dp = NULL;
374: register c;
375: char *action;
376: int twocolons;
377:
378: if (file!=NULL && (fd=fopen(file, "r"))==NULL)
379: die("cannot open %s", file);
380: lineno=1;
381: lastc=EOF;
382: for(;;){
383: c=nextc();
384: for(;;){
385: while(c==' ' || c=='\t')
386: c=nextc();
387: if (delim(c, "=:;\n"))
388: break;
389: starttoken();
390: while(!delim(c, " \t\n=:;")){
391: addtoken(c);
392: c=nextc();
393: }
394: endtoken();
395: tp=listtoken(token, tp);
396: }
397: switch(c){
398: case EOF:
399: if (tp!=NULL)
400: err(incomp);
401: fclose(fd);
402: return;
403: case EOS:
404: if (tp==NULL)
405: break;
406: case '\n':
407: err("newline after target or macroname");
408: case ';':
409: err("; after target or macroname");
410: case '=':
411: if (tp==NULL || tp->next!=NULL)
412: err("= without macro name or in token list");
413: defining++;
414: while((c=nextc())==' ' || c=='\t');
415: starttoken();
416: while(c!=EOS && c!=EOF) {
417: addtoken(c);
418: c=nextc();
419: }
420: endtoken();
421: define(tp->value, token, 0);
422: defining=0;
423: break;
424: case ':':
425: if (tp==NULL)
426: err(": without preceding target");
427: c=nextc();
428: if (c==':'){
429: twocolons=1;
430: c=nextc();
431: } else
432: twocolons=0;
433: for(;;){
434: while(c==' ' || c=='\t')
435: c=nextc();
436: if (delim(c, "=:;\n"))
437: break;
438: starttoken();
439: while(!delim(c, TDELIM)){
440: addtoken(c);
441: c=nextc();
442: }
443: endtoken();
444: dp=listtoken(token, dp);
445: }
446: switch(c){
447: #if !MSDOS && !GEMDOS
448: case ':':
449: err("::: or : in or after dependency list");
450: #endif
451: case '=':
452: err("= in or after dependency");
453: case EOF:
454: err(incomp);
455: case ';':
456: case '\n':
457: ++defining;
458: starttoken();
459: while((c=nextc())!=EOS && c!=EOF)
460: addtoken(c);
461: endtoken();
462: defining = 0;
463: action=token;
464: break;
465: case EOS:
466: action=NULL;
467: }
468: install(tp, dp, action, twocolons);
469: }
470: tp = freetoken(tp);
471: dp = freetoken(dp);
472: dp = NULL;
473: }
474: }
475:
476: /* Input with library lookup */
477: inlib(file) char *file;
478: {
479: register char *p, *cp;
480: if ((p = getenv("LIBPATH")) == NULL)
481: p = DEFLIBPATH;
482: cp = path(p, file, AREAD);
483: input(cp ? cp : file);
484: }
485:
486: /* Input first file in list which is found via SRCPATH. */
487: /* Look in current directory first */
488: inpath(file) char *file;
489: {
490: register char **vp, *cp;
491:
492: cp = NULL;
493: for (vp = &file; *vp != NULL; vp += 1)
494: if (access(*vp, AREAD) >= 0) {
495: cp = *vp;
496: break;
497: }
498: if ( ! cp)
499: for (vp = &file; *vp != NULL; vp += 1)
500: if ((cp = path(srcpath, *vp, AREAD)) != NULL)
501: break;
502: input(cp ? cp : file);
503: }
504:
505: /* Return the last modified date of file with name name. If it's an archive,
506: * open it up and read the insertion date of the pertinent member.
507: */
508: time_t
509: getmdate(name) char *name;
510: {
511: #if _I386
512: char *subname;
513: char *lwa;
514: int fd, x;
515: char magic[SARMAG];
516: int size;
517:
518: time_t result;
519: struct ar_hdr hdrbuf;
520: #endif
521:
522: if (stat(name, &statbuf) == 0)
523: return(statbuf.st_mtime);
524:
525:
526: #if _I386
527: subname = index(name, '(');
528: if (subname == NULL)
529: return (0);
530: lwa = &name[strlen(name) - 1];
531: if (*lwa != ')')
532: return (0);
533: *subname = NUL;
534: fd = open(name, READ);
535: *subname++ = '(';
536: if (fd == EOF)
537: return (0);
538: if (read(fd, magic, SARMAG) != SARMAG)
539: {
540: close(fd);
541: return (0);
542: }
543: if (!strcmp(magic, ARMAG)) {
544: close(fd);
545: return (0);
546: }
547: *lwa = NUL;
548: result = 0;
549: while (read(fd, &hdrbuf, sizeof hdrbuf) == sizeof hdrbuf) {
550: if ((strncmp(hdrbuf.ar_name, subname, x = strlen(subname)) == 0)
551: && (hdrbuf.ar_name[x] == '/'))
552: {
553: result = atoi(hdrbuf.ar_date);
554: break;
555: }
556: size = atoi(hdrbuf.ar_size);
557: lseek(fd, size, SEEK_CUR);
558: }
559: *lwa = ')';
560:
561: return (result);
562: #else
563: return 0;
564: #endif
565: }
566:
567:
568: /* Does file name exist? */
569: fexists(name) char *name;
570: {
571: #if 0
572: if (dflag)
573: printf("fexists(%s) = %d getmdate(name) = %d\n", name,
574: getmdate(name) != 0, getmdate(name));
575: #endif
576: return getmdate(name) != 0;
577: }
578:
579: /*
580: * Find name on srcpath.
581: * Return 'name' unchanged if file exists as 'name', 'name' is absolute,
582: * or 'name' not found on sourcepath.
583: * If successful, return pointer to allocated copy.
584: */
585: char *
586: fpath(name) char *name;
587: {
588: register char *s;
589:
590: if (fexists(name)
591: || *name == PATHSEP
592: || srcpath == NULL
593: || (s = path(srcpath, name, AREAD)) == NULL)
594: return name;
595: starttoken();
596: while (*s)
597: addtoken(*s++);
598: endtoken();
599: return token;
600: }
601:
602: /* Return a pointer to the symbol table entry with name "name", NULL if it's
603: * not there.
604: */
605: SYM *
606: sexists(name) register char *name;
607: {
608: register SYM *sp;
609:
610: for(sp=sym;sp!=NULL;sp=sp->next)
611: if (Streq(name, sp->name))
612: return(sp);
613: return(NULL);
614: }
615:
616: /*
617: * Return a pointer to the member of deplist which has name as the last
618: * part of it's pathname, otherwise return NULL.
619: */
620: SYM *
621: dexists(name, dp) register char *name; register DEP *dp;
622: {
623: register char *p;
624: while (dp != NULL) {
625: if ((p = rindex(dp->symbol->name, PATHSEP)) && Streq(name, p+1))
626: return dp->symbol;
627: else
628: dp = dp->next;
629: }
630: return NULL;
631: }
632:
633: /* Look for symbol with name "name" in the symbol table; install it if it's
634: * not there; initialize the action and dependency lists to NULL, the type to
635: * unknown, zero the modification date, and return a pointer to the entry.
636: */
637: SYM *
638: lookup(name) char *name;
639: {
640: register SYM *sp;
641:
642: if ((sp=sexists(name))!=NULL)
643: return(sp);
644: sp = (SYM *)mmalloc(sizeof (*sp)); /*necessary?*/
645: sp->name=name;
646: sp->filename=fpath(name);
647: sp->action=NULL;
648: sp->deplist=NULL;
649: sp->type=T_UNKNOWN;
650: sp->moddate=0;
651: sp->next=sym;
652: sym=sp;
653: return(sp);
654: }
655:
656: /* Install a dependency with symbol having name "name", action "action" in
657: * the end of the dependency list pointed to by next. If s has already
658: * been noted as a file in the dependency list, install action. Return a
659: * pointer to the beginning of the dependency list.
660: */
661: DEP *
662: adddep(name, action, next) char *name, *action; DEP *next;
663: {
664: register DEP *v;
665: register SYM *s;
666: DEP *dp;
667:
668: s=lookup(name);
669: for(v=next;v!=NULL;v=v->next)
670: if (s==v->symbol){
671: if (action != NULL) {
672: if (v->action!=NULL)
673: err("multiple detailed actions for %s",
674: s->name);
675: v->action=action;
676: }
677: return(next);
678: }
679: v = (DEP *)malloc(sizeof (*v)); /*necessary?*/
680: v->symbol=s;
681: v->action=action;
682: v->next=NULL;
683: if (next==NULL)
684: return(v);
685: for(dp=next;dp->next!=NULL;dp=dp->next);
686: dp->next=v;
687: return(next);
688: }
689:
690: /* Do everything for a dependency with left-hand side cons, r.h.s. ante,
691: * action "action", and one or two colons. If cons is the first target in the
692: * file, it becomes the default target. Mark each target in cons as detailed
693: * if twocolons, undetailed if not, and install action in the symbol table
694: * action slot for cons in the latter case. Call adddep() to actually create
695: * the dependency list.
696: */
697: install(cons, ante, action, twocolons) TOKEN *ante, *cons; char *action;
698: {
699: SYM *cp;
700: TOKEN *ap;
701:
702: if (deftarget==NULL && cons->value[0]!='.')
703: deftarget=cons->value;
704: if (dflag){
705: printf("Ante:");
706: ap=ante;
707: while(ap!=NULL){
708: printf(" %s", ap->value);
709: ap=ap->next;
710: }
711: printf("\nCons:");
712: ap=cons;
713: while(ap!=NULL){
714: printf(" %s", ap->value);
715: ap=ap->next;
716: }
717: printf("\n");
718: if (action!=NULL)
719: printf("Action: '%s'\n", action);
720: if (twocolons)
721: printf("two colons\n");
722: }
723: for (; cons != NULL; cons = cons->next) {
724: cp=lookup(cons->value);
725: if (cp==suffixes && ante==NULL)
726: cp->deplist=NULL;
727: else{
728: if (twocolons){
729: if (cp->type==T_UNKNOWN)
730: cp->type=T_DETAIL;
731: else if (cp->type!=T_DETAIL)
732: err("'::' not allowed for %s",
733: cp->name);
734: } else {
735: if (cp->type==T_UNKNOWN)
736: cp->type=T_NODETAIL;
737: else if (cp->type!=T_NODETAIL)
738: err("must use '::' for %s", cp->name);
739: if (action != NULL) {
740: if (cp->action != NULL)
741: {
742: if (!inactionfile)
743: err("multiple action"
744: "s for %s", cp->name);
745: }
746: else
747: cp->action = action;
748: }
749: }
750: for(ap=ante;ap!=NULL;ap=ap->next)
751: cp->deplist=adddep(ap->value,
752: twocolons?action:NULL, cp->deplist);
753: }
754: }
755: }
756:
757: /* Make s; first, make everything s depends on; if the target has detailed
758: * actions, execute any implicit actions associated with it, then execute
759: * the actions associated with the dependencies which are newer than s.
760: * Otherwise, put the dependencies that are newer than s in token ($?),
761: * make s if it doesn't exist, and call docmd.
762: */
763: make(s) register SYM *s;
764: {
765: register DEP *dep;
766: register char *t, *name;
767: int update;
768: int type;
769:
770: if (s->type==T_DONE)
771: return;
772: name = s->filename;
773: if (dflag) {
774: if (s->name == name)
775: printf("Making %s\n", name);
776: else
777: printf("Making %s (file %s)\n", s->name, name);
778: }
779: type=s->type;
780: s->type=T_DONE;
781: s->moddate=getmdate(name);
782: for(dep=s->deplist;dep!=NULL;dep=dep->next)
783: make(dep->symbol);
784: if (type==T_DETAIL){
785: implicit(s, "", 0);
786: for(dep=s->deplist;dep!=NULL;dep=dep->next)
787: if (dep->symbol->moddate>s->moddate)
788: docmd0(s, dep->action, name, dep->symbol->filename);
789: } else {
790: update=0;
791: starttoken();
792: for(dep=s->deplist;dep!=NULL;dep=dep->next){
793: if (dflag)
794: printf("%s time=%ld %s time=%ld\n",
795: dep->symbol->filename, dep->symbol->moddate,
796: name, s->moddate);
797: if (dep->symbol->moddate>s->moddate){
798: update++;
799: addtoken(' ');
800: for(t=dep->symbol->filename;*t;t++)
801: addtoken(*t);
802: }
803: }
804: endtoken();
805: t = token;
806: if (!update && !fexists(name)) {
807: update = TRUE;
808: if (dflag)
809: printf("'%s' made due to non-existence\n",
810: name);
811: }
812: if (s->action==NULL)
813: implicit(s, t, update);
814: else if (update)
815: docmd0(s, s->action, name, t);
816: free(t);
817: }
818: }
819:
820: /*
821: * Expand substitutes the macros in actions and returns the string.
822: */
823: expand(str) register char *str;
824: {
825: register int c;
826: register char *p;
827: int endc;
828:
829: while (c = *str++) {
830: if (c == '$') {
831: c = *str++;
832: switch (c) {
833: case '\0': err(badmac);
834: case '$': addtoken(c); continue;
835: case '@': p = mvarval[0]; break;
836: case '?': p = mvarval[1]; break;
837: case '<': p = mvarval[2]; break;
838: case '*': p = mvarval[3]; break;
839: case '{':
840: case '(':
841: endc = (c == '(') ? ')' : '}';
842: c = '(';
843: p = str;
844: do c = *str++; while (c != 0 && c != endc);
845: if (c == 0)
846: err(badmac);
847: *--str = 0;
848: p = mexists(p);
849: *str++ = endc;
850: break;
851: default:
852: if ( ! ismacro(c))
853: err(badmac);
854: c = *str;
855: *str = 0;
856: p = mexists(str-1);
857: *str = c;
858: break;
859: }
860: if (p != NULL)
861: expand(p);
862: } else
863: addtoken(c);
864: }
865: }
866:
867: /* Like docmd(), except builds its own dependency list and prefix args. */
868: docmd0(s, cmd, at, ques) SYM *s; char *cmd, *at, *ques;
869: {
870: register char *cp;
871: register DEP *dep;
872: char *less, *prefix;
873:
874: /* Build dependency list. */
875: starttoken();
876: for (dep = s->deplist; dep != NULL; dep = dep->next) {
877: addtoken(' ');
878: for (cp = dep->symbol->filename; *cp; cp++)
879: addtoken(*cp);
880: }
881: endtoken();
882: less = token;
883:
884: /* Build prefix. */
885: starttoken();
886: for (cp = s->name; *cp; cp++)
887: addtoken(*cp);
888: endtoken();
889: prefix = token;
890:
891: if ((cp = rindex(prefix, '.')) != NULL)
892: *cp = '\0';
893: docmd(s, cmd, at, ques, less, prefix);
894: free(less);
895: free(prefix);
896: }
897:
898: /* Mark s as modified; if tflag, touch s, otherwise execute the necessary
899: * commands.
900: */
901: docmd(s, cmd, at, ques, less, star) SYM *s; char *cmd, *at, *ques, *less, *star;
902: {
903: if (dflag)
904: printf("ex '%s'\n\t$@='%s'\n\t$?='%s'\n\t$<='%s'\n\t$*='%s'\n",
905: cmd, at, ques, less, star);
906: if (qflag)
907: exit(NOTUTD);
908: s->moddate = now;
909: if (tflag)
910: cmd = "touch $@";
911: if (cmd == NULL)
912: return;
913: mvarval[0] = at;
914: mvarval[1] = ques;
915: mvarval[2] = less;
916: mvarval[3] = star;
917: starttoken();
918: expand(cmd);
919: endtoken();
920: doit(token);
921: free(token);
922: }
923:
924:
925: /* look for '-' (ignore errors) and '@' (silent) in cmd, then execute it
926: * and note the return status.
927: */
928: doit(cmd) register char *cmd;
929: {
930: register char *mark;
931: int sflg, iflg, rstat;
932:
933: if (nflag) {
934: printf("%s\n", cmd);
935: return;
936: }
937: do {
938: mark = index(cmd, '\n');
939: if (mark != NULL)
940: *mark = NUL;
941: if (*cmd == '-') {
942: ++cmd;
943: iflg = TRUE;
944: } else
945: iflg = iflag;
946: if (*cmd == '@') {
947: ++cmd;
948: sflg = TRUE;
949: } else
950: sflg = sflag;
951: if (!sflg)
952: printf("%s\n", cmd);
953: fflush(stdout);
954: rstat = system(cmd);
955: if (rstat != 0 && !iflg)
956: if (sflg)
957: die("%s exited with status %d",
958: cmd, rstat);
959: else
960: die(" exited with status %d", rstat);
961: cmd = mark + 1;
962: } while (mark != NULL && *cmd != NUL);
963: }
964:
965:
966: /* Find the implicit rule to generate obj and execute it. Put the name of
967: * obj up to '.' in prefix, and look for the rest in the dependency list
968: * of .SUFFIXES. Find the file "prefix.foo" upon which obj depends, where
969: * foo appears in the dependency list of suffixes after the suffix of obj.
970: * Then make obj according to the rule from makeactions. If we can't find
971: * any rules, use .DEFAULT, provided we're definite.
972: */
973: implicit(obj, ques, definite) SYM *obj; char *ques; int definite;
974: {
975: register char *s;
976: register DEP *d;
977: char *prefix, *file, *rulename, *suffix;
978: SYM *rule;
979: SYM *subj;
980:
981: if (dflag)
982: printf("Implicit %s (%s)\n", obj->name, ques);
983: if ((suffix=rindex(obj->name, '.')) == NULL
984: || suffix==obj->name) {
985: if (definite)
986: defalt(obj, ques);
987: return;
988: }
989: starttoken();
990: for(s=obj->name; s<suffix; s++)
991: addtoken(*s);
992: endtoken();
993: prefix=token;
994: for(d=suffixes->deplist;d!=NULL;d=d->next)
995: if (Streq(suffix, d->symbol->name))
996: break;
997: if (d==NULL){
998: free(prefix);
999: if (definite)
1000: defalt(obj, ques);
1001: return;
1002: }
1003: while((d=d->next)!=NULL){
1004: starttoken();
1005: for(s=obj->name; s!=suffix; s++)
1006: addtoken(*s);
1007: for(s=d->symbol->name;*s;s++)
1008: addtoken(*s);
1009: endtoken();
1010: file=token;
1011: if ((s = fpath(file)) != file) {
1012: free(file);
1013: file = s;
1014: }
1015: subj=NULL;
1016: if (fexists(file) || (subj=dexists(file, obj->deplist))){
1017: starttoken();
1018: for(s=d->symbol->filename;*s!='\0';s++)
1019: addtoken(*s);
1020: for(s=suffix;*s!='\0';s++)
1021: addtoken(*s);
1022: endtoken();
1023: rulename=token;
1024: if ((rule=sexists(rulename))!=NULL){
1025: if (subj != NULL || (subj=sexists(file))) {
1026: free(file);
1027: file=subj->name;
1028: } else
1029: subj=lookup(file);
1030: make(subj);
1031: if (definite || subj->moddate>obj->moddate)
1032: docmd(obj, rule->action,
1033: obj->name, ques, file, prefix);
1034: free(prefix);
1035: free(rulename);
1036: return;
1037: }
1038: free(rulename);
1039: }
1040: free(file);
1041: }
1042: free(prefix);
1043: if (definite)
1044: defalt(obj, ques);
1045: }
1046:
1047: /*
1048: * Deflt uses the commands associated to '.DEFAULT' to make the object
1049: * 'obj'.
1050: */
1051: defalt(obj, ques) SYM *obj; char *ques;
1052: {
1053: if (deflt == NULL)
1054: {
1055: if (obj->deplist == NULL)
1056: die("do not know how to make %s", obj->name);
1057: }
1058: else
1059: docmd0(obj, deflt->action, obj->name, ques);
1060: }
1061:
1062: main(argc, argv, envp) int argc; char *argv[], *envp[];
1063: {
1064: register char *s, *value;
1065: register char *namesave;
1066: register int c;
1067: int len, numtargets = 0;
1068: char **dtarget;
1069: TOKEN *fp = NULL;
1070: SYM *sp;
1071: DEP *d;
1072: MACRO *mp;
1073:
1074:
1075: if ((dtarget = malloc(argc * sizeof(char *))) == NULL)
1076: err(nospace);
1077:
1078: time(&now);
1079: ++argv;
1080: --argc;
1081:
1082: while (argc > 0)
1083: {
1084: if (argv[0][0] == '-')
1085: {
1086: for (--argc, s = *argv++; *++s != NUL;)
1087: switch (*s) {
1088: case 'd': dflag++; break;
1089: case 'e': eflag++; break;
1090: case 'i': iflag++; break;
1091: case 'n': nflag++; break;
1092: case 'p': pflag++; break;
1093: case 'q': qflag++; break;
1094: case 'r': rflag++; break;
1095: case 's': sflag++; break;
1096: case 't': tflag++; break;
1097: case 'f':
1098: if (--argc < 0)
1099: Usage();
1100: fp=listtoken(*argv++, fp);
1101: break;
1102: default:
1103: Usage();
1104: }
1105: }
1106: else if ((value = index(*argv, '=')) != NULL)
1107: {
1108: s = *argv;
1109: while (*s != ' ' && *s != '\t' && *s != '=')
1110: ++s;
1111: *s = '\0';
1112: define(*argv++, value+1, 1);
1113: --argc;
1114: }
1115: else
1116: {
1117: dtarget[numtargets++] = *argv++;
1118: --argc;
1119: }
1120: }
1121: while (*envp != NULL) {
1122: if ((value = index(*envp, '=')) != NULL
1123: && index(value, '$') == NULL) {
1124: s = *envp;
1125: while ((c=*s) != ' ' && c != '\t' && c != '=')
1126: ++s;
1127:
1128: len = s - *envp;
1129: namesave=mmalloc(len+1);
1130: strncpy(namesave, *envp, len);
1131: namesave[len] = '\0';
1132:
1133: if (eflag)
1134: define(namesave, value+1, 1);
1135: else {
1136: starttoken();
1137: while (*++value) addtoken(*value);
1138: endtoken();
1139: define(namesave, token, 0);
1140: }
1141: }
1142: ++envp;
1143: }
1144: srcpath = mexists("SRCPATH");
1145: suffixes=lookup(".SUFFIXES");
1146: if (!rflag)
1147: inlib(MACROFILE);
1148: deftarget = NULL;
1149: if (fp == NULL)
1150: inpath("makefile", "Makefile", NULL);
1151: else {
1152: fd = stdin;
1153: do {
1154: input( strcmp(fp->value, "-") == 0 ? NULL : fp->value);
1155: fp = fp->next;
1156: } while (fp != NULL);
1157: }
1158: if (!rflag)
1159: {
1160: inactionfile = 1;
1161: inlib(ACTIONFILE);
1162: inactionfile = 0;
1163: }
1164:
1165: if (sexists(".IGNORE") != NULL)
1166: ++iflag;
1167: if (sexists(".SILENT") != NULL)
1168: ++sflag;
1169: deflt = sexists(".DEFAULT");
1170: if (pflag){
1171: if (macro != NULL) {
1172: printf("Macros:\n");
1173: for (mp = macro; mp != NULL; mp=mp->next)
1174: printf("%s=%s\n", mp->name, mp->value);
1175: }
1176: printf("Rules:\n");
1177: for(sp=sym;sp!=NULL;sp=sp->next){
1178: if (sp->type!=T_UNKNOWN){
1179: printf("%s:", sp->name);
1180: if (sp->type==T_DETAIL)
1181: putchar(':');
1182: for(d=sp->deplist;d!=NULL;d=d->next)
1183: printf(" %s", d->symbol->name);
1184: printf("\n");
1185: if (sp->action)
1186: printf("\t%s\n", sp->action);
1187: }
1188: }
1189: }
1190: if (numtargets)
1191:
1192: {
1193: int i;
1194:
1195: for (i=0;i<numtargets;i++)
1196: make(lookup(dtarget[i]));
1197: } else
1198: make(lookup(deftarget));
1199:
1200: exit(ALLOK);
1201: }
1202:
1203: /* Whine about usage and then quit */
1204: Usage()
1205: {
1206: fprintf(stderr, "%s\n", usage);
1207: exit(1);
1208: }
1209:
1210: /* end of make.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.