Annotation of coherent/d/bin/make/o.make.c, revision 1.1.1.1

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!=&macroname[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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.