|
|
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.