Annotation of 43BSDReno/usr.bin/make/targ.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
                      3:  * Copyright (c) 1988, 1989 by Adam de Boor
                      4:  * Copyright (c) 1989 by Berkeley Softworks
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to Berkeley by
                      8:  * Adam de Boor.
                      9:  *
                     10:  * Redistribution and use in source and binary forms are permitted
                     11:  * provided that: (1) source distributions retain this entire copyright
                     12:  * notice and comment, and (2) distributions including binaries display
                     13:  * the following acknowledgement:  ``This product includes software
                     14:  * developed by the University of California, Berkeley and its contributors''
                     15:  * in the documentation or other materials provided with the distribution
                     16:  * and in all advertising materials mentioning features or use of this
                     17:  * software. Neither the name of the University nor the names of its
                     18:  * contributors may be used to endorse or promote products derived
                     19:  * from this software without specific prior written permission.
                     20:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     21:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     22:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     23:  */
                     24: 
                     25: #ifndef lint
                     26: static char sccsid[] = "@(#)targ.c     5.7 (Berkeley) 6/1/90";
                     27: #endif /* not lint */
                     28: 
                     29: /*-
                     30:  * targ.c --
                     31:  *     Functions for maintaining the Lst allTargets. Target nodes are
                     32:  * kept in two structures: a Lst, maintained by the list library, and a
                     33:  * hash table, maintained by the hash library.
                     34:  *
                     35:  * Interface:
                     36:  *     Targ_Init               Initialization procedure.
                     37:  *
                     38:  *     Targ_NewGN              Create a new GNode for the passed target
                     39:  *                             (string). The node is *not* placed in the
                     40:  *                             hash table, though all its fields are
                     41:  *                             initialized.
                     42:  *
                     43:  *     Targ_FindNode           Find the node for a given target, creating
                     44:  *                             and storing it if it doesn't exist and the
                     45:  *                             flags are right (TARG_CREATE)
                     46:  *
                     47:  *     Targ_FindList           Given a list of names, find nodes for all
                     48:  *                             of them. If a name doesn't exist and the
                     49:  *                             TARG_NOCREATE flag was given, an error message
                     50:  *                             is printed. Else, if a name doesn't exist,
                     51:  *                             its node is created.
                     52:  *
                     53:  *     Targ_Ignore             Return TRUE if errors should be ignored when
                     54:  *                             creating the given target.
                     55:  *
                     56:  *     Targ_Silent             Return TRUE if we should be silent when
                     57:  *                             creating the given target.
                     58:  *
                     59:  *     Targ_Precious           Return TRUE if the target is precious and
                     60:  *                             should not be removed if we are interrupted.
                     61:  *
                     62:  * Debugging:
                     63:  *     Targ_PrintGraph         Print out the entire graphm all variables
                     64:  *                             and statistics for the directory cache. Should
                     65:  *                             print something for suffixes, too, but...
                     66:  */
                     67: 
                     68: #include         <stdio.h>
                     69: #include         <time.h>
                     70: #include         "make.h"
                     71: #include         "hash.h"
                     72: 
                     73: static Lst        allTargets;  /* the list of all targets found so far */
                     74: static Hash_Table targets;     /* a hash table of same */
                     75: 
                     76: #define HTSIZE 191             /* initial size of hash table */
                     77: 
                     78: /*-
                     79:  *-----------------------------------------------------------------------
                     80:  * Targ_Init --
                     81:  *     Initialize this module
                     82:  *
                     83:  * Results:
                     84:  *     None
                     85:  *
                     86:  * Side Effects:
                     87:  *     The allTargets list and the targets hash table are initialized
                     88:  *-----------------------------------------------------------------------
                     89:  */
                     90: void
                     91: Targ_Init ()
                     92: {
                     93:     allTargets = Lst_Init (FALSE);
                     94:     Hash_InitTable (&targets, HTSIZE, HASH_STRING_KEYS);
                     95: }
                     96: 
                     97: /*-
                     98:  *-----------------------------------------------------------------------
                     99:  * Targ_NewGN  --
                    100:  *     Create and initialize a new graph node
                    101:  *
                    102:  * Results:
                    103:  *     An initialized graph node with the name field filled with a copy
                    104:  *     of the passed name
                    105:  *
                    106:  * Side Effects:
                    107:  *     None.
                    108:  *-----------------------------------------------------------------------
                    109:  */
                    110: GNode *
                    111: Targ_NewGN (name)
                    112:     char           *name;      /* the name to stick in the new node */
                    113: {
                    114:     register GNode *gn;
                    115: 
                    116:     gn = (GNode *) emalloc (sizeof (GNode));
                    117:     gn->name = strdup (name);
                    118:     gn->path = (char *) 0;
                    119:     if (name[0] == '-' && name[1] == 'l') {
                    120:        gn->type = OP_LIB;
                    121:     } else {
                    122:        gn->type = 0;
                    123:     }
                    124:     gn->unmade =       0;
                    125:     gn->make =                 FALSE;
                    126:     gn->made =                 UNMADE;
                    127:     gn->childMade =    FALSE;
                    128:     gn->mtime = gn->cmtime = 0;
                    129:     gn->iParents =     Lst_Init (FALSE);
                    130:     gn->cohorts =      Lst_Init (FALSE);
                    131:     gn->parents =      Lst_Init (FALSE);
                    132:     gn->children =     Lst_Init (FALSE);
                    133:     gn->successors =   Lst_Init(FALSE);
                    134:     gn->preds =        Lst_Init(FALSE);
                    135:     gn->context =      Lst_Init (FALSE);
                    136:     gn->commands =     Lst_Init (FALSE);
                    137: 
                    138:     return (gn);
                    139: }
                    140: 
                    141: /*-
                    142:  *-----------------------------------------------------------------------
                    143:  * Targ_FindNode  --
                    144:  *     Find a node in the list using the given name for matching
                    145:  *
                    146:  * Results:
                    147:  *     The node in the list if it was. If it wasn't, return NILGNODE of
                    148:  *     flags was TARG_NOCREATE or the newly created and initialized node
                    149:  *     if it was TARG_CREATE
                    150:  *
                    151:  * Side Effects:
                    152:  *     Sometimes a node is created and added to the list
                    153:  *-----------------------------------------------------------------------
                    154:  */
                    155: GNode *
                    156: Targ_FindNode (name, flags)
                    157:     char           *name;      /* the name to find */
                    158:     int             flags;     /* flags governing events when target not
                    159:                                 * found */
                    160: {
                    161:     GNode         *gn;       /* node in that element */
                    162:     Hash_Entry   *he;        /* New or used hash entry for node */
                    163:     Boolean      isNew;      /* Set TRUE if Hash_CreateEntry had to create */
                    164:                              /* an entry for the node */
                    165: 
                    166: 
                    167:     if (flags & TARG_CREATE) {
                    168:        he = Hash_CreateEntry (&targets, name, &isNew);
                    169:        if (isNew) {
                    170:            gn = Targ_NewGN (name);
                    171:            Hash_SetValue (he, gn);
                    172:            (void) Lst_AtEnd (allTargets, (ClientData)gn);
                    173:        }
                    174:     } else {
                    175:        he = Hash_FindEntry (&targets, name);
                    176:     }
                    177: 
                    178:     if (he == (Hash_Entry *) NULL) {
                    179:        return (NILGNODE);
                    180:     } else {
                    181:        return ((GNode *) Hash_GetValue (he));
                    182:     }
                    183: }
                    184: 
                    185: /*-
                    186:  *-----------------------------------------------------------------------
                    187:  * Targ_FindList --
                    188:  *     Make a complete list of GNodes from the given list of names 
                    189:  *
                    190:  * Results:
                    191:  *     A complete list of graph nodes corresponding to all instances of all
                    192:  *     the names in names. 
                    193:  *
                    194:  * Side Effects:
                    195:  *     If flags is TARG_CREATE, nodes will be created for all names in
                    196:  *     names which do not yet have graph nodes. If flags is TARG_NOCREATE,
                    197:  *     an error message will be printed for each name which can't be found.
                    198:  * -----------------------------------------------------------------------
                    199:  */
                    200: Lst
                    201: Targ_FindList (names, flags)
                    202:     Lst                   names;       /* list of names to find */
                    203:     int            flags;      /* flags used if no node is found for a given
                    204:                                 * name */
                    205: {
                    206:     Lst            nodes;      /* result list */
                    207:     register LstNode  ln;              /* name list element */
                    208:     register GNode *gn;                /* node in tLn */
                    209:     char         *name;
                    210: 
                    211:     nodes = Lst_Init (FALSE);
                    212: 
                    213:     if (Lst_Open (names) == FAILURE) {
                    214:        return (nodes);
                    215:     }
                    216:     while ((ln = Lst_Next (names)) != NILLNODE) {
                    217:        name = (char *)Lst_Datum(ln);
                    218:        gn = Targ_FindNode (name, flags);
                    219:        if (gn != NILGNODE) {
                    220:            /*
                    221:             * Note: Lst_AtEnd must come before the Lst_Concat so the nodes
                    222:             * are added to the list in the order in which they were
                    223:             * encountered in the makefile.
                    224:             */
                    225:            (void) Lst_AtEnd (nodes, (ClientData)gn);
                    226:            if (gn->type & OP_DOUBLEDEP) {
                    227:                (void)Lst_Concat (nodes, gn->cohorts, LST_CONCNEW);
                    228:            }
                    229:        } else if (flags == TARG_NOCREATE) {
                    230:            Error ("\"%s\" -- target unknown.", name);
                    231:        }
                    232:     }
                    233:     Lst_Close (names);
                    234:     return (nodes);
                    235: }
                    236: 
                    237: /*-
                    238:  *-----------------------------------------------------------------------
                    239:  * Targ_Ignore  --
                    240:  *     Return true if should ignore errors when creating gn
                    241:  *
                    242:  * Results:
                    243:  *     TRUE if should ignore errors
                    244:  *
                    245:  * Side Effects:
                    246:  *     None
                    247:  *-----------------------------------------------------------------------
                    248:  */
                    249: Boolean
                    250: Targ_Ignore (gn)
                    251:     GNode          *gn;                /* node to check for */
                    252: {
                    253:     if (ignoreErrors || gn->type & OP_IGNORE) {
                    254:        return (TRUE);
                    255:     } else {
                    256:        return (FALSE);
                    257:     }
                    258: }
                    259: 
                    260: /*-
                    261:  *-----------------------------------------------------------------------
                    262:  * Targ_Silent  --
                    263:  *     Return true if be silent when creating gn
                    264:  *
                    265:  * Results:
                    266:  *     TRUE if should be silent
                    267:  *
                    268:  * Side Effects:
                    269:  *     None
                    270:  *-----------------------------------------------------------------------
                    271:  */
                    272: Boolean
                    273: Targ_Silent (gn)
                    274:     GNode          *gn;                /* node to check for */
                    275: {
                    276:     if (beSilent || gn->type & OP_SILENT) {
                    277:        return (TRUE);
                    278:     } else {
                    279:        return (FALSE);
                    280:     }
                    281: }
                    282: 
                    283: /*-
                    284:  *-----------------------------------------------------------------------
                    285:  * Targ_Precious --
                    286:  *     See if the given target is precious
                    287:  *
                    288:  * Results:
                    289:  *     TRUE if it is precious. FALSE otherwise
                    290:  *
                    291:  * Side Effects:
                    292:  *     None
                    293:  *-----------------------------------------------------------------------
                    294:  */
                    295: Boolean
                    296: Targ_Precious (gn)
                    297:     GNode          *gn;                /* the node to check */
                    298: {
                    299:     if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP))) {
                    300:        return (TRUE);
                    301:     } else {
                    302:        return (FALSE);
                    303:     }
                    304: }
                    305: 
                    306: /******************* DEBUG INFO PRINTING ****************/
                    307: 
                    308: static GNode     *mainTarg;    /* the main target, as set by Targ_SetMain */
                    309: /*- 
                    310:  *-----------------------------------------------------------------------
                    311:  * Targ_SetMain --
                    312:  *     Set our idea of the main target we'll be creating. Used for
                    313:  *     debugging output.
                    314:  *
                    315:  * Results:
                    316:  *     None.
                    317:  *
                    318:  * Side Effects:
                    319:  *     "mainTarg" is set to the main target's node.
                    320:  *-----------------------------------------------------------------------
                    321:  */
                    322: void
                    323: Targ_SetMain (gn)
                    324:     GNode   *gn;       /* The main target we'll create */
                    325: {
                    326:     mainTarg = gn;
                    327: }
                    328: 
                    329: static int
                    330: TargPrintName (gn, ppath)
                    331:     GNode          *gn;
                    332:     int                    ppath;
                    333: {
                    334:     printf ("%s ", gn->name);
                    335: #ifdef notdef
                    336:     if (ppath) {
                    337:        if (gn->path) {
                    338:            printf ("[%s]  ", gn->path);
                    339:        }
                    340:        if (gn == mainTarg) {
                    341:            printf ("(MAIN NAME)  ");
                    342:        }
                    343:     }
                    344: #endif notdef
                    345:     return (0);
                    346: }
                    347: 
                    348: 
                    349: int
                    350: Targ_PrintCmd (cmd)
                    351:     char           *cmd;
                    352: {
                    353:     printf ("\t%s\n", cmd);
                    354:     return (0);
                    355: }
                    356: 
                    357: /*-
                    358:  *-----------------------------------------------------------------------
                    359:  * Targ_FmtTime --
                    360:  *     Format a modification time in some reasonable way and return it.
                    361:  *
                    362:  * Results:
                    363:  *     The time reformatted.
                    364:  *
                    365:  * Side Effects:
                    366:  *     The time is placed in a static area, so it is overwritten
                    367:  *     with each call.
                    368:  *
                    369:  *-----------------------------------------------------------------------
                    370:  */
                    371: char *
                    372: Targ_FmtTime (time)
                    373:     int    time;
                    374: {
                    375:     struct tm          *parts;
                    376:     static char                buf[40];
                    377:     static char                *months[] = {
                    378:        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                    379:        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
                    380:     };
                    381: 
                    382:     parts = localtime(&time);
                    383: 
                    384:     sprintf (buf, "%d:%02d:%02d %s %d, 19%d",
                    385:             parts->tm_hour, parts->tm_min, parts->tm_sec,
                    386:             months[parts->tm_mon], parts->tm_mday, parts->tm_year);
                    387:     return(buf);
                    388: }
                    389:     
                    390: /*-
                    391:  *-----------------------------------------------------------------------
                    392:  * Targ_PrintType --
                    393:  *     Print out a type field giving only those attributes the user can
                    394:  *     set.
                    395:  *
                    396:  * Results:
                    397:  *
                    398:  * Side Effects:
                    399:  *
                    400:  *-----------------------------------------------------------------------
                    401:  */
                    402: void
                    403: Targ_PrintType (type)
                    404:     register int    type;
                    405: {
                    406:     register int    tbit;
                    407:     
                    408: #ifdef __STDC__
                    409: #define PRINTBIT(attr) case CONCAT(OP_,attr): printf("." #attr " "); break
                    410: #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf("." #attr " "); break
                    411: #else
                    412: #define PRINTBIT(attr)         case CONCAT(OP_,attr): printf(".attr "); break
                    413: #define PRINTDBIT(attr)        case CONCAT(OP_,attr): if (DEBUG(TARG)) printf(".attr "); break
                    414: #endif /* __STDC__ */
                    415: 
                    416:     type &= ~OP_OPMASK;
                    417: 
                    418:     while (type) {
                    419:        tbit = 1 << (ffs(type) - 1);
                    420:        type &= ~tbit;
                    421: 
                    422:        switch(tbit) {
                    423:            PRINTBIT(OPTIONAL);
                    424:            PRINTBIT(USE);
                    425:            PRINTBIT(EXEC);
                    426:            PRINTBIT(IGNORE);
                    427:            PRINTBIT(PRECIOUS);
                    428:            PRINTBIT(SILENT);
                    429:            PRINTBIT(MAKE);
                    430:            PRINTBIT(JOIN);
                    431:            PRINTBIT(INVISIBLE);
                    432:            PRINTBIT(NOTMAIN);
                    433:            PRINTDBIT(LIB);
                    434:            /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */
                    435:            case OP_MEMBER: if (DEBUG(TARG)) printf(".MEMBER "); break;
                    436:            PRINTDBIT(ARCHV);
                    437:        }
                    438:     }
                    439: }
                    440: 
                    441: /*-
                    442:  *-----------------------------------------------------------------------
                    443:  * TargPrintNode --
                    444:  *     print the contents of a node
                    445:  *-----------------------------------------------------------------------
                    446:  */
                    447: static int
                    448: TargPrintNode (gn, pass)
                    449:     GNode         *gn;
                    450:     int                  pass;
                    451: {
                    452:     if (!OP_NOP(gn->type)) {
                    453:        printf("#\n");
                    454:        if (gn == mainTarg) {
                    455:            printf("# *** MAIN TARGET ***\n");
                    456:        }
                    457:        if (pass == 2) {
                    458:            if (gn->unmade) {
                    459:                printf("# %d unmade children\n", gn->unmade);
                    460:            } else {
                    461:                printf("# No unmade children\n");
                    462:            }
                    463:            if (! (gn->type & (OP_JOIN|OP_USE|OP_EXEC))) {
                    464:                if (gn->mtime != 0) {
                    465:                    printf("# last modified %s: %s\n",
                    466:                              Targ_FmtTime(gn->mtime),
                    467:                              (gn->made == UNMADE ? "unmade" :
                    468:                               (gn->made == MADE ? "made" :
                    469:                                (gn->made == UPTODATE ? "up-to-date" :
                    470:                                 "error when made"))));
                    471:                } else if (gn->made != UNMADE) {
                    472:                    printf("# non-existent (maybe): %s\n",
                    473:                              (gn->made == MADE ? "made" :
                    474:                               (gn->made == UPTODATE ? "up-to-date" :
                    475:                                (gn->made == ERROR ? "error when made" :
                    476:                                 "aborted"))));
                    477:                } else {
                    478:                    printf("# unmade\n");
                    479:                }
                    480:            }
                    481:            if (!Lst_IsEmpty (gn->iParents)) {
                    482:                printf("# implicit parents: ");
                    483:                Lst_ForEach (gn->iParents, TargPrintName, (ClientData)0);
                    484:                putc ('\n', stdout);
                    485:            }
                    486:        }
                    487:        if (!Lst_IsEmpty (gn->parents)) {
                    488:            printf("# parents: ");
                    489:            Lst_ForEach (gn->parents, TargPrintName, (ClientData)0);
                    490:            putc ('\n', stdout);
                    491:        }
                    492:        
                    493:        printf("%-16s", gn->name);
                    494:        switch (gn->type & OP_OPMASK) {
                    495:            case OP_DEPENDS:
                    496:                printf(": "); break;
                    497:            case OP_FORCE:
                    498:                printf("! "); break;
                    499:            case OP_DOUBLEDEP:
                    500:                printf(":: "); break;
                    501:        }
                    502:        Targ_PrintType (gn->type);
                    503:        Lst_ForEach (gn->children, TargPrintName, (ClientData)0);
                    504:        putc ('\n', stdout);
                    505:        Lst_ForEach (gn->commands, Targ_PrintCmd, (ClientData)0);
                    506:        printf("\n\n");
                    507:        if (gn->type & OP_DOUBLEDEP) {
                    508:            Lst_ForEach (gn->cohorts, TargPrintNode, (ClientData)pass);
                    509:        }
                    510:     }
                    511:     return (0);
                    512: }
                    513: 
                    514: /*-
                    515:  *-----------------------------------------------------------------------
                    516:  * TargPrintOnlySrc --
                    517:  *     Print only those targets that are just a source.
                    518:  *
                    519:  * Results:
                    520:  *     0.
                    521:  *
                    522:  * Side Effects:
                    523:  *     The name of each file is printed preceeded by #\t
                    524:  *
                    525:  *-----------------------------------------------------------------------
                    526:  */
                    527: static int
                    528: TargPrintOnlySrc(gn)
                    529:     GNode        *gn;
                    530: {
                    531:     if (OP_NOP(gn->type)) {
                    532:        printf("#\t%s [%s]\n", gn->name,
                    533:                  gn->path ? gn->path : gn->name);
                    534:     }
                    535:     return (0);
                    536: }
                    537: 
                    538: /*-
                    539:  *-----------------------------------------------------------------------
                    540:  * Targ_PrintGraph --
                    541:  *     print the entire graph. heh heh
                    542:  *
                    543:  * Results:
                    544:  *     none
                    545:  *
                    546:  * Side Effects:
                    547:  *     lots o' output
                    548:  *-----------------------------------------------------------------------
                    549:  */
                    550: Targ_PrintGraph (pass)
                    551:     int            pass;       /* Which pass this is. 1 => no processing
                    552:                         * 2 => processing done */
                    553: {
                    554:     printf("#*** Input graph:\n");
                    555:     Lst_ForEach (allTargets, TargPrintNode, (ClientData)pass);
                    556:     printf("\n\n");
                    557:     printf("#\n#   Files that are only sources:\n");
                    558:     Lst_ForEach (allTargets, TargPrintOnlySrc);
                    559:     printf("#*** Global Variables:\n");
                    560:     Var_Dump (VAR_GLOBAL);
                    561:     printf("#*** Command-line Variables:\n");
                    562:     Var_Dump (VAR_CMD);
                    563:     printf("\n");
                    564:     Dir_PrintDirectories();
                    565:     printf("\n");
                    566:     Suff_PrintAll();
                    567: }

unix.superglobalmegacorp.com

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