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

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

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