[BACK]Return to targ.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / usr.bin / make

Annotation of src/usr.bin/make/targ.c, Revision 1.93

1.93    ! rillig      1: /*     $NetBSD: targ.c,v 1.92 2020/09/24 07:11:29 rillig Exp $ */
1.5       christos    2:
1.1       cgd         3: /*
1.10      christos    4:  * Copyright (c) 1988, 1989, 1990, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
1.30      agc         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, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. Neither the name of the University nor the names of its contributors
                     19:  *    may be used to endorse or promote products derived from this software
                     20:  *    without specific prior written permission.
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     25:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     26:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     27:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     28:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     29:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     30:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     31:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     32:  * SUCH DAMAGE.
                     33:  */
                     34:
                     35: /*
1.1       cgd        36:  * Copyright (c) 1989 by Berkeley Softworks
                     37:  * All rights reserved.
                     38:  *
                     39:  * This code is derived from software contributed to Berkeley by
                     40:  * Adam de Boor.
                     41:  *
                     42:  * Redistribution and use in source and binary forms, with or without
                     43:  * modification, are permitted provided that the following conditions
                     44:  * are met:
                     45:  * 1. Redistributions of source code must retain the above copyright
                     46:  *    notice, this list of conditions and the following disclaimer.
                     47:  * 2. Redistributions in binary form must reproduce the above copyright
                     48:  *    notice, this list of conditions and the following disclaimer in the
                     49:  *    documentation and/or other materials provided with the distribution.
                     50:  * 3. All advertising materials mentioning features or use of this software
                     51:  *    must display the following acknowledgement:
                     52:  *     This product includes software developed by the University of
                     53:  *     California, Berkeley and its contributors.
                     54:  * 4. Neither the name of the University nor the names of its contributors
                     55:  *    may be used to endorse or promote products derived from this software
                     56:  *    without specific prior written permission.
                     57:  *
                     58:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     59:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     60:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     61:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     62:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     63:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     64:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     65:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     66:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     67:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     68:  * SUCH DAMAGE.
                     69:  */
                     70:
                     71: /*-
                     72:  * targ.c --
                     73:  *     Functions for maintaining the Lst allTargets. Target nodes are
1.77      rillig     74:  *     kept in two structures: a Lst and a hash table.
1.1       cgd        75:  *
                     76:  * Interface:
                     77:  *     Targ_Init               Initialization procedure.
                     78:  *
1.4       jtc        79:  *     Targ_End                Cleanup the module
                     80:  *
1.12      christos   81:  *     Targ_List               Return the list of all targets so far.
                     82:  *
1.1       cgd        83:  *     Targ_NewGN              Create a new GNode for the passed target
                     84:  *                             (string). The node is *not* placed in the
                     85:  *                             hash table, though all its fields are
                     86:  *                             initialized.
                     87:  *
                     88:  *     Targ_FindNode           Find the node for a given target, creating
                     89:  *                             and storing it if it doesn't exist and the
                     90:  *                             flags are right (TARG_CREATE)
                     91:  *
                     92:  *     Targ_FindList           Given a list of names, find nodes for all
                     93:  *                             of them. If a name doesn't exist and the
                     94:  *                             TARG_NOCREATE flag was given, an error message
                     95:  *                             is printed. Else, if a name doesn't exist,
                     96:  *                             its node is created.
                     97:  *
                     98:  *     Targ_Ignore             Return TRUE if errors should be ignored when
                     99:  *                             creating the given target.
                    100:  *
                    101:  *     Targ_Silent             Return TRUE if we should be silent when
                    102:  *                             creating the given target.
                    103:  *
                    104:  *     Targ_Precious           Return TRUE if the target is precious and
                    105:  *                             should not be removed if we are interrupted.
                    106:  *
1.42      apb       107:  *     Targ_Propagate          Propagate information between related
                    108:  *                             nodes.  Should be called after the
                    109:  *                             makefiles are parsed but before any
                    110:  *                             action is taken.
                    111:  *
1.1       cgd       112:  * Debugging:
                    113:  *     Targ_PrintGraph         Print out the entire graphm all variables
                    114:  *                             and statistics for the directory cache. Should
                    115:  *                             print something for suffixes, too, but...
                    116:  */
                    117:
                    118: #include         <stdio.h>
                    119: #include         <time.h>
1.28      wiz       120:
1.1       cgd       121: #include         "make.h"
1.3       cgd       122: #include         "dir.h"
1.1       cgd       123:
1.88      rillig    124: /*     "@(#)targ.c     8.2 (Berkeley) 3/19/94" */
1.93    ! rillig    125: MAKE_RCSID("$NetBSD: targ.c,v 1.92 2020/09/24 07:11:29 rillig Exp $");
1.88      rillig    126:
1.89      rillig    127: static GNodeList *allTargets;  /* the list of all targets found so far */
1.18      mycroft   128: #ifdef CLEANUP
1.89      rillig    129: static GNodeList *allGNs;      /* List of all the GNodes */
1.18      mycroft   130: #endif
1.1       cgd       131: static Hash_Table targets;     /* a hash table of same */
                    132:
1.55      dsl       133: static int TargPrintOnlySrc(void *, void *);
1.18      mycroft   134: #ifdef CLEANUP
1.55      dsl       135: static void TargFreeGN(void *);
1.18      mycroft   136: #endif
1.4       jtc       137:
1.1       cgd       138: void
1.28      wiz       139: Targ_Init(void)
1.1       cgd       140: {
1.65      rillig    141:     allTargets = Lst_Init();
1.83      rillig    142:     Hash_InitTable(&targets);
1.1       cgd       143: }
                    144:
1.4       jtc       145: void
1.28      wiz       146: Targ_End(void)
1.4       jtc       147: {
1.64      sjg       148:     Targ_Stats();
1.18      mycroft   149: #ifdef CLEANUP
1.76      rillig    150:     Lst_Free(allTargets);
1.73      rillig    151:     if (allGNs != NULL)
1.76      rillig    152:        Lst_Destroy(allGNs, TargFreeGN);
1.4       jtc       153:     Hash_DeleteTable(&targets);
1.18      mycroft   154: #endif
1.12      christos  155: }
                    156:
1.64      sjg       157: void
                    158: Targ_Stats(void)
                    159: {
                    160:     Hash_DebugStats(&targets, "targets");
                    161: }
                    162:
1.77      rillig    163: /* Return the list of all targets. */
1.89      rillig    164: GNodeList *
1.28      wiz       165: Targ_List(void)
1.12      christos  166: {
                    167:     return allTargets;
1.4       jtc       168: }
                    169:
1.77      rillig    170: /* Create and initialize a new graph node. The gnode is added to the list of
                    171:  * all gnodes.
1.1       cgd       172:  *
1.28      wiz       173:  * Input:
1.91      rillig    174:  *     name            the name of the node, such as "clean", "src.c", ".END"
1.1       cgd       175:  */
                    176: GNode *
1.29      christos  177: Targ_NewGN(const char *name)
1.1       cgd       178: {
1.28      wiz       179:     GNode *gn;
1.1       cgd       180:
1.53      joerg     181:     gn = bmake_malloc(sizeof(GNode));
                    182:     gn->name = bmake_strdup(name);
1.11      christos  183:     gn->uname = NULL;
1.29      christos  184:     gn->path = NULL;
1.77      rillig    185:     gn->type = name[0] == '-' && name[1] == 'l' ? OP_LIB : 0;
1.1       cgd       186:     gn->unmade =       0;
1.27      pk        187:     gn->unmade_cohorts = 0;
1.45      dsl       188:     gn->cohort_num[0] = 0;
1.27      pk        189:     gn->centurion =            NULL;
1.1       cgd       190:     gn->made =                 UNMADE;
1.16      christos  191:     gn->flags =        0;
1.56      christos  192:     gn->checked =      0;
                    193:     gn->mtime =                0;
                    194:     gn->cmgn =         NULL;
1.80      rillig    195:     gn->implicitParents = Lst_Init();
1.65      rillig    196:     gn->cohorts =      Lst_Init();
                    197:     gn->parents =      Lst_Init();
                    198:     gn->children =     Lst_Init();
                    199:     gn->order_pred =   Lst_Init();
                    200:     gn->order_succ =   Lst_Init();
1.83      rillig    201:     Hash_InitTable(&gn->context);
1.65      rillig    202:     gn->commands =     Lst_Init();
1.3       cgd       203:     gn->suffix =       NULL;
1.77      rillig    204:     gn->fname =        NULL;
1.21      christos  205:     gn->lineno =       0;
1.1       cgd       206:
1.18      mycroft   207: #ifdef CLEANUP
1.4       jtc       208:     if (allGNs == NULL)
1.65      rillig    209:        allGNs = Lst_Init();
1.76      rillig    210:     Lst_Append(allGNs, gn);
1.18      mycroft   211: #endif
1.4       jtc       212:
1.63      rillig    213:     return gn;
1.1       cgd       214: }
                    215:
1.18      mycroft   216: #ifdef CLEANUP
1.4       jtc       217: static void
1.55      dsl       218: TargFreeGN(void *gnp)
1.4       jtc       219: {
1.37      christos  220:     GNode *gn = (GNode *)gnp;
1.4       jtc       221:
                    222:     free(gn->name);
1.61      christos  223:     free(gn->uname);
                    224:     free(gn->path);
1.4       jtc       225:
1.80      rillig    226:     Lst_Free(gn->implicitParents);
1.76      rillig    227:     Lst_Free(gn->cohorts);
                    228:     Lst_Free(gn->parents);
                    229:     Lst_Free(gn->children);
                    230:     Lst_Free(gn->order_succ);
                    231:     Lst_Free(gn->order_pred);
1.17      mycroft   232:     Hash_DeleteTable(&gn->context);
1.76      rillig    233:     Lst_Free(gn->commands);
1.77      rillig    234:
                    235:     /* XXX: does gn->suffix need to be freed? It is reference-counted. */
                    236:     /* gn->fname points to name allocated when file was opened, don't free */
                    237:
1.36      christos  238:     free(gn);
1.4       jtc       239: }
1.18      mycroft   240: #endif
1.4       jtc       241:
                    242:
1.77      rillig    243: /* Find a node in the list using the given name for matching.
                    244:  * If the node is created, it is added to the .ALLTARGETS list.
1.1       cgd       245:  *
1.28      wiz       246:  * Input:
                    247:  *     name            the name to find
1.77      rillig    248:  *     flags           flags governing events when target not found
1.28      wiz       249:  *
1.1       cgd       250:  * Results:
1.77      rillig    251:  *     The node in the list if it was. If it wasn't, return NULL if
1.1       cgd       252:  *     flags was TARG_NOCREATE or the newly created and initialized node
                    253:  *     if it was TARG_CREATE
                    254:  */
                    255: GNode *
1.29      christos  256: Targ_FindNode(const char *name, int flags)
1.1       cgd       257: {
                    258:     GNode         *gn;       /* node in that element */
1.60      manu      259:     Hash_Entry   *he = NULL; /* New or used hash entry for node */
1.1       cgd       260:     Boolean      isNew;      /* Set TRUE if Hash_CreateEntry had to create */
                    261:                              /* an entry for the node */
                    262:
1.45      dsl       263:     if (!(flags & (TARG_CREATE | TARG_NOHASH))) {
                    264:        he = Hash_FindEntry(&targets, name);
                    265:        if (he == NULL)
1.54      dsl       266:            return NULL;
1.45      dsl       267:        return (GNode *)Hash_GetValue(he);
                    268:     }
1.1       cgd       269:
1.45      dsl       270:     if (!(flags & TARG_NOHASH)) {
1.34      christos  271:        he = Hash_CreateEntry(&targets, name, &isNew);
1.45      dsl       272:        if (!isNew)
                    273:            return (GNode *)Hash_GetValue(he);
1.1       cgd       274:     }
                    275:
1.45      dsl       276:     gn = Targ_NewGN(name);
                    277:     if (!(flags & TARG_NOHASH))
                    278:        Hash_SetValue(he, gn);
                    279:     Var_Append(".ALLTARGETS", name, VAR_GLOBAL);
1.76      rillig    280:     Lst_Append(allTargets, gn);
1.50      dsl       281:     if (doing_depend)
                    282:        gn->flags |= FROM_DEPEND;
1.45      dsl       283:     return gn;
1.1       cgd       284: }
                    285:
1.90      rillig    286: /* Return the .END node, which contains the commands to be executed when
                    287:  * everything else is done. */
                    288: GNode *Targ_GetEndNode(void)
                    289: {
                    290:     /* Save the node locally to avoid having to search for it all the time. */
                    291:     static GNode *endNode = NULL;
                    292:     if (endNode == NULL) {
                    293:        endNode = Targ_FindNode(".END", TARG_CREATE);
                    294:        endNode->type = OP_SPECIAL;
                    295:     }
                    296:     return endNode;
                    297: }
                    298:
1.77      rillig    299: /* Make a complete list of GNodes from the given list of names.
                    300:  * If flags is TARG_CREATE, nodes will be created for all names in
                    301:  * names which do not yet have graph nodes. If flags is TARG_NOCREATE,
                    302:  * an error message will be printed for each name which can't be found.
1.1       cgd       303:  *
1.28      wiz       304:  * Input:
                    305:  *     name            list of names to find
                    306:  *     flags           flags used if no node is found for a given name
                    307:  *
1.1       cgd       308:  * Results:
                    309:  *     A complete list of graph nodes corresponding to all instances of all
1.10      christos  310:  *     the names in names.
1.1       cgd       311:  */
1.89      rillig    312: GNodeList *
                    313: Targ_FindList(StringList *names, int flags)
1.1       cgd       314: {
1.89      rillig    315:     GNodeList *nodes;
                    316:     StringListNode *ln;
1.1       cgd       317:
1.65      rillig    318:     nodes = Lst_Init();
1.1       cgd       319:
1.76      rillig    320:     Lst_Open(names);
                    321:     while ((ln = Lst_Next(names)) != NULL) {
1.89      rillig    322:        char *name = LstNode_Datum(ln);
                    323:        GNode *gn = Targ_FindNode(name, flags);
1.54      dsl       324:        if (gn != NULL) {
1.76      rillig    325:            Lst_Append(nodes, gn);
1.1       cgd       326:        } else if (flags == TARG_NOCREATE) {
1.34      christos  327:            Error("\"%s\" -- target unknown.", name);
1.1       cgd       328:        }
                    329:     }
1.76      rillig    330:     Lst_Close(names);
1.63      rillig    331:     return nodes;
1.1       cgd       332: }
                    333:
1.77      rillig    334: /* Return true if should ignore errors when creating gn. */
1.1       cgd       335: Boolean
1.28      wiz       336: Targ_Ignore(GNode *gn)
1.1       cgd       337: {
1.77      rillig    338:     return ignoreErrors || gn->type & OP_IGNORE;
1.1       cgd       339: }
                    340:
1.77      rillig    341: /* Return true if be silent when creating gn. */
1.1       cgd       342: Boolean
1.28      wiz       343: Targ_Silent(GNode *gn)
1.1       cgd       344: {
1.77      rillig    345:     return beSilent || gn->type & OP_SILENT;
1.1       cgd       346: }
                    347:
1.77      rillig    348: /* See if the given target is precious. */
1.1       cgd       349: Boolean
1.28      wiz       350: Targ_Precious(GNode *gn)
1.1       cgd       351: {
1.77      rillig    352:     return allPrecious || gn->type & (OP_PRECIOUS | OP_DOUBLEDEP);
1.1       cgd       353: }
                    354:
                    355: /******************* DEBUG INFO PRINTING ****************/
                    356:
                    357: static GNode     *mainTarg;    /* the main target, as set by Targ_SetMain */
1.77      rillig    358:
                    359: /* Set our idea of the main target we'll be creating. Used for debugging
                    360:  * output. */
1.1       cgd       361: void
1.28      wiz       362: Targ_SetMain(GNode *gn)
1.1       cgd       363: {
                    364:     mainTarg = gn;
                    365: }
                    366:
1.86      rillig    367: static void
1.89      rillig    368: PrintNodeNames(GNodeList *gnodes)
1.1       cgd       369: {
1.89      rillig    370:     GNodeListNode *node;
1.38      dsl       371:
1.85      rillig    372:     for (node = Lst_First(gnodes); node != NULL; node = LstNode_Next(node)) {
                    373:        GNode *gn = LstNode_Datum(node);
                    374:        fprintf(debug_file, " %s%s", gn->name, gn->cohort_num);
                    375:     }
                    376: }
1.38      dsl       377:
1.85      rillig    378: static void
1.89      rillig    379: PrintNodeNamesLine(const char *label, GNodeList *gnodes)
1.85      rillig    380: {
                    381:     if (Lst_IsEmpty(gnodes))
                    382:        return;
                    383:     fprintf(debug_file, "# %s:", label);
                    384:     PrintNodeNames(gnodes);
                    385:     fprintf(debug_file, "\n");
1.1       cgd       386: }
                    387:
1.84      rillig    388: void
                    389: Targ_PrintCmds(GNode *gn)
                    390: {
1.93    ! rillig    391:     StringListNode *node = Lst_First(gn->commands);
        !           392:     for (; node != NULL; node = LstNode_Next(node)) {
        !           393:        const char *cmd = LstNode_Datum(node);
        !           394:        fprintf(debug_file, "\t%s\n", cmd);
        !           395:     }
1.84      rillig    396: }
                    397:
1.77      rillig    398: /* Format a modification time in some reasonable way and return it.
                    399:  * The time is placed in a static area, so it is overwritten with each call. */
1.1       cgd       400: char *
1.28      wiz       401: Targ_FmtTime(time_t tm)
1.1       cgd       402: {
                    403:     struct tm          *parts;
1.15      christos  404:     static char                buf[128];
1.1       cgd       405:
1.25      reinoud   406:     parts = localtime(&tm);
1.15      christos  407:     (void)strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts);
1.63      rillig    408:     return buf;
1.1       cgd       409: }
1.10      christos  410:
1.77      rillig    411: /* Print out a type field giving only those attributes the user can set. */
1.1       cgd       412: void
1.52      christos  413: Targ_PrintType(int type)
1.1       cgd       414: {
1.28      wiz       415:     int    tbit;
1.10      christos  416:
1.82      rillig    417: #define PRINTBIT(attr) case CONCAT(OP_,attr): fprintf(debug_file, " ." #attr); break
                    418: #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG))fprintf(debug_file, " ." #attr); break
1.1       cgd       419:
                    420:     type &= ~OP_OPMASK;
                    421:
                    422:     while (type) {
1.52      christos  423:        tbit = 1 << (ffs(type) - 1);
1.1       cgd       424:        type &= ~tbit;
                    425:
                    426:        switch(tbit) {
                    427:            PRINTBIT(OPTIONAL);
                    428:            PRINTBIT(USE);
                    429:            PRINTBIT(EXEC);
                    430:            PRINTBIT(IGNORE);
                    431:            PRINTBIT(PRECIOUS);
                    432:            PRINTBIT(SILENT);
                    433:            PRINTBIT(MAKE);
                    434:            PRINTBIT(JOIN);
                    435:            PRINTBIT(INVISIBLE);
                    436:            PRINTBIT(NOTMAIN);
                    437:            PRINTDBIT(LIB);
                    438:            /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */
1.82      rillig    439:            case OP_MEMBER: if (DEBUG(TARG))fprintf(debug_file, " .MEMBER"); break;
1.1       cgd       440:            PRINTDBIT(ARCHV);
1.26      pk        441:            PRINTDBIT(MADE);
                    442:            PRINTDBIT(PHONY);
1.1       cgd       443:        }
                    444:     }
                    445: }
                    446:
1.45      dsl       447: static const char *
1.71      rillig    448: made_name(GNodeMade made)
1.45      dsl       449: {
                    450:     switch (made) {
                    451:     case UNMADE:     return "unmade";
                    452:     case DEFERRED:   return "deferred";
                    453:     case REQUESTED:  return "requested";
                    454:     case BEINGMADE:  return "being made";
                    455:     case MADE:       return "made";
                    456:     case UPTODATE:   return "up-to-date";
                    457:     case ERROR:      return "error when made";
                    458:     case ABORTED:    return "aborted";
                    459:     default:         return "unknown enum_made value";
                    460:     }
                    461: }
                    462:
1.87      rillig    463: static int
                    464: PrintNode(void *gnp, void *passp)
1.1       cgd       465: {
1.87      rillig    466:     GNode *gn = gnp;
                    467:     int pass = *(const int *)passp;
1.45      dsl       468:
1.72      rillig    469:     fprintf(debug_file, "# %s%s", gn->name, gn->cohort_num);
                    470:     GNode_FprintDetails(debug_file, ", ", gn, "\n");
1.45      dsl       471:     if (gn->flags == 0)
                    472:        return 0;
                    473:
1.1       cgd       474:     if (!OP_NOP(gn->type)) {
1.43      dsl       475:        fprintf(debug_file, "#\n");
1.1       cgd       476:        if (gn == mainTarg) {
1.43      dsl       477:            fprintf(debug_file, "# *** MAIN TARGET ***\n");
1.1       cgd       478:        }
1.45      dsl       479:        if (pass >= 2) {
1.1       cgd       480:            if (gn->unmade) {
1.43      dsl       481:                fprintf(debug_file, "# %d unmade children\n", gn->unmade);
1.1       cgd       482:            } else {
1.43      dsl       483:                fprintf(debug_file, "# No unmade children\n");
1.1       cgd       484:            }
1.22      christos  485:            if (! (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC))) {
1.1       cgd       486:                if (gn->mtime != 0) {
1.43      dsl       487:                    fprintf(debug_file, "# last modified %s: %s\n",
1.1       cgd       488:                              Targ_FmtTime(gn->mtime),
1.45      dsl       489:                              made_name(gn->made));
1.1       cgd       490:                } else if (gn->made != UNMADE) {
1.43      dsl       491:                    fprintf(debug_file, "# non-existent (maybe): %s\n",
1.45      dsl       492:                              made_name(gn->made));
1.1       cgd       493:                } else {
1.43      dsl       494:                    fprintf(debug_file, "# unmade\n");
1.1       cgd       495:                }
                    496:            }
1.85      rillig    497:            PrintNodeNamesLine("implicit parents", gn->implicitParents);
1.41      dsl       498:        } else {
                    499:            if (gn->unmade)
1.43      dsl       500:                fprintf(debug_file, "# %d unmade children\n", gn->unmade);
1.1       cgd       501:        }
1.85      rillig    502:        PrintNodeNamesLine("parents", gn->parents);
                    503:        PrintNodeNamesLine("order_pred", gn->order_pred);
                    504:        PrintNodeNamesLine("order_succ", gn->order_succ);
1.10      christos  505:
1.43      dsl       506:        fprintf(debug_file, "%-16s", gn->name);
1.1       cgd       507:        switch (gn->type & OP_OPMASK) {
                    508:            case OP_DEPENDS:
1.82      rillig    509:                fprintf(debug_file, ":"); break;
1.1       cgd       510:            case OP_FORCE:
1.82      rillig    511:                fprintf(debug_file, "!"); break;
1.1       cgd       512:            case OP_DOUBLEDEP:
1.82      rillig    513:                fprintf(debug_file, "::"); break;
1.1       cgd       514:        }
1.34      christos  515:        Targ_PrintType(gn->type);
1.85      rillig    516:        PrintNodeNames(gn->children);
1.43      dsl       517:        fprintf(debug_file, "\n");
1.84      rillig    518:        Targ_PrintCmds(gn);
1.43      dsl       519:        fprintf(debug_file, "\n\n");
1.20      mycroft   520:        if (gn->type & OP_DOUBLEDEP) {
1.92      rillig    521:            Lst_ForEachUntil(gn->cohorts, PrintNode, passp);
1.1       cgd       522:        }
                    523:     }
1.63      rillig    524:     return 0;
1.1       cgd       525: }
                    526:
1.87      rillig    527: /* Print the contents of a node. */
                    528: void
                    529: Targ_PrintNode(GNode *gn, int pass)
                    530: {
                    531:     PrintNode(gn, &pass);
                    532: }
                    533:
                    534: void
1.89      rillig    535: Targ_PrintNodes(GNodeList *gnodes, int pass)
1.87      rillig    536: {
1.92      rillig    537:     Lst_ForEachUntil(gnodes, PrintNode, &pass);
1.87      rillig    538: }
                    539:
1.77      rillig    540: /* Print only those targets that are just a source.
                    541:  * The name of each file is printed, preceded by #\t. */
1.1       cgd       542: static int
1.57      joerg     543: TargPrintOnlySrc(void *gnp, void *dummy MAKE_ATTR_UNUSED)
1.4       jtc       544: {
1.37      christos  545:     GNode        *gn = (GNode *)gnp;
1.45      dsl       546:     if (!OP_NOP(gn->type))
                    547:        return 0;
1.4       jtc       548:
1.82      rillig    549:     fprintf(debug_file, "#\t%s [%s]",
1.45      dsl       550:            gn->name, gn->path ? gn->path : gn->name);
                    551:     Targ_PrintType(gn->type);
                    552:     fprintf(debug_file, "\n");
                    553:
                    554:     return 0;
1.1       cgd       555: }
                    556:
1.77      rillig    557: /* Input:
                    558:  *     pass            1 => before processing
                    559:  *                     2 => after processing
                    560:  *                     3 => after processing, an error occurred
1.1       cgd       561:  */
1.3       cgd       562: void
1.28      wiz       563: Targ_PrintGraph(int pass)
1.1       cgd       564: {
1.43      dsl       565:     fprintf(debug_file, "#*** Input graph:\n");
1.92      rillig    566:     Lst_ForEachUntil(allTargets, PrintNode, &pass);
1.43      dsl       567:     fprintf(debug_file, "\n\n");
                    568:     fprintf(debug_file, "#\n#   Files that are only sources:\n");
1.92      rillig    569:     Lst_ForEachUntil(allTargets, TargPrintOnlySrc, NULL);
1.43      dsl       570:     fprintf(debug_file, "#*** Global Variables:\n");
1.34      christos  571:     Var_Dump(VAR_GLOBAL);
1.43      dsl       572:     fprintf(debug_file, "#*** Command-line Variables:\n");
1.34      christos  573:     Var_Dump(VAR_CMD);
1.43      dsl       574:     fprintf(debug_file, "\n");
1.1       cgd       575:     Dir_PrintDirectories();
1.43      dsl       576:     fprintf(debug_file, "\n");
1.1       cgd       577:     Suff_PrintAll();
1.19      mycroft   578: }
                    579:
1.78      rillig    580: /* Propagate some type information to cohort nodes (those from the ::
                    581:  * dependency operator).
1.77      rillig    582:  *
1.78      rillig    583:  * Should be called after the makefiles are parsed but before any action is
                    584:  * taken. */
                    585: void
                    586: Targ_Propagate(void)
1.19      mycroft   587: {
1.89      rillig    588:     GNodeListNode *pn, *cn;
1.45      dsl       589:
1.78      rillig    590:     for (pn = Lst_First(allTargets); pn != NULL; pn = LstNode_Next(pn)) {
1.79      rillig    591:        GNode *pgn = LstNode_Datum(pn);
1.19      mycroft   592:
1.78      rillig    593:        if (!(pgn->type & OP_DOUBLEDEP))
                    594:            continue;
1.42      apb       595:
1.78      rillig    596:        for (cn = Lst_First(pgn->cohorts); cn != NULL; cn = LstNode_Next(cn)) {
1.79      rillig    597:            GNode *cgn = LstNode_Datum(cn);
1.42      apb       598:
1.78      rillig    599:            cgn->type |= pgn->type & ~OP_OPMASK;
                    600:        }
                    601:     }
1.1       cgd       602: }

CVSweb <webmaster@jp.NetBSD.org>