1: /* static char *sccsid = "@(#)main.c 4.10 (2.11BSD) 98/9/15"; */ 2: 3: #include "defs" 4: 5: /* 6: command make to update programs. 7: Flags: 'd' print out debugging comments 8: 'p' print out a version of the input graph 9: 's' silent mode--don't print out commands 10: 'f' the next argument is the name of the description file; 11: "makefile" is the default 12: 'i' ignore error codes from the shell 13: 'S' stop after any command fails (normally do parallel work) 14: 'n' don't issue, just print, commands 15: 't' touch (update time of) files but don't issue command 16: 'q' don't do anything, but check if object is up to date; 17: returns exit code 0 if up to date, -1 if not 18: 'e' environment variables have precedence over makefiles 19: */ 20: 21: struct nameblock *mainname = NULL; 22: struct nameblock *firstname = NULL; 23: struct lineblock *sufflist = NULL; 24: struct varblock *firstvar = NULL; 25: struct pattern *firstpat = NULL; 26: struct dirhdr *firstod = NULL; 27: 28: #include <signal.h> 29: int sigivalue = 0; 30: int sigqvalue = 0; 31: int waitpid = 0; 32: 33: int dbgflag = NO; 34: int prtrflag = NO; 35: int silflag = NO; 36: int noexflag = NO; 37: int keepgoing = NO; 38: int noruleflag = NO; 39: int touchflag = NO; 40: int questflag = NO; 41: int ndocoms = NO; 42: int ignerr = NO; /* default is to stop on error */ 43: int okdel = YES; 44: int doenvlast = NO; 45: int inarglist; 46: #ifdef pwb 47: char *prompt = ">"; /* other systems -- pick what you want */ 48: #else 49: char *prompt = ""; /* other systems -- pick what you want */ 50: #endif 51: int nopdir = 0; 52: char junkname[20]; 53: char funny[128]; 54: char options[26 + 1] = { '-' }; 55: 56: main(argc,argv) 57: int argc; 58: char *argv[]; 59: { 60: register struct nameblock *p; 61: register int i, j; 62: int descset, nfargs; 63: TIMETYPE tjunk; 64: char c, *s; 65: static char onechar[2] = 'X'; 66: #ifdef unix 67: int intrupt(); 68: #endif 69: char *op = options + 1; 70: 71: 72: #ifdef METERFILE 73: meter(METERFILE); 74: #endif 75: 76: descset = 0; 77: 78: funny['\0'] = (META | TERMINAL); 79: for(s = "=|^();&<>*?[]:$`'\"\\\n" ; *s ; ++s) 80: funny[*s] |= META; 81: for(s = "\n\t :;&>|" ; *s ; ++s) 82: funny[*s] |= TERMINAL; 83: 84: 85: inarglist = 1; 86: for(i=1; i<argc; ++i) 87: if(argv[i]!=0 && argv[i][0]!='-' && eqsign(argv[i])) 88: argv[i] = 0; 89: 90: setvar("$","$"); 91: inarglist = 0; 92: 93: for (i=1; i<argc; ++i) 94: if (argv[i]!=0 && argv[i][0]=='-') { 95: for (j=1 ; (c=argv[i][j])!='\0' ; ++j) { 96: *op++ = c; 97: switch (c) { 98: 99: case 'd': 100: dbgflag = YES; 101: break; 102: 103: case 'p': 104: prtrflag = YES; 105: break; 106: 107: case 's': 108: silflag = YES; 109: break; 110: 111: case 'i': 112: ignerr = YES; 113: break; 114: 115: case 'S': 116: keepgoing = NO; 117: break; 118: 119: case 'k': 120: keepgoing = YES; 121: break; 122: 123: case 'n': 124: noexflag = YES; 125: break; 126: 127: case 'r': 128: noruleflag = YES; 129: break; 130: 131: case 't': 132: touchflag = YES; 133: break; 134: 135: case 'q': 136: questflag = YES; 137: break; 138: 139: case 'f': 140: op--; /* don't pass this one */ 141: if(i >= argc-1) 142: fatal("No description argument after -f flag"); 143: if( rddescf(argv[i+1]) ) 144: fatal1("Cannot open %s", argv[i+1]); 145: argv[i+1] = 0; 146: ++descset; 147: break; 148: 149: case 'e': 150: doenvlast = YES; 151: break; 152: 153: default: 154: onechar[0] = c; /* to make lint happy */ 155: fatal1("Unknown flag argument %s", onechar); 156: } 157: } 158: argv[i] = 0; 159: } 160: 161: *op++ = '\0'; 162: if (strcmp(options, "-") == 0) 163: *options = '\0'; 164: setvar("MFLAGS", options); /* MFLAGS=options to make */ 165: 166: setmachine(); 167: 168: if( !descset ) 169: #ifdef unix 170: if( rddescf("makefile") ) rddescf("Makefile"); 171: #endif 172: #ifdef gcos 173: rddescf("makefile"); 174: #endif 175: 176: if (doenvlast == YES) 177: readenv(); 178: 179: if(prtrflag) printdesc(NO); 180: 181: if( srchname(".IGNORE") ) ++ignerr; 182: if( srchname(".SILENT") ) silflag = 1; 183: if(p=srchname(".SUFFIXES")) sufflist = p->linep; 184: if( !sufflist ) fprintf(stderr,"No suffix list.\n"); 185: 186: #ifdef unix 187: sigivalue = (int) signal(SIGINT, SIG_IGN) & 01; 188: sigqvalue = (int) signal(SIGQUIT, SIG_IGN) & 01; 189: enbint(intrupt); 190: #endif 191: 192: nfargs = 0; 193: 194: for(i=1; i<argc; ++i) 195: if((s=argv[i]) != 0) 196: { 197: if((p=srchname(s)) == 0) 198: { 199: p = makename(s); 200: } 201: ++nfargs; 202: doname(p, 0, &tjunk); 203: if(dbgflag) printdesc(YES); 204: } 205: 206: /* 207: If no file arguments have been encountered, make the first 208: name encountered that doesn't start with a dot 209: */ 210: 211: if(nfargs == 0) 212: if(mainname == 0) 213: fatal("No arguments or description file"); 214: else { 215: doname(mainname, 0, &tjunk); 216: if(dbgflag) printdesc(YES); 217: } 218: 219: exit(0); 220: } 221: 222: #include <sys/stat.h> 223: 224: #ifdef unix 225: intrupt() 226: { 227: struct varblock *varptr(); 228: char *p; 229: TIMETYPE exists(); 230: struct stat sbuf; 231: 232: if(okdel && !noexflag && !touchflag && 233: (p = varptr("@")->varval) && 234: (stat(p, &sbuf) >= 0 && (sbuf.st_mode&S_IFMT) == S_IFREG) && 235: !isprecious(p) ) 236: { 237: fprintf(stderr, "\n*** %s removed.", p); 238: unlink(p); 239: } 240: 241: if(junkname[0]) 242: unlink(junkname); 243: fprintf(stderr, "\n"); 244: exit(2); 245: } 246: 247: 248: 249: 250: isprecious(p) 251: char *p; 252: { 253: register struct lineblock *lp; 254: register struct depblock *dp; 255: register struct nameblock *np; 256: 257: if(np = srchname(".PRECIOUS")) 258: for(lp = np->linep ; lp ; lp = lp->nxtlineblock) 259: for(dp = lp->depp ; dp ; dp = dp->nxtdepblock) 260: if(! unequal(p, dp->depname->namep)) 261: return(YES); 262: 263: return(NO); 264: } 265: 266: 267: enbint(k) 268: int (*k)(); 269: { 270: if(sigivalue == 0) 271: signal(SIGINT,k); 272: if(sigqvalue == 0) 273: signal(SIGQUIT,k); 274: } 275: #endif 276: 277: extern char *builtin[]; 278: 279: char **linesptr = builtin; 280: 281: FILE * fin; 282: int firstrd = 0; 283: 284: 285: rddescf(descfile) 286: char *descfile; 287: { 288: FILE * k; 289: 290: /* read and parse description */ 291: 292: if( !firstrd++ ) 293: { 294: if( !noruleflag ) 295: rdd1( (FILE *) NULL); 296: 297: if (doenvlast == NO) 298: readenv(); 299: 300: #ifdef pwb 301: { 302: char *nlog, s[BUFSIZ]; 303: nlog = logdir(); 304: if ( (k=fopen( concat(nlog,"/makecomm",s), "r")) != NULL) 305: rdd1(k); 306: else if ( (k=fopen( concat(nlog,"/Makecomm",s), "r")) != NULL) 307: rdd1(k); 308: 309: if ( (k=fopen("makecomm", "r")) != NULL) 310: rdd1(k); 311: else if ( (k=fopen("Makecomm", "r")) != NULL) 312: rdd1(k); 313: } 314: #endif 315: 316: } 317: if(! unequal(descfile, "-")) 318: return( rdd1(stdin) ); 319: 320: if( (k = fopen(descfile,"r")) != NULL) 321: return( rdd1(k) ); 322: 323: return(1); 324: } 325: 326: 327: 328: 329: rdd1(k) 330: FILE * k; 331: { 332: extern int yylineno; 333: extern char *zznextc; 334: 335: fin = k; 336: yylineno = 0; 337: zznextc = 0; 338: 339: if( yyparse() ) 340: fatal("Description file error"); 341: 342: if(fin != NULL && fin != stdin) 343: fclose(fin); 344: 345: return(0); 346: } 347: 348: printdesc(prntflag) 349: int prntflag; 350: { 351: struct nameblock *p; 352: struct depblock *dp; 353: struct varblock *vp; 354: struct dirhdr *od; 355: struct shblock *sp; 356: struct lineblock *lp; 357: 358: #ifdef unix 359: if(prntflag) 360: { 361: printf("Open directories:\n"); 362: for (od = firstod; od; od = od->nxtopendir) 363: printf("\t%d: %s\n", od->dirfc->dd_fd, od->dirn); 364: } 365: #endif 366: 367: if(firstvar != 0) printf("Macros:\n"); 368: for(vp = firstvar; vp ; vp = vp->nxtvarblock) 369: printf("\t%s = %s\n" , vp->varname , vp->varval); 370: 371: for(p = firstname; p; p = p->nxtnameblock) 372: { 373: printf("\n\n%s",p->namep); 374: if(p->linep != 0) printf(":"); 375: if(prntflag) printf(" done=%d",p->done); 376: if(p==mainname) printf(" (MAIN NAME)"); 377: for(lp = p->linep ; lp ; lp = lp->nxtlineblock) 378: { 379: if( dp = lp->depp ) 380: { 381: printf("\n depends on:"); 382: for(; dp ; dp = dp->nxtdepblock) 383: if(dp->depname != 0) 384: printf(" %s ", dp->depname->namep); 385: } 386: 387: if(sp = lp->shp) 388: { 389: printf("\n commands:\n"); 390: for( ; sp!=0 ; sp = sp->nxtshblock) 391: printf("\t%s\n", sp->shbp); 392: } 393: } 394: } 395: printf("\n"); 396: fflush(stdout); 397: } 398: 399: readenv() 400: { 401: register char **ep, *p; 402: extern char **environ; 403: 404: for(ep = environ ; *ep ; ++ep) { 405: for (p = *ep; *p; p++) { 406: if (isalnum(*p)) 407: continue; 408: if (*p == '=') { 409: eqsign(*ep); 410: } 411: break; 412: } 413: } 414: } 415: 416: #include <sys/utsname.h> 417: 418: /* 419: * This is done in a function by itself because 'uname()' uses a 640 420: * structure which we do not want permanently allocated on main()'s stack. 421: */ 422: setmachine() 423: { 424: struct utsname foo; 425: 426: if (uname(&foo) < 0) 427: strcpy(foo.machine, "?"); 428: setvar("MACHINE", foo.machine); 429: }