[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.44

1.44    ! dsl         1: /*     $NetBSD: targ.c,v 1.43 2006/10/15 08:38:22 dsl 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:
1.31      ross       71: #ifndef MAKE_NATIVE
1.44    ! dsl        72: static char rcsid[] = "$NetBSD: targ.c,v 1.43 2006/10/15 08:38:22 dsl Exp $";
1.14      lukem      73: #else
1.13      christos   74: #include <sys/cdefs.h>
1.1       cgd        75: #ifndef lint
1.9       thorpej    76: #if 0
1.10      christos   77: static char sccsid[] = "@(#)targ.c     8.2 (Berkeley) 3/19/94";
1.9       thorpej    78: #else
1.44    ! dsl        79: __RCSID("$NetBSD: targ.c,v 1.43 2006/10/15 08:38:22 dsl Exp $");
1.9       thorpej    80: #endif
1.1       cgd        81: #endif /* not lint */
1.14      lukem      82: #endif
1.1       cgd        83:
                     84: /*-
                     85:  * targ.c --
                     86:  *     Functions for maintaining the Lst allTargets. Target nodes are
                     87:  * kept in two structures: a Lst, maintained by the list library, and a
                     88:  * hash table, maintained by the hash library.
                     89:  *
                     90:  * Interface:
                     91:  *     Targ_Init               Initialization procedure.
                     92:  *
1.4       jtc        93:  *     Targ_End                Cleanup the module
                     94:  *
1.12      christos   95:  *     Targ_List               Return the list of all targets so far.
                     96:  *
1.1       cgd        97:  *     Targ_NewGN              Create a new GNode for the passed target
                     98:  *                             (string). The node is *not* placed in the
                     99:  *                             hash table, though all its fields are
                    100:  *                             initialized.
                    101:  *
                    102:  *     Targ_FindNode           Find the node for a given target, creating
                    103:  *                             and storing it if it doesn't exist and the
                    104:  *                             flags are right (TARG_CREATE)
                    105:  *
                    106:  *     Targ_FindList           Given a list of names, find nodes for all
                    107:  *                             of them. If a name doesn't exist and the
                    108:  *                             TARG_NOCREATE flag was given, an error message
                    109:  *                             is printed. Else, if a name doesn't exist,
                    110:  *                             its node is created.
                    111:  *
                    112:  *     Targ_Ignore             Return TRUE if errors should be ignored when
                    113:  *                             creating the given target.
                    114:  *
                    115:  *     Targ_Silent             Return TRUE if we should be silent when
                    116:  *                             creating the given target.
                    117:  *
                    118:  *     Targ_Precious           Return TRUE if the target is precious and
                    119:  *                             should not be removed if we are interrupted.
                    120:  *
1.42      apb       121:  *     Targ_Propagate          Propagate information between related
                    122:  *                             nodes.  Should be called after the
                    123:  *                             makefiles are parsed but before any
                    124:  *                             action is taken.
                    125:  *
1.1       cgd       126:  * Debugging:
                    127:  *     Targ_PrintGraph         Print out the entire graphm all variables
                    128:  *                             and statistics for the directory cache. Should
                    129:  *                             print something for suffixes, too, but...
                    130:  */
                    131:
                    132: #include         <stdio.h>
                    133: #include         <time.h>
1.28      wiz       134:
1.1       cgd       135: #include         "make.h"
                    136: #include         "hash.h"
1.3       cgd       137: #include         "dir.h"
1.1       cgd       138:
                    139: static Lst        allTargets;  /* the list of all targets found so far */
1.18      mycroft   140: #ifdef CLEANUP
1.4       jtc       141: static Lst       allGNs;       /* List of all the GNodes */
1.18      mycroft   142: #endif
1.1       cgd       143: static Hash_Table targets;     /* a hash table of same */
                    144:
                    145: #define HTSIZE 191             /* initial size of hash table */
                    146:
1.28      wiz       147: static int TargPrintOnlySrc(ClientData, ClientData);
                    148: static int TargPrintName(ClientData, ClientData);
1.18      mycroft   149: #ifdef CLEANUP
1.28      wiz       150: static void TargFreeGN(ClientData);
1.18      mycroft   151: #endif
1.28      wiz       152: static int TargPropagateCohort(ClientData, ClientData);
                    153: static int TargPropagateNode(ClientData, ClientData);
1.4       jtc       154:
1.1       cgd       155: /*-
                    156:  *-----------------------------------------------------------------------
                    157:  * Targ_Init --
                    158:  *     Initialize this module
                    159:  *
                    160:  * Results:
                    161:  *     None
                    162:  *
                    163:  * Side Effects:
                    164:  *     The allTargets list and the targets hash table are initialized
                    165:  *-----------------------------------------------------------------------
                    166:  */
                    167: void
1.28      wiz       168: Targ_Init(void)
1.1       cgd       169: {
1.34      christos  170:     allTargets = Lst_Init(FALSE);
                    171:     Hash_InitTable(&targets, HTSIZE);
1.1       cgd       172: }
                    173:
                    174: /*-
                    175:  *-----------------------------------------------------------------------
1.4       jtc       176:  * Targ_End --
                    177:  *     Finalize this module
                    178:  *
                    179:  * Results:
                    180:  *     None
                    181:  *
                    182:  * Side Effects:
                    183:  *     All lists and gnodes are cleared
                    184:  *-----------------------------------------------------------------------
                    185:  */
                    186: void
1.28      wiz       187: Targ_End(void)
1.4       jtc       188: {
1.18      mycroft   189: #ifdef CLEANUP
1.4       jtc       190:     Lst_Destroy(allTargets, NOFREE);
                    191:     if (allGNs)
                    192:        Lst_Destroy(allGNs, TargFreeGN);
                    193:     Hash_DeleteTable(&targets);
1.18      mycroft   194: #endif
1.12      christos  195: }
                    196:
                    197: /*-
                    198:  *-----------------------------------------------------------------------
                    199:  * Targ_List --
                    200:  *     Return the list of all targets
                    201:  *
                    202:  * Results:
                    203:  *     The list of all targets.
                    204:  *
                    205:  * Side Effects:
                    206:  *     None
                    207:  *-----------------------------------------------------------------------
                    208:  */
                    209: Lst
1.28      wiz       210: Targ_List(void)
1.12      christos  211: {
                    212:     return allTargets;
1.4       jtc       213: }
                    214:
                    215: /*-
                    216:  *-----------------------------------------------------------------------
1.1       cgd       217:  * Targ_NewGN  --
                    218:  *     Create and initialize a new graph node
                    219:  *
1.28      wiz       220:  * Input:
                    221:  *     name            the name to stick in the new node
                    222:  *
1.1       cgd       223:  * Results:
                    224:  *     An initialized graph node with the name field filled with a copy
                    225:  *     of the passed name
                    226:  *
                    227:  * Side Effects:
1.4       jtc       228:  *     The gnode is added to the list of all gnodes.
1.1       cgd       229:  *-----------------------------------------------------------------------
                    230:  */
                    231: GNode *
1.29      christos  232: Targ_NewGN(const char *name)
1.1       cgd       233: {
1.28      wiz       234:     GNode *gn;
1.1       cgd       235:
1.34      christos  236:     gn = emalloc(sizeof(GNode));
                    237:     gn->name = estrdup(name);
1.11      christos  238:     gn->uname = NULL;
1.29      christos  239:     gn->path = NULL;
1.1       cgd       240:     if (name[0] == '-' && name[1] == 'l') {
                    241:        gn->type = OP_LIB;
                    242:     } else {
                    243:        gn->type = 0;
                    244:     }
                    245:     gn->unmade =       0;
1.27      pk        246:     gn->unmade_cohorts = 0;
                    247:     gn->centurion =            NULL;
1.1       cgd       248:     gn->made =                 UNMADE;
1.16      christos  249:     gn->flags =        0;
1.6       christos  250:     gn->order =                0;
1.1       cgd       251:     gn->mtime = gn->cmtime = 0;
1.34      christos  252:     gn->iParents =     Lst_Init(FALSE);
                    253:     gn->cohorts =      Lst_Init(FALSE);
                    254:     gn->parents =      Lst_Init(FALSE);
1.42      apb       255:     gn->ancestors =    Lst_Init(FALSE);
1.34      christos  256:     gn->children =     Lst_Init(FALSE);
                    257:     gn->successors =   Lst_Init(FALSE);
                    258:     gn->preds =        Lst_Init(FALSE);
1.42      apb       259:     gn->recpreds =     Lst_Init(FALSE);
1.17      mycroft   260:     Hash_InitTable(&gn->context, 0);
1.34      christos  261:     gn->commands =     Lst_Init(FALSE);
1.3       cgd       262:     gn->suffix =       NULL;
1.21      christos  263:     gn->lineno =       0;
                    264:     gn->fname =        NULL;
1.1       cgd       265:
1.18      mycroft   266: #ifdef CLEANUP
1.4       jtc       267:     if (allGNs == NULL)
                    268:        allGNs = Lst_Init(FALSE);
1.44    ! dsl       269:     Lst_AtEnd(allGNs, gn);
1.18      mycroft   270: #endif
1.4       jtc       271:
1.1       cgd       272:     return (gn);
                    273: }
                    274:
1.18      mycroft   275: #ifdef CLEANUP
1.1       cgd       276: /*-
                    277:  *-----------------------------------------------------------------------
1.4       jtc       278:  * TargFreeGN  --
                    279:  *     Destroy a GNode
                    280:  *
                    281:  * Results:
                    282:  *     None.
                    283:  *
                    284:  * Side Effects:
                    285:  *     None.
                    286:  *-----------------------------------------------------------------------
                    287:  */
                    288: static void
1.28      wiz       289: TargFreeGN(ClientData gnp)
1.4       jtc       290: {
1.37      christos  291:     GNode *gn = (GNode *)gnp;
1.4       jtc       292:
                    293:
                    294:     free(gn->name);
1.11      christos  295:     if (gn->uname)
                    296:        free(gn->uname);
1.4       jtc       297:     if (gn->path)
                    298:        free(gn->path);
1.21      christos  299:     if (gn->fname)
                    300:        free(gn->fname);
1.4       jtc       301:
                    302:     Lst_Destroy(gn->iParents, NOFREE);
                    303:     Lst_Destroy(gn->cohorts, NOFREE);
                    304:     Lst_Destroy(gn->parents, NOFREE);
1.42      apb       305:     Lst_Destroy(gn->ancestors, NOFREE);
1.4       jtc       306:     Lst_Destroy(gn->children, NOFREE);
                    307:     Lst_Destroy(gn->successors, NOFREE);
                    308:     Lst_Destroy(gn->preds, NOFREE);
1.42      apb       309:     Lst_Destroy(gn->recpreds, NOFREE);
1.17      mycroft   310:     Hash_DeleteTable(&gn->context);
1.4       jtc       311:     Lst_Destroy(gn->commands, NOFREE);
1.36      christos  312:     free(gn);
1.4       jtc       313: }
1.18      mycroft   314: #endif
1.4       jtc       315:
                    316:
                    317: /*-
                    318:  *-----------------------------------------------------------------------
1.1       cgd       319:  * Targ_FindNode  --
                    320:  *     Find a node in the list using the given name for matching
                    321:  *
1.28      wiz       322:  * Input:
                    323:  *     name            the name to find
                    324:  *     flags           flags governing events when target not
                    325:  *                     found
                    326:  *
1.1       cgd       327:  * Results:
                    328:  *     The node in the list if it was. If it wasn't, return NILGNODE of
                    329:  *     flags was TARG_NOCREATE or the newly created and initialized node
                    330:  *     if it was TARG_CREATE
                    331:  *
                    332:  * Side Effects:
                    333:  *     Sometimes a node is created and added to the list
                    334:  *-----------------------------------------------------------------------
                    335:  */
                    336: GNode *
1.29      christos  337: Targ_FindNode(const char *name, int flags)
1.1       cgd       338: {
                    339:     GNode         *gn;       /* node in that element */
                    340:     Hash_Entry   *he;        /* New or used hash entry for node */
                    341:     Boolean      isNew;      /* Set TRUE if Hash_CreateEntry had to create */
                    342:                              /* an entry for the node */
                    343:
                    344:
                    345:     if (flags & TARG_CREATE) {
1.34      christos  346:        he = Hash_CreateEntry(&targets, name, &isNew);
1.1       cgd       347:        if (isNew) {
1.34      christos  348:            gn = Targ_NewGN(name);
1.35      christos  349:            Hash_SetValue(he, gn);
1.24      tv        350:            Var_Append(".ALLTARGETS", name, VAR_GLOBAL);
1.44    ! dsl       351:            (void)Lst_AtEnd(allTargets, gn);
1.1       cgd       352:        }
                    353:     } else {
1.34      christos  354:        he = Hash_FindEntry(&targets, name);
1.1       cgd       355:     }
                    356:
1.37      christos  357:     if (he == NULL) {
1.1       cgd       358:        return (NILGNODE);
                    359:     } else {
1.35      christos  360:        return ((GNode *)Hash_GetValue(he));
1.1       cgd       361:     }
                    362: }
                    363:
                    364: /*-
                    365:  *-----------------------------------------------------------------------
                    366:  * Targ_FindList --
1.10      christos  367:  *     Make a complete list of GNodes from the given list of names
1.1       cgd       368:  *
1.28      wiz       369:  * Input:
                    370:  *     name            list of names to find
                    371:  *     flags           flags used if no node is found for a given name
                    372:  *
1.1       cgd       373:  * Results:
                    374:  *     A complete list of graph nodes corresponding to all instances of all
1.10      christos  375:  *     the names in names.
1.1       cgd       376:  *
                    377:  * Side Effects:
                    378:  *     If flags is TARG_CREATE, nodes will be created for all names in
                    379:  *     names which do not yet have graph nodes. If flags is TARG_NOCREATE,
                    380:  *     an error message will be printed for each name which can't be found.
                    381:  * -----------------------------------------------------------------------
                    382:  */
                    383: Lst
1.28      wiz       384: Targ_FindList(Lst names, int flags)
1.1       cgd       385: {
                    386:     Lst            nodes;      /* result list */
1.28      wiz       387:     LstNode       ln;          /* name list element */
                    388:     GNode         *gn;         /* node in tLn */
                    389:     char          *name;
1.1       cgd       390:
1.34      christos  391:     nodes = Lst_Init(FALSE);
1.1       cgd       392:
1.34      christos  393:     if (Lst_Open(names) == FAILURE) {
1.1       cgd       394:        return (nodes);
                    395:     }
1.34      christos  396:     while ((ln = Lst_Next(names)) != NILLNODE) {
1.1       cgd       397:        name = (char *)Lst_Datum(ln);
1.34      christos  398:        gn = Targ_FindNode(name, flags);
1.1       cgd       399:        if (gn != NILGNODE) {
                    400:            /*
                    401:             * Note: Lst_AtEnd must come before the Lst_Concat so the nodes
                    402:             * are added to the list in the order in which they were
                    403:             * encountered in the makefile.
                    404:             */
1.44    ! dsl       405:            (void)Lst_AtEnd(nodes, gn);
1.1       cgd       406:        } else if (flags == TARG_NOCREATE) {
1.34      christos  407:            Error("\"%s\" -- target unknown.", name);
1.1       cgd       408:        }
                    409:     }
1.34      christos  410:     Lst_Close(names);
1.1       cgd       411:     return (nodes);
                    412: }
                    413:
                    414: /*-
                    415:  *-----------------------------------------------------------------------
                    416:  * Targ_Ignore  --
                    417:  *     Return true if should ignore errors when creating gn
                    418:  *
1.28      wiz       419:  * Input:
                    420:  *     gn              node to check for
                    421:  *
1.1       cgd       422:  * Results:
                    423:  *     TRUE if should ignore errors
                    424:  *
                    425:  * Side Effects:
                    426:  *     None
                    427:  *-----------------------------------------------------------------------
                    428:  */
                    429: Boolean
1.28      wiz       430: Targ_Ignore(GNode *gn)
1.1       cgd       431: {
                    432:     if (ignoreErrors || gn->type & OP_IGNORE) {
                    433:        return (TRUE);
                    434:     } else {
                    435:        return (FALSE);
                    436:     }
                    437: }
                    438:
                    439: /*-
                    440:  *-----------------------------------------------------------------------
                    441:  * Targ_Silent  --
                    442:  *     Return true if be silent when creating gn
                    443:  *
1.28      wiz       444:  * Input:
                    445:  *     gn              node to check for
                    446:  *
1.1       cgd       447:  * Results:
                    448:  *     TRUE if should be silent
                    449:  *
                    450:  * Side Effects:
                    451:  *     None
                    452:  *-----------------------------------------------------------------------
                    453:  */
                    454: Boolean
1.28      wiz       455: Targ_Silent(GNode *gn)
1.1       cgd       456: {
                    457:     if (beSilent || gn->type & OP_SILENT) {
                    458:        return (TRUE);
                    459:     } else {
                    460:        return (FALSE);
                    461:     }
                    462: }
                    463:
                    464: /*-
                    465:  *-----------------------------------------------------------------------
                    466:  * Targ_Precious --
                    467:  *     See if the given target is precious
                    468:  *
1.28      wiz       469:  * Input:
                    470:  *     gn              the node to check
                    471:  *
1.1       cgd       472:  * Results:
                    473:  *     TRUE if it is precious. FALSE otherwise
                    474:  *
                    475:  * Side Effects:
                    476:  *     None
                    477:  *-----------------------------------------------------------------------
                    478:  */
                    479: Boolean
1.28      wiz       480: Targ_Precious(GNode *gn)
1.1       cgd       481: {
                    482:     if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP))) {
                    483:        return (TRUE);
                    484:     } else {
                    485:        return (FALSE);
                    486:     }
                    487: }
                    488:
                    489: /******************* DEBUG INFO PRINTING ****************/
                    490:
                    491: static GNode     *mainTarg;    /* the main target, as set by Targ_SetMain */
1.10      christos  492: /*-
1.1       cgd       493:  *-----------------------------------------------------------------------
                    494:  * Targ_SetMain --
                    495:  *     Set our idea of the main target we'll be creating. Used for
                    496:  *     debugging output.
                    497:  *
1.28      wiz       498:  * Input:
                    499:  *     gn              The main target we'll create
                    500:  *
1.1       cgd       501:  * Results:
                    502:  *     None.
                    503:  *
                    504:  * Side Effects:
                    505:  *     "mainTarg" is set to the main target's node.
                    506:  *-----------------------------------------------------------------------
                    507:  */
                    508: void
1.28      wiz       509: Targ_SetMain(GNode *gn)
1.1       cgd       510: {
                    511:     mainTarg = gn;
                    512: }
                    513:
1.38      dsl       514: #define PrintWait (ClientData)1
                    515: #define PrintPath (ClientData)2
                    516:
1.1       cgd       517: static int
1.38      dsl       518: TargPrintName(ClientData gnp, ClientData pflags)
1.1       cgd       519: {
1.38      dsl       520:     static int last_order;
1.37      christos  521:     GNode *gn = (GNode *)gnp;
1.38      dsl       522:
                    523:     if (pflags == PrintWait && gn->order > last_order)
1.43      dsl       524:        fprintf(debug_file, ".WAIT ");
1.38      dsl       525:     last_order = gn->order;
                    526:
1.43      dsl       527:     fprintf(debug_file, "%s ", gn->name);
1.38      dsl       528:
1.1       cgd       529: #ifdef notdef
1.38      dsl       530:     if (pflags == PrintPath) {
1.1       cgd       531:        if (gn->path) {
1.43      dsl       532:            fprintf(debug_file, "[%s]  ", gn->path);
1.1       cgd       533:        }
                    534:        if (gn == mainTarg) {
1.43      dsl       535:            fprintf(debug_file, "(MAIN NAME)  ");
1.1       cgd       536:        }
                    537:     }
1.3       cgd       538: #endif /* notdef */
1.38      dsl       539:
                    540:     return 0;
1.1       cgd       541: }
                    542:
                    543:
                    544: int
1.28      wiz       545: Targ_PrintCmd(ClientData cmd, ClientData dummy)
1.1       cgd       546: {
1.43      dsl       547:     fprintf(debug_file, "\t%s\n", (char *)cmd);
1.4       jtc       548:     return (dummy ? 0 : 0);
1.1       cgd       549: }
                    550:
                    551: /*-
                    552:  *-----------------------------------------------------------------------
                    553:  * Targ_FmtTime --
                    554:  *     Format a modification time in some reasonable way and return it.
                    555:  *
                    556:  * Results:
                    557:  *     The time reformatted.
                    558:  *
                    559:  * Side Effects:
                    560:  *     The time is placed in a static area, so it is overwritten
                    561:  *     with each call.
                    562:  *
                    563:  *-----------------------------------------------------------------------
                    564:  */
                    565: char *
1.28      wiz       566: Targ_FmtTime(time_t tm)
1.1       cgd       567: {
                    568:     struct tm          *parts;
1.15      christos  569:     static char                buf[128];
1.1       cgd       570:
1.25      reinoud   571:     parts = localtime(&tm);
1.15      christos  572:     (void)strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts);
1.1       cgd       573:     return(buf);
                    574: }
1.10      christos  575:
1.1       cgd       576: /*-
                    577:  *-----------------------------------------------------------------------
                    578:  * Targ_PrintType --
                    579:  *     Print out a type field giving only those attributes the user can
                    580:  *     set.
                    581:  *
                    582:  * Results:
                    583:  *
                    584:  * Side Effects:
                    585:  *
                    586:  *-----------------------------------------------------------------------
                    587:  */
                    588: void
1.28      wiz       589: Targ_PrintType(int type)
1.1       cgd       590: {
1.28      wiz       591:     int    tbit;
1.10      christos  592:
1.43      dsl       593: #define PRINTBIT(attr) case CONCAT(OP_,attr): fprintf(debug_file, "." #attr " "); break
                    594: #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG))fprintf(debug_file, "." #attr " "); break
1.1       cgd       595:
                    596:     type &= ~OP_OPMASK;
                    597:
                    598:     while (type) {
                    599:        tbit = 1 << (ffs(type) - 1);
                    600:        type &= ~tbit;
                    601:
                    602:        switch(tbit) {
                    603:            PRINTBIT(OPTIONAL);
                    604:            PRINTBIT(USE);
                    605:            PRINTBIT(EXEC);
                    606:            PRINTBIT(IGNORE);
                    607:            PRINTBIT(PRECIOUS);
                    608:            PRINTBIT(SILENT);
                    609:            PRINTBIT(MAKE);
                    610:            PRINTBIT(JOIN);
                    611:            PRINTBIT(INVISIBLE);
                    612:            PRINTBIT(NOTMAIN);
                    613:            PRINTDBIT(LIB);
                    614:            /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */
1.43      dsl       615:            case OP_MEMBER: if (DEBUG(TARG))fprintf(debug_file, ".MEMBER "); break;
1.1       cgd       616:            PRINTDBIT(ARCHV);
1.26      pk        617:            PRINTDBIT(MADE);
                    618:            PRINTDBIT(PHONY);
1.1       cgd       619:        }
                    620:     }
                    621: }
                    622:
                    623: /*-
                    624:  *-----------------------------------------------------------------------
                    625:  * TargPrintNode --
                    626:  *     print the contents of a node
                    627:  *-----------------------------------------------------------------------
                    628:  */
1.40      dsl       629: int
                    630: Targ_PrintNode(ClientData gnp, ClientData passp)
1.1       cgd       631: {
1.37      christos  632:     GNode         *gn = (GNode *)gnp;
1.40      dsl       633:     int                  pass = passp ? *(int *)passp : 0;
1.1       cgd       634:     if (!OP_NOP(gn->type)) {
1.43      dsl       635:        fprintf(debug_file, "#\n");
1.1       cgd       636:        if (gn == mainTarg) {
1.43      dsl       637:            fprintf(debug_file, "# *** MAIN TARGET ***\n");
1.1       cgd       638:        }
                    639:        if (pass == 2) {
                    640:            if (gn->unmade) {
1.43      dsl       641:                fprintf(debug_file, "# %d unmade children\n", gn->unmade);
1.1       cgd       642:            } else {
1.43      dsl       643:                fprintf(debug_file, "# No unmade children\n");
1.1       cgd       644:            }
1.22      christos  645:            if (! (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC))) {
1.1       cgd       646:                if (gn->mtime != 0) {
1.43      dsl       647:                    fprintf(debug_file, "# last modified %s: %s\n",
1.1       cgd       648:                              Targ_FmtTime(gn->mtime),
                    649:                              (gn->made == UNMADE ? "unmade" :
                    650:                               (gn->made == MADE ? "made" :
                    651:                                (gn->made == UPTODATE ? "up-to-date" :
                    652:                                 "error when made"))));
                    653:                } else if (gn->made != UNMADE) {
1.43      dsl       654:                    fprintf(debug_file, "# non-existent (maybe): %s\n",
1.1       cgd       655:                              (gn->made == MADE ? "made" :
                    656:                               (gn->made == UPTODATE ? "up-to-date" :
                    657:                                (gn->made == ERROR ? "error when made" :
                    658:                                 "aborted"))));
                    659:                } else {
1.43      dsl       660:                    fprintf(debug_file, "# unmade\n");
1.1       cgd       661:                }
                    662:            }
                    663:            if (!Lst_IsEmpty (gn->iParents)) {
1.43      dsl       664:                fprintf(debug_file, "# implicit parents: ");
1.44    ! dsl       665:                Lst_ForEach(gn->iParents, TargPrintName, NULL);
1.43      dsl       666:                fprintf(debug_file, "\n");
1.1       cgd       667:            }
1.41      dsl       668:        } else {
                    669:            if (gn->unmade)
1.43      dsl       670:                fprintf(debug_file, "# %d unmade children\n", gn->unmade);
1.1       cgd       671:        }
                    672:        if (!Lst_IsEmpty (gn->parents)) {
1.43      dsl       673:            fprintf(debug_file, "# parents: ");
1.44    ! dsl       674:            Lst_ForEach(gn->parents, TargPrintName, NULL);
1.43      dsl       675:            fprintf(debug_file, "\n");
1.1       cgd       676:        }
1.42      apb       677:        if (!Lst_IsEmpty (gn->children)) {
1.43      dsl       678:            fprintf(debug_file, "# children: ");
1.44    ! dsl       679:            Lst_ForEach(gn->children, TargPrintName, NULL);
1.43      dsl       680:            fprintf(debug_file, "\n");
1.42      apb       681:        }
1.39      dsl       682:        if (!Lst_IsEmpty (gn->preds)) {
1.43      dsl       683:            fprintf(debug_file, "# preds: ");
1.44    ! dsl       684:            Lst_ForEach(gn->preds, TargPrintName, NULL);
1.43      dsl       685:            fprintf(debug_file, "\n");
1.39      dsl       686:        }
1.42      apb       687:        if (!Lst_IsEmpty (gn->recpreds)) {
1.43      dsl       688:            fprintf(debug_file, "# recpreds: ");
1.44    ! dsl       689:            Lst_ForEach(gn->recpreds, TargPrintName, NULL);
1.43      dsl       690:            fprintf(debug_file, "\n");
1.42      apb       691:        }
1.39      dsl       692:        if (!Lst_IsEmpty (gn->successors)) {
1.43      dsl       693:            fprintf(debug_file, "# successors: ");
1.44    ! dsl       694:            Lst_ForEach(gn->successors, TargPrintName, NULL);
1.43      dsl       695:            fprintf(debug_file, "\n");
1.39      dsl       696:        }
1.10      christos  697:
1.43      dsl       698:        fprintf(debug_file, "%-16s", gn->name);
1.1       cgd       699:        switch (gn->type & OP_OPMASK) {
                    700:            case OP_DEPENDS:
1.43      dsl       701:                fprintf(debug_file, ": "); break;
1.1       cgd       702:            case OP_FORCE:
1.43      dsl       703:                fprintf(debug_file, "! "); break;
1.1       cgd       704:            case OP_DOUBLEDEP:
1.43      dsl       705:                fprintf(debug_file, ":: "); break;
1.1       cgd       706:        }
1.34      christos  707:        Targ_PrintType(gn->type);
1.38      dsl       708:        Lst_ForEach(gn->children, TargPrintName, PrintWait);
1.43      dsl       709:        fprintf(debug_file, "\n");
1.44    ! dsl       710:        Lst_ForEach(gn->commands, Targ_PrintCmd, NULL);
1.43      dsl       711:        fprintf(debug_file, "\n\n");
1.20      mycroft   712:        if (gn->type & OP_DOUBLEDEP) {
1.44    ! dsl       713:            Lst_ForEach(gn->cohorts, Targ_PrintNode, &pass);
1.1       cgd       714:        }
                    715:     }
                    716:     return (0);
                    717: }
                    718:
                    719: /*-
                    720:  *-----------------------------------------------------------------------
                    721:  * TargPrintOnlySrc --
                    722:  *     Print only those targets that are just a source.
                    723:  *
                    724:  * Results:
                    725:  *     0.
                    726:  *
                    727:  * Side Effects:
1.23      wiz       728:  *     The name of each file is printed preceded by #\t
1.1       cgd       729:  *
                    730:  *-----------------------------------------------------------------------
                    731:  */
                    732: static int
1.28      wiz       733: TargPrintOnlySrc(ClientData gnp, ClientData dummy)
1.4       jtc       734: {
1.37      christos  735:     GNode        *gn = (GNode *)gnp;
1.4       jtc       736:     if (OP_NOP(gn->type))
1.43      dsl       737:        fprintf(debug_file, "#\t%s [%s]\n", gn->name, gn->path ? gn->path : gn->name);
1.4       jtc       738:
                    739:     return (dummy ? 0 : 0);
1.1       cgd       740: }
                    741:
                    742: /*-
                    743:  *-----------------------------------------------------------------------
                    744:  * Targ_PrintGraph --
                    745:  *     print the entire graph. heh heh
                    746:  *
1.28      wiz       747:  * Input:
                    748:  *     pass            Which pass this is. 1 => no processing
                    749:  *                     2 => processing done
                    750:  *
1.1       cgd       751:  * Results:
                    752:  *     none
                    753:  *
                    754:  * Side Effects:
                    755:  *     lots o' output
                    756:  *-----------------------------------------------------------------------
                    757:  */
1.3       cgd       758: void
1.28      wiz       759: Targ_PrintGraph(int pass)
1.1       cgd       760: {
1.43      dsl       761:     fprintf(debug_file, "#*** Input graph:\n");
1.44    ! dsl       762:     Lst_ForEach(allTargets, Targ_PrintNode, &pass);
1.43      dsl       763:     fprintf(debug_file, "\n\n");
                    764:     fprintf(debug_file, "#\n#   Files that are only sources:\n");
1.44    ! dsl       765:     Lst_ForEach(allTargets, TargPrintOnlySrc, NULL);
1.43      dsl       766:     fprintf(debug_file, "#*** Global Variables:\n");
1.34      christos  767:     Var_Dump(VAR_GLOBAL);
1.43      dsl       768:     fprintf(debug_file, "#*** Command-line Variables:\n");
1.34      christos  769:     Var_Dump(VAR_CMD);
1.43      dsl       770:     fprintf(debug_file, "\n");
1.1       cgd       771:     Dir_PrintDirectories();
1.43      dsl       772:     fprintf(debug_file, "\n");
1.1       cgd       773:     Suff_PrintAll();
1.19      mycroft   774: }
                    775:
1.42      apb       776: /*-
                    777:  *-----------------------------------------------------------------------
                    778:  * TargAppendAncestor -
                    779:  *     Appends a single ancestor to a node's list of ancestors,
                    780:  *     ignoring duplicates.
                    781:  *
                    782:  * Input:
                    783:  *     ancestorgnp     An ancestor to be added to a list.
                    784:  *     thisgnp         The node whose ancestor list will be changed.
                    785:  *
                    786:  * Results:
                    787:  *     Always returns 0, for the benefit of Lst_ForEach().
                    788:  *
                    789:  * Side Effects:
                    790:  *     May modify the ancestors list of the node we are
                    791:  *     examining.
                    792:  *-----------------------------------------------------------------------
                    793:  */
                    794: static int
                    795: TargAppendAncestor(ClientData ancestorgnp, ClientData thisgnp)
                    796: {
                    797:     GNode        *ancestorgn = (GNode *)ancestorgnp;
                    798:     GNode        *thisgn = (GNode *)thisgnp;
                    799:
                    800:     if (Lst_Member(thisgn->ancestors, ancestorgn) == NILLNODE) {
1.44    ! dsl       801:        (void)Lst_AtEnd(thisgn->ancestors, ancestorgn);
1.42      apb       802:     }
                    803:     return (0);
                    804: }
                    805:
                    806: /*-
                    807:  *-----------------------------------------------------------------------
                    808:  * TargAppendParentAncestors -
                    809:  *     Appends all ancestors of a parent node to the ancestor list of a
                    810:  *     given node, ignoring duplicates.
                    811:  *
                    812:  * Input:
                    813:  *     parentgnp       A parent node whose ancestor list will be
                    814:  *                     propagated to another node.
                    815:  *     thisgnp         The node whose ancestor list will be changed.
                    816:  *
                    817:  * Results:
                    818:  *     Always returns 0, for the benefit of Lst_ForEach().
                    819:  *
                    820:  * Side Effects:
                    821:  *     May modify the ancestors list of the node we are
                    822:  *     examining.
                    823:  *-----------------------------------------------------------------------
                    824:  */
                    825: static int
                    826: TargAppendParentAncestors(ClientData parentgnp, ClientData thisgnp)
                    827: {
                    828:     GNode        *parentgn = (GNode *)parentgnp;
                    829:     GNode        *thisgn = (GNode *)thisgnp;
                    830:
                    831:     Lst_ForEach(parentgn->ancestors, TargAppendAncestor, thisgn);
                    832:     return (0);
                    833: }
                    834:
                    835: /*-
                    836:  *-----------------------------------------------------------------------
                    837:  * TargInitAncestors -
                    838:  *     Initialises the ancestor list of a node and all the
                    839:  *     node's ancestors.
                    840:  *
                    841:  * Input:
                    842:  *     thisgnp         The node that we are examining.
                    843:  *
                    844:  * Results:
                    845:  *     Always returns 0, for the benefit of Lst_ForEach().
                    846:  *
                    847:  * Side Effects:
                    848:  *     May initialise the ancestors list of the node we are
                    849:  *     examining and all its ancestors.  Does nothing if the
                    850:  *     list has already been initialised.
                    851:  *-----------------------------------------------------------------------
                    852:  */
1.19      mycroft   853: static int
1.42      apb       854: TargInitAncestors(ClientData thisgnp, ClientData junk __unused)
                    855: {
                    856:     GNode        *thisgn = (GNode *)thisgnp;
                    857:
                    858:     if (Lst_IsEmpty (thisgn->ancestors)) {
                    859:        /*
                    860:         * Add our parents to our ancestor list before recursing, to
                    861:         * ensure that loops in the dependency graph will not result in
                    862:         * infinite recursion.
                    863:         */
                    864:        Lst_ForEach(thisgn->parents, TargAppendAncestor, thisgn);
                    865:        Lst_ForEach(thisgn->iParents, TargAppendAncestor, thisgn);
                    866:        /* Recursively initialise our parents' ancestor lists */
1.44    ! dsl       867:        Lst_ForEach(thisgn->parents, TargInitAncestors, NULL);
        !           868:        Lst_ForEach(thisgn->iParents, TargInitAncestors, NULL);
1.42      apb       869:        /* Our parents' ancestors are also our ancestors */
                    870:        Lst_ForEach(thisgn->parents, TargAppendParentAncestors, thisgn);
                    871:        Lst_ForEach(thisgn->iParents, TargAppendParentAncestors, thisgn);
                    872:     }
                    873:     return (0);
                    874: }
                    875:
                    876: /*-
                    877:  *-----------------------------------------------------------------------
                    878:  * TargHasAncestor -
                    879:  *     Checks whether one node is an ancestor of another node.
                    880:  *
                    881:  *     If called with both arguments pointing to the
                    882:  *     same node, checks whether the node is part of a cycle
                    883:  *     in the graph.
                    884:  *
                    885:  * Input:
                    886:  *     thisgnp         The node whose ancestor list we are examining.
                    887:  *     seekgnp         The node that we are seeking in the
                    888:  *                     ancestor list.
                    889:  *
                    890:  * Results:
                    891:  *     TRUE if seekgn is an ancestor of thisgn; FALSE if not.
                    892:  *
                    893:  * Side Effects:
                    894:  *     Initialises the ancestors list in thisgnp and all its ancestors.
                    895:  *-----------------------------------------------------------------------
                    896:  */
                    897: static Boolean
                    898: TargHasAncestor(ClientData thisgnp, ClientData seekgnp)
                    899: {
                    900:     GNode        *thisgn = (GNode *)thisgnp;
                    901:     GNode        *seekgn = (GNode *)seekgnp;
                    902:
1.44    ! dsl       903:     TargInitAncestors(thisgn, NULL);
1.42      apb       904:     if (Lst_Member(thisgn->ancestors, seekgn) != NILLNODE) {
                    905:        return (TRUE);
                    906:     }
                    907:     return (FALSE);
                    908: }
                    909:
                    910: /*-
                    911:  *-----------------------------------------------------------------------
                    912:  * TargPropagateRecpredChild --
                    913:  *     Create a new predecessor/successor relationship between a pair
                    914:  *     of nodes, and recursively propagate the relationship to all
                    915:  *     children of the successor node.
                    916:  *
                    917:  *     If there is already a predecessor/successor relationship
                    918:  *     in the opposite direction, or if there is already an
                    919:  *     ancestor/descendent relationship in the oposite direction, then
                    920:  *     we avoid adding the new relationship, because that would cause a
                    921:  *     cycle in the graph.
                    922:  *
                    923:  * Input:
                    924:  *     succgnp         Successor node.
                    925:  *     predgnp         Predecessor node.
                    926:  *
                    927:  * Results:
                    928:  *     Always returns 0, for the benefit of Lst_ForEach().
                    929:  *
                    930:  * Side Effects:
                    931:  *     preds/successors information is modified for predgnp, succgnp,
                    932:  *     and recursively for all children of succgnp.
                    933:  *-----------------------------------------------------------------------
                    934:  */
                    935: static int
                    936: TargPropagateRecpredChild(ClientData succgnp, ClientData predgnp)
                    937: {
                    938:     GNode        *succgn = (GNode *)succgnp;
                    939:     GNode        *predgn = (GNode *)predgnp;
                    940:     Boolean      debugmore = FALSE;    /* how much debugging? */
                    941:
                    942:     /* Ignore if succgn == predgn */
                    943:     if (succgn == predgn) {
                    944:        if (DEBUG(TARG) && debugmore) {
1.43      dsl       945:            fprintf(debug_file, "# TargPropagateRecpredChild: not propagating %s - %s (identical)\n",
1.42      apb       946:                    predgn->name, succgn->name);
                    947:        }
                    948:        return (0);
                    949:     }
                    950:     /* Pre-existing pred/successor relationship
                    951:      * in the opposite direction takes precedence. */
                    952:     if (Lst_Member(succgn->successors, predgn) != NILLNODE) {
                    953:        if (DEBUG(TARG) && debugmore) {
1.43      dsl       954:            fprintf(debug_file, "# TargPropagateRecpredChild: not propagating %s - %s (opposite)\n",
1.42      apb       955:                    predgn->name, succgn->name);
                    956:        }
                    957:        return (0);
                    958:     }
                    959:     /* Pre-existing descendent/ancestor relationship in the opposite
                    960:      * direction takes precedence. */
                    961:     if (TargHasAncestor(succgn, predgn)) {
                    962:        if (DEBUG(TARG) && debugmore) {
1.43      dsl       963:            fprintf(debug_file, "# TargPropagateRecpredChild: not propagating %s - %s (ancestor)\n",
1.42      apb       964:                    predgn->name, succgn->name);
                    965:        }
                    966:        return (0);
                    967:     }
                    968:     /* Note the new pred/successor relationship. */
                    969:     if (DEBUG(TARG)) {
1.43      dsl       970:        fprintf(debug_file, "# TargPropagateRecpredChild: propagating %s - %s\n",
1.42      apb       971:                predgn->name, succgn->name);
                    972:     }
                    973:     if (Lst_Member(succgn->preds, predgn) == NILLNODE) {
1.44    ! dsl       974:        (void)Lst_AtEnd(succgn->preds, predgn);
        !           975:        (void)Lst_AtEnd(predgn->successors, succgn);
1.42      apb       976:     }
                    977:     /* Recurse, provided there's not a cycle. */
                    978:     if (! TargHasAncestor(succgn, succgn)) {
                    979:        Lst_ForEach(succgn->children, TargPropagateRecpredChild, predgn);
                    980:     }
                    981:     return (0);
                    982: }
                    983:
                    984: /*-
                    985:  *-----------------------------------------------------------------------
                    986:  * TargPropagateRecpred --
                    987:  *     Recursively propagate information about a single predecessor
                    988:  *     node, from a single successor node to all children of the
                    989:  *     successor node.
                    990:  *
                    991:  * Input:
                    992:  *     predgnp         Predecessor node.
                    993:  *     succgnp         Successor node.
                    994:  *
                    995:  * Results:
                    996:  *     Always returns 0, for the benefit of Lst_ForEach().
                    997:  *
                    998:  * Side Effects:
                    999:  *     preds/successors information is modified for predgnp, succgnp,
                   1000:  *     and recursively for all children of succgnp.
                   1001:  *
                   1002:  *     The real work is done by TargPropagateRecpredChild(), which
                   1003:  *     will be called for each child of the successor node.
                   1004:  *-----------------------------------------------------------------------
                   1005:  */
                   1006: static int
                   1007: TargPropagateRecpred(ClientData predgnp, ClientData succgnp)
1.19      mycroft  1008: {
1.42      apb      1009:     GNode        *predgn = (GNode *)predgnp;
                   1010:     GNode        *succgn = (GNode *)succgnp;
1.19      mycroft  1011:
1.42      apb      1012:     Lst_ForEach(succgn->children, TargPropagateRecpredChild, predgn);
1.19      mycroft  1013:     return (0);
                   1014: }
                   1015:
1.42      apb      1016: /*-
                   1017:  *-----------------------------------------------------------------------
                   1018:  * TargPropagateNode --
                   1019:  *     Propagate information from a single node to related nodes if
                   1020:  *     appropriate.
                   1021:  *
                   1022:  * Input:
                   1023:  *     gnp             The node that we are processing.
                   1024:  *
                   1025:  * Results:
                   1026:  *     Always returns 0, for the benefit of Lst_ForEach().
                   1027:  *
                   1028:  * Side Effects:
                   1029:  *     Information is propagated from this node to cohort or child
                   1030:  *     nodes.
                   1031:  *
                   1032:  *     If the node was defined with "::", then TargPropagateCohort()
                   1033:  *     will be called for each cohort node.
                   1034:  *
                   1035:  *     If the node has recursive predecessors, then
                   1036:  *     TargPropagateRecpred() will be called for each recursive
                   1037:  *     predecessor.
                   1038:  *-----------------------------------------------------------------------
                   1039:  */
1.19      mycroft  1040: static int
1.33      jmc      1041: TargPropagateNode(ClientData gnp, ClientData junk __unused)
1.19      mycroft  1042: {
1.37      christos 1043:     GNode        *gn = (GNode *)gnp;
1.20      mycroft  1044:     if (gn->type & OP_DOUBLEDEP)
1.34      christos 1045:        Lst_ForEach(gn->cohorts, TargPropagateCohort, gnp);
1.42      apb      1046:     Lst_ForEach(gn->recpreds, TargPropagateRecpred, gnp);
1.19      mycroft  1047:     return (0);
                   1048: }
                   1049:
1.42      apb      1050: /*-
                   1051:  *-----------------------------------------------------------------------
                   1052:  * TargPropagateCohort --
                   1053:  *     Propagate some bits in the type mask from a node to
                   1054:  *     a related cohort node.
                   1055:  *
                   1056:  * Input:
                   1057:  *     cnp             The node that we are processing.
                   1058:  *     gnp             Another node that has cnp as a cohort.
                   1059:  *
                   1060:  * Results:
                   1061:  *     Always returns 0, for the benefit of Lst_ForEach().
                   1062:  *
                   1063:  * Side Effects:
                   1064:  *     cnp's type bitmask is modified to incorporate some of the
                   1065:  *     bits from gnp's type bitmask.  (XXX need a better explanation.)
                   1066:  *-----------------------------------------------------------------------
                   1067:  */
                   1068: static int
                   1069: TargPropagateCohort(ClientData cgnp, ClientData pgnp)
                   1070: {
                   1071:     GNode        *cgn = (GNode *)cgnp;
                   1072:     GNode        *pgn = (GNode *)pgnp;
                   1073:
                   1074:     cgn->type |= pgn->type & ~OP_OPMASK;
                   1075:     return (0);
                   1076: }
                   1077:
                   1078: /*-
                   1079:  *-----------------------------------------------------------------------
                   1080:  * Targ_Propagate --
                   1081:  *     Propagate information between related nodes.  Should be called
                   1082:  *     after the makefiles are parsed but before any action is taken.
                   1083:  *
                   1084:  * Results:
                   1085:  *     none
                   1086:  *
                   1087:  * Side Effects:
                   1088:  *     Information is propagated between related nodes throughout the
                   1089:  *     graph.
                   1090:  *-----------------------------------------------------------------------
                   1091:  */
1.19      mycroft  1092: void
1.28      wiz      1093: Targ_Propagate(void)
1.19      mycroft  1094: {
1.44    ! dsl      1095:     Lst_ForEach(allTargets, TargPropagateNode, NULL);
1.1       cgd      1096: }

CVSweb <webmaster@jp.NetBSD.org>