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