Annotation of coherent/d/bin/make/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:  *     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 != &macroname[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 */

unix.superglobalmegacorp.com

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