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