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

1.68    ! rillig      1: /*     $NetBSD: targ.c,v 1.67 2020/08/21 04:42:02 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:
1.31      ross       71: #ifndef MAKE_NATIVE
1.68    ! rillig     72: static char rcsid[] = "$NetBSD: targ.c,v 1.67 2020/08/21 04:42:02 rillig 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.68    ! rillig     79: __RCSID("$NetBSD: targ.c,v 1.67 2020/08/21 04:42:02 rillig 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.55      dsl       147: static int TargPrintOnlySrc(void *, void *);
                    148: static int TargPrintName(void *, void *);
1.18      mycroft   149: #ifdef CLEANUP
1.55      dsl       150: static void TargFreeGN(void *);
1.18      mycroft   151: #endif
1.55      dsl       152: static int TargPropagateCohort(void *, void *);
                    153: static int TargPropagateNode(void *, void *);
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.65      rillig    170:     allTargets = Lst_Init();
1.34      christos  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.64      sjg       189:     Targ_Stats();
1.18      mycroft   190: #ifdef CLEANUP
1.54      dsl       191:     Lst_Destroy(allTargets, NULL);
1.4       jtc       192:     if (allGNs)
                    193:        Lst_Destroy(allGNs, TargFreeGN);
                    194:     Hash_DeleteTable(&targets);
1.18      mycroft   195: #endif
1.12      christos  196: }
                    197:
1.64      sjg       198: void
                    199: Targ_Stats(void)
                    200: {
                    201:     Hash_DebugStats(&targets, "targets");
                    202: }
                    203:
1.12      christos  204: /*-
                    205:  *-----------------------------------------------------------------------
                    206:  * Targ_List --
                    207:  *     Return the list of all targets
                    208:  *
                    209:  * Results:
                    210:  *     The list of all targets.
                    211:  *
                    212:  * Side Effects:
                    213:  *     None
                    214:  *-----------------------------------------------------------------------
                    215:  */
                    216: Lst
1.28      wiz       217: Targ_List(void)
1.12      christos  218: {
                    219:     return allTargets;
1.4       jtc       220: }
                    221:
                    222: /*-
                    223:  *-----------------------------------------------------------------------
1.1       cgd       224:  * Targ_NewGN  --
                    225:  *     Create and initialize a new graph node
                    226:  *
1.28      wiz       227:  * Input:
                    228:  *     name            the name to stick in the new node
                    229:  *
1.1       cgd       230:  * Results:
                    231:  *     An initialized graph node with the name field filled with a copy
                    232:  *     of the passed name
                    233:  *
                    234:  * Side Effects:
1.4       jtc       235:  *     The gnode is added to the list of all gnodes.
1.1       cgd       236:  *-----------------------------------------------------------------------
                    237:  */
                    238: GNode *
1.29      christos  239: Targ_NewGN(const char *name)
1.1       cgd       240: {
1.28      wiz       241:     GNode *gn;
1.1       cgd       242:
1.53      joerg     243:     gn = bmake_malloc(sizeof(GNode));
                    244:     gn->name = bmake_strdup(name);
1.11      christos  245:     gn->uname = NULL;
1.29      christos  246:     gn->path = NULL;
1.1       cgd       247:     if (name[0] == '-' && name[1] == 'l') {
                    248:        gn->type = OP_LIB;
                    249:     } else {
                    250:        gn->type = 0;
                    251:     }
                    252:     gn->unmade =       0;
1.27      pk        253:     gn->unmade_cohorts = 0;
1.45      dsl       254:     gn->cohort_num[0] = 0;
1.27      pk        255:     gn->centurion =            NULL;
1.1       cgd       256:     gn->made =                 UNMADE;
1.16      christos  257:     gn->flags =        0;
1.56      christos  258:     gn->checked =      0;
                    259:     gn->mtime =                0;
                    260:     gn->cmgn =         NULL;
1.65      rillig    261:     gn->iParents =     Lst_Init();
                    262:     gn->cohorts =      Lst_Init();
                    263:     gn->parents =      Lst_Init();
                    264:     gn->children =     Lst_Init();
                    265:     gn->order_pred =   Lst_Init();
                    266:     gn->order_succ =   Lst_Init();
1.17      mycroft   267:     Hash_InitTable(&gn->context, 0);
1.65      rillig    268:     gn->commands =     Lst_Init();
1.3       cgd       269:     gn->suffix =       NULL;
1.21      christos  270:     gn->lineno =       0;
                    271:     gn->fname =        NULL;
1.1       cgd       272:
1.18      mycroft   273: #ifdef CLEANUP
1.4       jtc       274:     if (allGNs == NULL)
1.65      rillig    275:        allGNs = Lst_Init();
1.44      dsl       276:     Lst_AtEnd(allGNs, gn);
1.18      mycroft   277: #endif
1.4       jtc       278:
1.63      rillig    279:     return gn;
1.1       cgd       280: }
                    281:
1.18      mycroft   282: #ifdef CLEANUP
1.1       cgd       283: /*-
                    284:  *-----------------------------------------------------------------------
1.4       jtc       285:  * TargFreeGN  --
                    286:  *     Destroy a GNode
                    287:  *
                    288:  * Results:
                    289:  *     None.
                    290:  *
                    291:  * Side Effects:
                    292:  *     None.
                    293:  *-----------------------------------------------------------------------
                    294:  */
                    295: static void
1.55      dsl       296: TargFreeGN(void *gnp)
1.4       jtc       297: {
1.37      christos  298:     GNode *gn = (GNode *)gnp;
1.4       jtc       299:
                    300:
                    301:     free(gn->name);
1.61      christos  302:     free(gn->uname);
                    303:     free(gn->path);
1.46      dsl       304:     /* gn->fname points to name allocated when file was opened, don't free */
1.4       jtc       305:
1.54      dsl       306:     Lst_Destroy(gn->iParents, NULL);
                    307:     Lst_Destroy(gn->cohorts, NULL);
                    308:     Lst_Destroy(gn->parents, NULL);
                    309:     Lst_Destroy(gn->children, NULL);
                    310:     Lst_Destroy(gn->order_succ, NULL);
                    311:     Lst_Destroy(gn->order_pred, NULL);
1.17      mycroft   312:     Hash_DeleteTable(&gn->context);
1.54      dsl       313:     Lst_Destroy(gn->commands, NULL);
1.36      christos  314:     free(gn);
1.4       jtc       315: }
1.18      mycroft   316: #endif
1.4       jtc       317:
                    318:
                    319: /*-
                    320:  *-----------------------------------------------------------------------
1.1       cgd       321:  * Targ_FindNode  --
                    322:  *     Find a node in the list using the given name for matching
                    323:  *
1.28      wiz       324:  * Input:
                    325:  *     name            the name to find
                    326:  *     flags           flags governing events when target not
                    327:  *                     found
                    328:  *
1.1       cgd       329:  * Results:
1.54      dsl       330:  *     The node in the list if it was. If it wasn't, return NULL of
1.1       cgd       331:  *     flags was TARG_NOCREATE or the newly created and initialized node
                    332:  *     if it was TARG_CREATE
                    333:  *
                    334:  * Side Effects:
                    335:  *     Sometimes a node is created and added to the list
                    336:  *-----------------------------------------------------------------------
                    337:  */
                    338: GNode *
1.29      christos  339: Targ_FindNode(const char *name, int flags)
1.1       cgd       340: {
                    341:     GNode         *gn;       /* node in that element */
1.60      manu      342:     Hash_Entry   *he = NULL; /* New or used hash entry for node */
1.1       cgd       343:     Boolean      isNew;      /* Set TRUE if Hash_CreateEntry had to create */
                    344:                              /* an entry for the node */
                    345:
1.45      dsl       346:     if (!(flags & (TARG_CREATE | TARG_NOHASH))) {
                    347:        he = Hash_FindEntry(&targets, name);
                    348:        if (he == NULL)
1.54      dsl       349:            return NULL;
1.45      dsl       350:        return (GNode *)Hash_GetValue(he);
                    351:     }
1.1       cgd       352:
1.45      dsl       353:     if (!(flags & TARG_NOHASH)) {
1.34      christos  354:        he = Hash_CreateEntry(&targets, name, &isNew);
1.45      dsl       355:        if (!isNew)
                    356:            return (GNode *)Hash_GetValue(he);
1.1       cgd       357:     }
                    358:
1.45      dsl       359:     gn = Targ_NewGN(name);
                    360:     if (!(flags & TARG_NOHASH))
                    361:        Hash_SetValue(he, gn);
                    362:     Var_Append(".ALLTARGETS", name, VAR_GLOBAL);
1.68    ! rillig    363:     Lst_AppendS(allTargets, gn);
1.50      dsl       364:     if (doing_depend)
                    365:        gn->flags |= FROM_DEPEND;
1.45      dsl       366:     return gn;
1.1       cgd       367: }
                    368:
                    369: /*-
                    370:  *-----------------------------------------------------------------------
                    371:  * Targ_FindList --
1.10      christos  372:  *     Make a complete list of GNodes from the given list of names
1.1       cgd       373:  *
1.28      wiz       374:  * Input:
                    375:  *     name            list of names to find
                    376:  *     flags           flags used if no node is found for a given name
                    377:  *
1.1       cgd       378:  * Results:
                    379:  *     A complete list of graph nodes corresponding to all instances of all
1.10      christos  380:  *     the names in names.
1.1       cgd       381:  *
                    382:  * Side Effects:
                    383:  *     If flags is TARG_CREATE, nodes will be created for all names in
                    384:  *     names which do not yet have graph nodes. If flags is TARG_NOCREATE,
                    385:  *     an error message will be printed for each name which can't be found.
                    386:  * -----------------------------------------------------------------------
                    387:  */
                    388: Lst
1.28      wiz       389: Targ_FindList(Lst names, int flags)
1.1       cgd       390: {
                    391:     Lst            nodes;      /* result list */
1.28      wiz       392:     LstNode       ln;          /* name list element */
                    393:     GNode         *gn;         /* node in tLn */
                    394:     char          *name;
1.1       cgd       395:
1.65      rillig    396:     nodes = Lst_Init();
1.1       cgd       397:
1.67      rillig    398:     Lst_OpenS(names);
1.66      rillig    399:     while ((ln = Lst_NextS(names)) != NULL) {
1.1       cgd       400:        name = (char *)Lst_Datum(ln);
1.34      christos  401:        gn = Targ_FindNode(name, flags);
1.54      dsl       402:        if (gn != NULL) {
1.1       cgd       403:            /*
                    404:             * Note: Lst_AtEnd must come before the Lst_Concat so the nodes
                    405:             * are added to the list in the order in which they were
                    406:             * encountered in the makefile.
                    407:             */
1.68    ! rillig    408:            Lst_AppendS(nodes, gn);
1.1       cgd       409:        } else if (flags == TARG_NOCREATE) {
1.34      christos  410:            Error("\"%s\" -- target unknown.", name);
1.1       cgd       411:        }
                    412:     }
1.67      rillig    413:     Lst_CloseS(names);
1.63      rillig    414:     return nodes;
1.1       cgd       415: }
                    416:
                    417: /*-
                    418:  *-----------------------------------------------------------------------
                    419:  * Targ_Ignore  --
                    420:  *     Return true if should ignore errors when creating gn
                    421:  *
1.28      wiz       422:  * Input:
                    423:  *     gn              node to check for
                    424:  *
1.1       cgd       425:  * Results:
                    426:  *     TRUE if should ignore errors
                    427:  *
                    428:  * Side Effects:
                    429:  *     None
                    430:  *-----------------------------------------------------------------------
                    431:  */
                    432: Boolean
1.28      wiz       433: Targ_Ignore(GNode *gn)
1.1       cgd       434: {
                    435:     if (ignoreErrors || gn->type & OP_IGNORE) {
1.63      rillig    436:        return TRUE;
1.1       cgd       437:     } else {
1.63      rillig    438:        return FALSE;
1.1       cgd       439:     }
                    440: }
                    441:
                    442: /*-
                    443:  *-----------------------------------------------------------------------
                    444:  * Targ_Silent  --
                    445:  *     Return true if be silent when creating gn
                    446:  *
1.28      wiz       447:  * Input:
                    448:  *     gn              node to check for
                    449:  *
1.1       cgd       450:  * Results:
                    451:  *     TRUE if should be silent
                    452:  *
                    453:  * Side Effects:
                    454:  *     None
                    455:  *-----------------------------------------------------------------------
                    456:  */
                    457: Boolean
1.28      wiz       458: Targ_Silent(GNode *gn)
1.1       cgd       459: {
                    460:     if (beSilent || gn->type & OP_SILENT) {
1.63      rillig    461:        return TRUE;
1.1       cgd       462:     } else {
1.63      rillig    463:        return FALSE;
1.1       cgd       464:     }
                    465: }
                    466:
                    467: /*-
                    468:  *-----------------------------------------------------------------------
                    469:  * Targ_Precious --
                    470:  *     See if the given target is precious
                    471:  *
1.28      wiz       472:  * Input:
                    473:  *     gn              the node to check
                    474:  *
1.1       cgd       475:  * Results:
                    476:  *     TRUE if it is precious. FALSE otherwise
                    477:  *
                    478:  * Side Effects:
                    479:  *     None
                    480:  *-----------------------------------------------------------------------
                    481:  */
                    482: Boolean
1.28      wiz       483: Targ_Precious(GNode *gn)
1.1       cgd       484: {
                    485:     if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP))) {
1.63      rillig    486:        return TRUE;
1.1       cgd       487:     } else {
1.63      rillig    488:        return FALSE;
1.1       cgd       489:     }
                    490: }
                    491:
                    492: /******************* DEBUG INFO PRINTING ****************/
                    493:
                    494: static GNode     *mainTarg;    /* the main target, as set by Targ_SetMain */
1.10      christos  495: /*-
1.1       cgd       496:  *-----------------------------------------------------------------------
                    497:  * Targ_SetMain --
                    498:  *     Set our idea of the main target we'll be creating. Used for
                    499:  *     debugging output.
                    500:  *
1.28      wiz       501:  * Input:
                    502:  *     gn              The main target we'll create
                    503:  *
1.1       cgd       504:  * Results:
                    505:  *     None.
                    506:  *
                    507:  * Side Effects:
                    508:  *     "mainTarg" is set to the main target's node.
                    509:  *-----------------------------------------------------------------------
                    510:  */
                    511: void
1.28      wiz       512: Targ_SetMain(GNode *gn)
1.1       cgd       513: {
                    514:     mainTarg = gn;
                    515: }
                    516:
                    517: static int
1.57      joerg     518: TargPrintName(void *gnp, void *pflags MAKE_ATTR_UNUSED)
1.1       cgd       519: {
1.37      christos  520:     GNode *gn = (GNode *)gnp;
1.38      dsl       521:
1.45      dsl       522:     fprintf(debug_file, "%s%s ", gn->name, gn->cohort_num);
1.38      dsl       523:
                    524:     return 0;
1.1       cgd       525: }
                    526:
                    527:
                    528: int
1.62      riastrad  529: Targ_PrintCmd(void *cmd, void *dummy MAKE_ATTR_UNUSED)
1.1       cgd       530: {
1.43      dsl       531:     fprintf(debug_file, "\t%s\n", (char *)cmd);
1.62      riastrad  532:     return 0;
1.1       cgd       533: }
                    534:
                    535: /*-
                    536:  *-----------------------------------------------------------------------
                    537:  * Targ_FmtTime --
                    538:  *     Format a modification time in some reasonable way and return it.
                    539:  *
                    540:  * Results:
                    541:  *     The time reformatted.
                    542:  *
                    543:  * Side Effects:
                    544:  *     The time is placed in a static area, so it is overwritten
                    545:  *     with each call.
                    546:  *
                    547:  *-----------------------------------------------------------------------
                    548:  */
                    549: char *
1.28      wiz       550: Targ_FmtTime(time_t tm)
1.1       cgd       551: {
                    552:     struct tm          *parts;
1.15      christos  553:     static char                buf[128];
1.1       cgd       554:
1.25      reinoud   555:     parts = localtime(&tm);
1.15      christos  556:     (void)strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts);
1.63      rillig    557:     return buf;
1.1       cgd       558: }
1.10      christos  559:
1.1       cgd       560: /*-
                    561:  *-----------------------------------------------------------------------
                    562:  * Targ_PrintType --
                    563:  *     Print out a type field giving only those attributes the user can
                    564:  *     set.
                    565:  *
                    566:  * Results:
                    567:  *
                    568:  * Side Effects:
                    569:  *
                    570:  *-----------------------------------------------------------------------
                    571:  */
                    572: void
1.52      christos  573: Targ_PrintType(int type)
1.1       cgd       574: {
1.28      wiz       575:     int    tbit;
1.10      christos  576:
1.43      dsl       577: #define PRINTBIT(attr) case CONCAT(OP_,attr): fprintf(debug_file, "." #attr " "); break
                    578: #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG))fprintf(debug_file, "." #attr " "); break
1.1       cgd       579:
                    580:     type &= ~OP_OPMASK;
                    581:
                    582:     while (type) {
1.52      christos  583:        tbit = 1 << (ffs(type) - 1);
1.1       cgd       584:        type &= ~tbit;
                    585:
                    586:        switch(tbit) {
                    587:            PRINTBIT(OPTIONAL);
                    588:            PRINTBIT(USE);
                    589:            PRINTBIT(EXEC);
                    590:            PRINTBIT(IGNORE);
                    591:            PRINTBIT(PRECIOUS);
                    592:            PRINTBIT(SILENT);
                    593:            PRINTBIT(MAKE);
                    594:            PRINTBIT(JOIN);
                    595:            PRINTBIT(INVISIBLE);
                    596:            PRINTBIT(NOTMAIN);
                    597:            PRINTDBIT(LIB);
                    598:            /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */
1.43      dsl       599:            case OP_MEMBER: if (DEBUG(TARG))fprintf(debug_file, ".MEMBER "); break;
1.1       cgd       600:            PRINTDBIT(ARCHV);
1.26      pk        601:            PRINTDBIT(MADE);
                    602:            PRINTDBIT(PHONY);
1.1       cgd       603:        }
                    604:     }
                    605: }
                    606:
1.45      dsl       607: static const char *
                    608: made_name(enum enum_made made)
                    609: {
                    610:     switch (made) {
                    611:     case UNMADE:     return "unmade";
                    612:     case DEFERRED:   return "deferred";
                    613:     case REQUESTED:  return "requested";
                    614:     case BEINGMADE:  return "being made";
                    615:     case MADE:       return "made";
                    616:     case UPTODATE:   return "up-to-date";
                    617:     case ERROR:      return "error when made";
                    618:     case ABORTED:    return "aborted";
                    619:     default:         return "unknown enum_made value";
                    620:     }
                    621: }
                    622:
1.1       cgd       623: /*-
                    624:  *-----------------------------------------------------------------------
                    625:  * TargPrintNode --
                    626:  *     print the contents of a node
                    627:  *-----------------------------------------------------------------------
                    628:  */
1.40      dsl       629: int
1.55      dsl       630: Targ_PrintNode(void *gnp, void *passp)
1.1       cgd       631: {
1.37      christos  632:     GNode         *gn = (GNode *)gnp;
1.40      dsl       633:     int                  pass = passp ? *(int *)passp : 0;
1.45      dsl       634:
                    635:     fprintf(debug_file, "# %s%s, flags %x, type %x, made %d\n",
                    636:            gn->name, gn->cohort_num, gn->flags, gn->type, gn->made);
                    637:     if (gn->flags == 0)
                    638:        return 0;
                    639:
1.1       cgd       640:     if (!OP_NOP(gn->type)) {
1.43      dsl       641:        fprintf(debug_file, "#\n");
1.1       cgd       642:        if (gn == mainTarg) {
1.43      dsl       643:            fprintf(debug_file, "# *** MAIN TARGET ***\n");
1.1       cgd       644:        }
1.45      dsl       645:        if (pass >= 2) {
1.1       cgd       646:            if (gn->unmade) {
1.43      dsl       647:                fprintf(debug_file, "# %d unmade children\n", gn->unmade);
1.1       cgd       648:            } else {
1.43      dsl       649:                fprintf(debug_file, "# No unmade children\n");
1.1       cgd       650:            }
1.22      christos  651:            if (! (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC))) {
1.1       cgd       652:                if (gn->mtime != 0) {
1.43      dsl       653:                    fprintf(debug_file, "# last modified %s: %s\n",
1.1       cgd       654:                              Targ_FmtTime(gn->mtime),
1.45      dsl       655:                              made_name(gn->made));
1.1       cgd       656:                } else if (gn->made != UNMADE) {
1.43      dsl       657:                    fprintf(debug_file, "# non-existent (maybe): %s\n",
1.45      dsl       658:                              made_name(gn->made));
1.1       cgd       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.45      dsl       677:        if (!Lst_IsEmpty (gn->order_pred)) {
                    678:            fprintf(debug_file, "# order_pred: ");
                    679:            Lst_ForEach(gn->order_pred, TargPrintName, NULL);
1.43      dsl       680:            fprintf(debug_file, "\n");
1.42      apb       681:        }
1.45      dsl       682:        if (!Lst_IsEmpty (gn->order_succ)) {
                    683:            fprintf(debug_file, "# order_succ: ");
                    684:            Lst_ForEach(gn->order_succ, TargPrintName, NULL);
1.43      dsl       685:            fprintf(debug_file, "\n");
1.39      dsl       686:        }
1.10      christos  687:
1.43      dsl       688:        fprintf(debug_file, "%-16s", gn->name);
1.1       cgd       689:        switch (gn->type & OP_OPMASK) {
                    690:            case OP_DEPENDS:
1.43      dsl       691:                fprintf(debug_file, ": "); break;
1.1       cgd       692:            case OP_FORCE:
1.43      dsl       693:                fprintf(debug_file, "! "); break;
1.1       cgd       694:            case OP_DOUBLEDEP:
1.43      dsl       695:                fprintf(debug_file, ":: "); break;
1.1       cgd       696:        }
1.34      christos  697:        Targ_PrintType(gn->type);
1.45      dsl       698:        Lst_ForEach(gn->children, TargPrintName, NULL);
1.43      dsl       699:        fprintf(debug_file, "\n");
1.44      dsl       700:        Lst_ForEach(gn->commands, Targ_PrintCmd, NULL);
1.43      dsl       701:        fprintf(debug_file, "\n\n");
1.20      mycroft   702:        if (gn->type & OP_DOUBLEDEP) {
1.44      dsl       703:            Lst_ForEach(gn->cohorts, Targ_PrintNode, &pass);
1.1       cgd       704:        }
                    705:     }
1.63      rillig    706:     return 0;
1.1       cgd       707: }
                    708:
                    709: /*-
                    710:  *-----------------------------------------------------------------------
                    711:  * TargPrintOnlySrc --
                    712:  *     Print only those targets that are just a source.
                    713:  *
                    714:  * Results:
                    715:  *     0.
                    716:  *
                    717:  * Side Effects:
1.23      wiz       718:  *     The name of each file is printed preceded by #\t
1.1       cgd       719:  *
                    720:  *-----------------------------------------------------------------------
                    721:  */
                    722: static int
1.57      joerg     723: TargPrintOnlySrc(void *gnp, void *dummy MAKE_ATTR_UNUSED)
1.4       jtc       724: {
1.37      christos  725:     GNode        *gn = (GNode *)gnp;
1.45      dsl       726:     if (!OP_NOP(gn->type))
                    727:        return 0;
1.4       jtc       728:
1.45      dsl       729:     fprintf(debug_file, "#\t%s [%s] ",
                    730:            gn->name, gn->path ? gn->path : gn->name);
                    731:     Targ_PrintType(gn->type);
                    732:     fprintf(debug_file, "\n");
                    733:
                    734:     return 0;
1.1       cgd       735: }
                    736:
                    737: /*-
                    738:  *-----------------------------------------------------------------------
                    739:  * Targ_PrintGraph --
                    740:  *     print the entire graph. heh heh
                    741:  *
1.28      wiz       742:  * Input:
                    743:  *     pass            Which pass this is. 1 => no processing
                    744:  *                     2 => processing done
                    745:  *
1.1       cgd       746:  * Results:
                    747:  *     none
                    748:  *
                    749:  * Side Effects:
                    750:  *     lots o' output
                    751:  *-----------------------------------------------------------------------
                    752:  */
1.3       cgd       753: void
1.28      wiz       754: Targ_PrintGraph(int pass)
1.1       cgd       755: {
1.43      dsl       756:     fprintf(debug_file, "#*** Input graph:\n");
1.44      dsl       757:     Lst_ForEach(allTargets, Targ_PrintNode, &pass);
1.43      dsl       758:     fprintf(debug_file, "\n\n");
                    759:     fprintf(debug_file, "#\n#   Files that are only sources:\n");
1.44      dsl       760:     Lst_ForEach(allTargets, TargPrintOnlySrc, NULL);
1.43      dsl       761:     fprintf(debug_file, "#*** Global Variables:\n");
1.34      christos  762:     Var_Dump(VAR_GLOBAL);
1.43      dsl       763:     fprintf(debug_file, "#*** Command-line Variables:\n");
1.34      christos  764:     Var_Dump(VAR_CMD);
1.43      dsl       765:     fprintf(debug_file, "\n");
1.1       cgd       766:     Dir_PrintDirectories();
1.43      dsl       767:     fprintf(debug_file, "\n");
1.1       cgd       768:     Suff_PrintAll();
1.19      mycroft   769: }
                    770:
1.42      apb       771: /*-
                    772:  *-----------------------------------------------------------------------
                    773:  * TargPropagateNode --
                    774:  *     Propagate information from a single node to related nodes if
                    775:  *     appropriate.
                    776:  *
                    777:  * Input:
                    778:  *     gnp             The node that we are processing.
                    779:  *
                    780:  * Results:
                    781:  *     Always returns 0, for the benefit of Lst_ForEach().
                    782:  *
                    783:  * Side Effects:
                    784:  *     Information is propagated from this node to cohort or child
                    785:  *     nodes.
                    786:  *
                    787:  *     If the node was defined with "::", then TargPropagateCohort()
                    788:  *     will be called for each cohort node.
                    789:  *
                    790:  *     If the node has recursive predecessors, then
                    791:  *     TargPropagateRecpred() will be called for each recursive
                    792:  *     predecessor.
                    793:  *-----------------------------------------------------------------------
                    794:  */
1.19      mycroft   795: static int
1.57      joerg     796: TargPropagateNode(void *gnp, void *junk MAKE_ATTR_UNUSED)
1.19      mycroft   797: {
1.37      christos  798:     GNode        *gn = (GNode *)gnp;
1.45      dsl       799:
1.20      mycroft   800:     if (gn->type & OP_DOUBLEDEP)
1.34      christos  801:        Lst_ForEach(gn->cohorts, TargPropagateCohort, gnp);
1.63      rillig    802:     return 0;
1.19      mycroft   803: }
                    804:
1.42      apb       805: /*-
                    806:  *-----------------------------------------------------------------------
                    807:  * TargPropagateCohort --
                    808:  *     Propagate some bits in the type mask from a node to
                    809:  *     a related cohort node.
                    810:  *
                    811:  * Input:
                    812:  *     cnp             The node that we are processing.
                    813:  *     gnp             Another node that has cnp as a cohort.
                    814:  *
                    815:  * Results:
                    816:  *     Always returns 0, for the benefit of Lst_ForEach().
                    817:  *
                    818:  * Side Effects:
                    819:  *     cnp's type bitmask is modified to incorporate some of the
                    820:  *     bits from gnp's type bitmask.  (XXX need a better explanation.)
                    821:  *-----------------------------------------------------------------------
                    822:  */
                    823: static int
1.55      dsl       824: TargPropagateCohort(void *cgnp, void *pgnp)
1.42      apb       825: {
                    826:     GNode        *cgn = (GNode *)cgnp;
                    827:     GNode        *pgn = (GNode *)pgnp;
                    828:
                    829:     cgn->type |= pgn->type & ~OP_OPMASK;
1.63      rillig    830:     return 0;
1.42      apb       831: }
                    832:
                    833: /*-
                    834:  *-----------------------------------------------------------------------
                    835:  * Targ_Propagate --
                    836:  *     Propagate information between related nodes.  Should be called
                    837:  *     after the makefiles are parsed but before any action is taken.
                    838:  *
                    839:  * Results:
                    840:  *     none
                    841:  *
                    842:  * Side Effects:
                    843:  *     Information is propagated between related nodes throughout the
                    844:  *     graph.
                    845:  *-----------------------------------------------------------------------
                    846:  */
1.19      mycroft   847: void
1.28      wiz       848: Targ_Propagate(void)
1.19      mycroft   849: {
1.44      dsl       850:     Lst_ForEach(allTargets, TargPropagateNode, NULL);
1.1       cgd       851: }

CVSweb <webmaster@jp.NetBSD.org>