~ubuntu-branches/ubuntu/trusty/bmake/trusty-proposed

« back to all changes in this revision

Viewing changes to targ.c

  • Committer: Package Import Robot
  • Author(s): Andrew Shadura
  • Date: 2013-09-22 16:07:33 UTC
  • Revision ID: package-import@ubuntu.com-20130922160733-9cvmsi7z0jswtrbi
Tags: upstream-20130904
ImportĀ upstreamĀ versionĀ 20130904

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*      $NetBSD: targ.c,v 1.57 2012/06/12 19:21:51 joerg Exp $  */
 
2
 
 
3
/*
 
4
 * Copyright (c) 1988, 1989, 1990, 1993
 
5
 *      The Regents of the University of California.  All rights reserved.
 
6
 *
 
7
 * This code is derived from software contributed to Berkeley by
 
8
 * Adam de Boor.
 
9
 *
 
10
 * Redistribution and use in source and binary forms, 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
/*
 
36
 * Copyright (c) 1989 by Berkeley Softworks
 
37
 * All rights reserved.
 
38
 *
 
39
 * This code is derived from software contributed to Berkeley by
 
40
 * Adam de Boor.
 
41
 *
 
42
 * Redistribution and use in source and binary forms, with or without
 
43
 * modification, are permitted provided that the following conditions
 
44
 * are met:
 
45
 * 1. Redistributions of source code must retain the above copyright
 
46
 *    notice, this list of conditions and the following disclaimer.
 
47
 * 2. Redistributions in binary form must reproduce the above copyright
 
48
 *    notice, this list of conditions and the following disclaimer in the
 
49
 *    documentation and/or other materials provided with the distribution.
 
50
 * 3. All advertising materials mentioning features or use of this software
 
51
 *    must display the following acknowledgement:
 
52
 *      This product includes software developed by the University of
 
53
 *      California, Berkeley and its contributors.
 
54
 * 4. Neither the name of the University nor the names of its contributors
 
55
 *    may be used to endorse or promote products derived from this software
 
56
 *    without specific prior written permission.
 
57
 *
 
58
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 
59
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
60
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
61
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 
62
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
63
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
64
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
65
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
66
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
67
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
68
 * SUCH DAMAGE.
 
69
 */
 
70
 
 
71
#ifndef MAKE_NATIVE
 
72
static char rcsid[] = "$NetBSD: targ.c,v 1.57 2012/06/12 19:21:51 joerg Exp $";
 
73
#else
 
74
#include <sys/cdefs.h>
 
75
#ifndef lint
 
76
#if 0
 
77
static char sccsid[] = "@(#)targ.c      8.2 (Berkeley) 3/19/94";
 
78
#else
 
79
__RCSID("$NetBSD: targ.c,v 1.57 2012/06/12 19:21:51 joerg Exp $");
 
80
#endif
 
81
#endif /* not lint */
 
82
#endif
 
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
 *
 
93
 *      Targ_End                Cleanup the module
 
94
 *
 
95
 *      Targ_List               Return the list of all targets so far.
 
96
 *
 
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
 *
 
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
 *
 
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>
 
134
 
 
135
#include          "make.h"
 
136
#include          "hash.h"
 
137
#include          "dir.h"
 
138
 
 
139
static Lst        allTargets;   /* the list of all targets found so far */
 
140
#ifdef CLEANUP
 
141
static Lst        allGNs;       /* List of all the GNodes */
 
142
#endif
 
143
static Hash_Table targets;      /* a hash table of same */
 
144
 
 
145
#define HTSIZE  191             /* initial size of hash table */
 
146
 
 
147
static int TargPrintOnlySrc(void *, void *);
 
148
static int TargPrintName(void *, void *);
 
149
#ifdef CLEANUP
 
150
static void TargFreeGN(void *);
 
151
#endif
 
152
static int TargPropagateCohort(void *, void *);
 
153
static int TargPropagateNode(void *, void *);
 
154
 
 
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
 
168
Targ_Init(void)
 
169
{
 
170
    allTargets = Lst_Init(FALSE);
 
171
    Hash_InitTable(&targets, HTSIZE);
 
172
}
 
173
 
 
174
/*-
 
175
 *-----------------------------------------------------------------------
 
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
 
187
Targ_End(void)
 
188
{
 
189
#ifdef CLEANUP
 
190
    Lst_Destroy(allTargets, NULL);
 
191
    if (allGNs)
 
192
        Lst_Destroy(allGNs, TargFreeGN);
 
193
    Hash_DeleteTable(&targets);
 
194
#endif
 
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
 
210
Targ_List(void)
 
211
{
 
212
    return allTargets;
 
213
}
 
214
 
 
215
/*-
 
216
 *-----------------------------------------------------------------------
 
217
 * Targ_NewGN  --
 
218
 *      Create and initialize a new graph node
 
219
 *
 
220
 * Input:
 
221
 *      name            the name to stick in the new node
 
222
 *
 
223
 * Results:
 
224
 *      An initialized graph node with the name field filled with a copy
 
225
 *      of the passed name
 
226
 *
 
227
 * Side Effects:
 
228
 *      The gnode is added to the list of all gnodes.
 
229
 *-----------------------------------------------------------------------
 
230
 */
 
231
GNode *
 
232
Targ_NewGN(const char *name)
 
233
{
 
234
    GNode *gn;
 
235
 
 
236
    gn = bmake_malloc(sizeof(GNode));
 
237
    gn->name = bmake_strdup(name);
 
238
    gn->uname = NULL;
 
239
    gn->path = NULL;
 
240
    if (name[0] == '-' && name[1] == 'l') {
 
241
        gn->type = OP_LIB;
 
242
    } else {
 
243
        gn->type = 0;
 
244
    }
 
245
    gn->unmade =        0;
 
246
    gn->unmade_cohorts = 0;
 
247
    gn->cohort_num[0] = 0;
 
248
    gn->centurion =     NULL;
 
249
    gn->made =          UNMADE;
 
250
    gn->flags =         0;
 
251
    gn->checked =       0;
 
252
    gn->mtime =         0;
 
253
    gn->cmgn =          NULL;
 
254
    gn->iParents =      Lst_Init(FALSE);
 
255
    gn->cohorts =       Lst_Init(FALSE);
 
256
    gn->parents =       Lst_Init(FALSE);
 
257
    gn->children =      Lst_Init(FALSE);
 
258
    gn->order_pred =    Lst_Init(FALSE);
 
259
    gn->order_succ =    Lst_Init(FALSE);
 
260
    Hash_InitTable(&gn->context, 0);
 
261
    gn->commands =      Lst_Init(FALSE);
 
262
    gn->suffix =        NULL;
 
263
    gn->lineno =        0;
 
264
    gn->fname =         NULL;
 
265
 
 
266
#ifdef CLEANUP
 
267
    if (allGNs == NULL)
 
268
        allGNs = Lst_Init(FALSE);
 
269
    Lst_AtEnd(allGNs, gn);
 
270
#endif
 
271
 
 
272
    return (gn);
 
273
}
 
274
 
 
275
#ifdef CLEANUP
 
276
/*-
 
277
 *-----------------------------------------------------------------------
 
278
 * TargFreeGN  --
 
279
 *      Destroy a GNode
 
280
 *
 
281
 * Results:
 
282
 *      None.
 
283
 *
 
284
 * Side Effects:
 
285
 *      None.
 
286
 *-----------------------------------------------------------------------
 
287
 */
 
288
static void
 
289
TargFreeGN(void *gnp)
 
290
{
 
291
    GNode *gn = (GNode *)gnp;
 
292
 
 
293
 
 
294
    free(gn->name);
 
295
    if (gn->uname)
 
296
        free(gn->uname);
 
297
    if (gn->path)
 
298
        free(gn->path);
 
299
    /* gn->fname points to name allocated when file was opened, don't free */
 
300
 
 
301
    Lst_Destroy(gn->iParents, NULL);
 
302
    Lst_Destroy(gn->cohorts, NULL);
 
303
    Lst_Destroy(gn->parents, NULL);
 
304
    Lst_Destroy(gn->children, NULL);
 
305
    Lst_Destroy(gn->order_succ, NULL);
 
306
    Lst_Destroy(gn->order_pred, NULL);
 
307
    Hash_DeleteTable(&gn->context);
 
308
    Lst_Destroy(gn->commands, NULL);
 
309
    free(gn);
 
310
}
 
311
#endif
 
312
 
 
313
 
 
314
/*-
 
315
 *-----------------------------------------------------------------------
 
316
 * Targ_FindNode  --
 
317
 *      Find a node in the list using the given name for matching
 
318
 *
 
319
 * Input:
 
320
 *      name            the name to find
 
321
 *      flags           flags governing events when target not
 
322
 *                      found
 
323
 *
 
324
 * Results:
 
325
 *      The node in the list if it was. If it wasn't, return NULL of
 
326
 *      flags was TARG_NOCREATE or the newly created and initialized node
 
327
 *      if it was TARG_CREATE
 
328
 *
 
329
 * Side Effects:
 
330
 *      Sometimes a node is created and added to the list
 
331
 *-----------------------------------------------------------------------
 
332
 */
 
333
GNode *
 
334
Targ_FindNode(const char *name, int flags)
 
335
{
 
336
    GNode         *gn;        /* node in that element */
 
337
    Hash_Entry    *he = NULL; /* New or used hash entry for node */
 
338
    Boolean       isNew;      /* Set TRUE if Hash_CreateEntry had to create */
 
339
                              /* an entry for the node */
 
340
 
 
341
    if (!(flags & (TARG_CREATE | TARG_NOHASH))) {
 
342
        he = Hash_FindEntry(&targets, name);
 
343
        if (he == NULL)
 
344
            return NULL;
 
345
        return (GNode *)Hash_GetValue(he);
 
346
    }
 
347
 
 
348
    if (!(flags & TARG_NOHASH)) {
 
349
        he = Hash_CreateEntry(&targets, name, &isNew);
 
350
        if (!isNew)
 
351
            return (GNode *)Hash_GetValue(he);
 
352
    }
 
353
 
 
354
    gn = Targ_NewGN(name);
 
355
    if (!(flags & TARG_NOHASH))
 
356
        Hash_SetValue(he, gn);
 
357
    Var_Append(".ALLTARGETS", name, VAR_GLOBAL);
 
358
    (void)Lst_AtEnd(allTargets, gn);
 
359
    if (doing_depend)
 
360
        gn->flags |= FROM_DEPEND;
 
361
    return gn;
 
362
}
 
363
 
 
364
/*-
 
365
 *-----------------------------------------------------------------------
 
366
 * Targ_FindList --
 
367
 *      Make a complete list of GNodes from the given list of names
 
368
 *
 
369
 * Input:
 
370
 *      name            list of names to find
 
371
 *      flags           flags used if no node is found for a given name
 
372
 *
 
373
 * Results:
 
374
 *      A complete list of graph nodes corresponding to all instances of all
 
375
 *      the names in names.
 
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
 
384
Targ_FindList(Lst names, int flags)
 
385
{
 
386
    Lst            nodes;       /* result list */
 
387
    LstNode        ln;          /* name list element */
 
388
    GNode          *gn;         /* node in tLn */
 
389
    char           *name;
 
390
 
 
391
    nodes = Lst_Init(FALSE);
 
392
 
 
393
    if (Lst_Open(names) == FAILURE) {
 
394
        return (nodes);
 
395
    }
 
396
    while ((ln = Lst_Next(names)) != NULL) {
 
397
        name = (char *)Lst_Datum(ln);
 
398
        gn = Targ_FindNode(name, flags);
 
399
        if (gn != NULL) {
 
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
             */
 
405
            (void)Lst_AtEnd(nodes, gn);
 
406
        } else if (flags == TARG_NOCREATE) {
 
407
            Error("\"%s\" -- target unknown.", name);
 
408
        }
 
409
    }
 
410
    Lst_Close(names);
 
411
    return (nodes);
 
412
}
 
413
 
 
414
/*-
 
415
 *-----------------------------------------------------------------------
 
416
 * Targ_Ignore  --
 
417
 *      Return true if should ignore errors when creating gn
 
418
 *
 
419
 * Input:
 
420
 *      gn              node to check for
 
421
 *
 
422
 * Results:
 
423
 *      TRUE if should ignore errors
 
424
 *
 
425
 * Side Effects:
 
426
 *      None
 
427
 *-----------------------------------------------------------------------
 
428
 */
 
429
Boolean
 
430
Targ_Ignore(GNode *gn)
 
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
 *
 
444
 * Input:
 
445
 *      gn              node to check for
 
446
 *
 
447
 * Results:
 
448
 *      TRUE if should be silent
 
449
 *
 
450
 * Side Effects:
 
451
 *      None
 
452
 *-----------------------------------------------------------------------
 
453
 */
 
454
Boolean
 
455
Targ_Silent(GNode *gn)
 
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
 *
 
469
 * Input:
 
470
 *      gn              the node to check
 
471
 *
 
472
 * Results:
 
473
 *      TRUE if it is precious. FALSE otherwise
 
474
 *
 
475
 * Side Effects:
 
476
 *      None
 
477
 *-----------------------------------------------------------------------
 
478
 */
 
479
Boolean
 
480
Targ_Precious(GNode *gn)
 
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 */
 
492
/*-
 
493
 *-----------------------------------------------------------------------
 
494
 * Targ_SetMain --
 
495
 *      Set our idea of the main target we'll be creating. Used for
 
496
 *      debugging output.
 
497
 *
 
498
 * Input:
 
499
 *      gn              The main target we'll create
 
500
 *
 
501
 * Results:
 
502
 *      None.
 
503
 *
 
504
 * Side Effects:
 
505
 *      "mainTarg" is set to the main target's node.
 
506
 *-----------------------------------------------------------------------
 
507
 */
 
508
void
 
509
Targ_SetMain(GNode *gn)
 
510
{
 
511
    mainTarg = gn;
 
512
}
 
513
 
 
514
static int
 
515
TargPrintName(void *gnp, void *pflags MAKE_ATTR_UNUSED)
 
516
{
 
517
    GNode *gn = (GNode *)gnp;
 
518
 
 
519
    fprintf(debug_file, "%s%s ", gn->name, gn->cohort_num);
 
520
 
 
521
    return 0;
 
522
}
 
523
 
 
524
 
 
525
int
 
526
Targ_PrintCmd(void *cmd, void *dummy)
 
527
{
 
528
    fprintf(debug_file, "\t%s\n", (char *)cmd);
 
529
    return (dummy ? 0 : 0);
 
530
}
 
531
 
 
532
/*-
 
533
 *-----------------------------------------------------------------------
 
534
 * Targ_FmtTime --
 
535
 *      Format a modification time in some reasonable way and return it.
 
536
 *
 
537
 * Results:
 
538
 *      The time reformatted.
 
539
 *
 
540
 * Side Effects:
 
541
 *      The time is placed in a static area, so it is overwritten
 
542
 *      with each call.
 
543
 *
 
544
 *-----------------------------------------------------------------------
 
545
 */
 
546
char *
 
547
Targ_FmtTime(time_t tm)
 
548
{
 
549
    struct tm           *parts;
 
550
    static char         buf[128];
 
551
 
 
552
    parts = localtime(&tm);
 
553
    (void)strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts);
 
554
    return(buf);
 
555
}
 
556
 
 
557
/*-
 
558
 *-----------------------------------------------------------------------
 
559
 * Targ_PrintType --
 
560
 *      Print out a type field giving only those attributes the user can
 
561
 *      set.
 
562
 *
 
563
 * Results:
 
564
 *
 
565
 * Side Effects:
 
566
 *
 
567
 *-----------------------------------------------------------------------
 
568
 */
 
569
void
 
570
Targ_PrintType(int type)
 
571
{
 
572
    int    tbit;
 
573
 
 
574
#define PRINTBIT(attr)  case CONCAT(OP_,attr): fprintf(debug_file, "." #attr " "); break
 
575
#define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG))fprintf(debug_file, "." #attr " "); break
 
576
 
 
577
    type &= ~OP_OPMASK;
 
578
 
 
579
    while (type) {
 
580
        tbit = 1 << (ffs(type) - 1);
 
581
        type &= ~tbit;
 
582
 
 
583
        switch(tbit) {
 
584
            PRINTBIT(OPTIONAL);
 
585
            PRINTBIT(USE);
 
586
            PRINTBIT(EXEC);
 
587
            PRINTBIT(IGNORE);
 
588
            PRINTBIT(PRECIOUS);
 
589
            PRINTBIT(SILENT);
 
590
            PRINTBIT(MAKE);
 
591
            PRINTBIT(JOIN);
 
592
            PRINTBIT(INVISIBLE);
 
593
            PRINTBIT(NOTMAIN);
 
594
            PRINTDBIT(LIB);
 
595
            /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */
 
596
            case OP_MEMBER: if (DEBUG(TARG))fprintf(debug_file, ".MEMBER "); break;
 
597
            PRINTDBIT(ARCHV);
 
598
            PRINTDBIT(MADE);
 
599
            PRINTDBIT(PHONY);
 
600
        }
 
601
    }
 
602
}
 
603
 
 
604
static const char *
 
605
made_name(enum enum_made made)
 
606
{
 
607
    switch (made) {
 
608
    case UNMADE:     return "unmade";
 
609
    case DEFERRED:   return "deferred";
 
610
    case REQUESTED:  return "requested";
 
611
    case BEINGMADE:  return "being made";
 
612
    case MADE:       return "made";
 
613
    case UPTODATE:   return "up-to-date";
 
614
    case ERROR:      return "error when made";
 
615
    case ABORTED:    return "aborted";
 
616
    default:         return "unknown enum_made value";
 
617
    }
 
618
}
 
619
 
 
620
/*-
 
621
 *-----------------------------------------------------------------------
 
622
 * TargPrintNode --
 
623
 *      print the contents of a node
 
624
 *-----------------------------------------------------------------------
 
625
 */
 
626
int
 
627
Targ_PrintNode(void *gnp, void *passp)
 
628
{
 
629
    GNode         *gn = (GNode *)gnp;
 
630
    int           pass = passp ? *(int *)passp : 0;
 
631
 
 
632
    fprintf(debug_file, "# %s%s, flags %x, type %x, made %d\n",
 
633
            gn->name, gn->cohort_num, gn->flags, gn->type, gn->made);
 
634
    if (gn->flags == 0)
 
635
        return 0;
 
636
 
 
637
    if (!OP_NOP(gn->type)) {
 
638
        fprintf(debug_file, "#\n");
 
639
        if (gn == mainTarg) {
 
640
            fprintf(debug_file, "# *** MAIN TARGET ***\n");
 
641
        }
 
642
        if (pass >= 2) {
 
643
            if (gn->unmade) {
 
644
                fprintf(debug_file, "# %d unmade children\n", gn->unmade);
 
645
            } else {
 
646
                fprintf(debug_file, "# No unmade children\n");
 
647
            }
 
648
            if (! (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC))) {
 
649
                if (gn->mtime != 0) {
 
650
                    fprintf(debug_file, "# last modified %s: %s\n",
 
651
                              Targ_FmtTime(gn->mtime),
 
652
                              made_name(gn->made));
 
653
                } else if (gn->made != UNMADE) {
 
654
                    fprintf(debug_file, "# non-existent (maybe): %s\n",
 
655
                              made_name(gn->made));
 
656
                } else {
 
657
                    fprintf(debug_file, "# unmade\n");
 
658
                }
 
659
            }
 
660
            if (!Lst_IsEmpty (gn->iParents)) {
 
661
                fprintf(debug_file, "# implicit parents: ");
 
662
                Lst_ForEach(gn->iParents, TargPrintName, NULL);
 
663
                fprintf(debug_file, "\n");
 
664
            }
 
665
        } else {
 
666
            if (gn->unmade)
 
667
                fprintf(debug_file, "# %d unmade children\n", gn->unmade);
 
668
        }
 
669
        if (!Lst_IsEmpty (gn->parents)) {
 
670
            fprintf(debug_file, "# parents: ");
 
671
            Lst_ForEach(gn->parents, TargPrintName, NULL);
 
672
            fprintf(debug_file, "\n");
 
673
        }
 
674
        if (!Lst_IsEmpty (gn->order_pred)) {
 
675
            fprintf(debug_file, "# order_pred: ");
 
676
            Lst_ForEach(gn->order_pred, TargPrintName, NULL);
 
677
            fprintf(debug_file, "\n");
 
678
        }
 
679
        if (!Lst_IsEmpty (gn->order_succ)) {
 
680
            fprintf(debug_file, "# order_succ: ");
 
681
            Lst_ForEach(gn->order_succ, TargPrintName, NULL);
 
682
            fprintf(debug_file, "\n");
 
683
        }
 
684
 
 
685
        fprintf(debug_file, "%-16s", gn->name);
 
686
        switch (gn->type & OP_OPMASK) {
 
687
            case OP_DEPENDS:
 
688
                fprintf(debug_file, ": "); break;
 
689
            case OP_FORCE:
 
690
                fprintf(debug_file, "! "); break;
 
691
            case OP_DOUBLEDEP:
 
692
                fprintf(debug_file, ":: "); break;
 
693
        }
 
694
        Targ_PrintType(gn->type);
 
695
        Lst_ForEach(gn->children, TargPrintName, NULL);
 
696
        fprintf(debug_file, "\n");
 
697
        Lst_ForEach(gn->commands, Targ_PrintCmd, NULL);
 
698
        fprintf(debug_file, "\n\n");
 
699
        if (gn->type & OP_DOUBLEDEP) {
 
700
            Lst_ForEach(gn->cohorts, Targ_PrintNode, &pass);
 
701
        }
 
702
    }
 
703
    return (0);
 
704
}
 
705
 
 
706
/*-
 
707
 *-----------------------------------------------------------------------
 
708
 * TargPrintOnlySrc --
 
709
 *      Print only those targets that are just a source.
 
710
 *
 
711
 * Results:
 
712
 *      0.
 
713
 *
 
714
 * Side Effects:
 
715
 *      The name of each file is printed preceded by #\t
 
716
 *
 
717
 *-----------------------------------------------------------------------
 
718
 */
 
719
static int
 
720
TargPrintOnlySrc(void *gnp, void *dummy MAKE_ATTR_UNUSED)
 
721
{
 
722
    GNode         *gn = (GNode *)gnp;
 
723
    if (!OP_NOP(gn->type))
 
724
        return 0;
 
725
 
 
726
    fprintf(debug_file, "#\t%s [%s] ",
 
727
            gn->name, gn->path ? gn->path : gn->name);
 
728
    Targ_PrintType(gn->type);
 
729
    fprintf(debug_file, "\n");
 
730
 
 
731
    return 0;
 
732
}
 
733
 
 
734
/*-
 
735
 *-----------------------------------------------------------------------
 
736
 * Targ_PrintGraph --
 
737
 *      print the entire graph. heh heh
 
738
 *
 
739
 * Input:
 
740
 *      pass            Which pass this is. 1 => no processing
 
741
 *                      2 => processing done
 
742
 *
 
743
 * Results:
 
744
 *      none
 
745
 *
 
746
 * Side Effects:
 
747
 *      lots o' output
 
748
 *-----------------------------------------------------------------------
 
749
 */
 
750
void
 
751
Targ_PrintGraph(int pass)
 
752
{
 
753
    fprintf(debug_file, "#*** Input graph:\n");
 
754
    Lst_ForEach(allTargets, Targ_PrintNode, &pass);
 
755
    fprintf(debug_file, "\n\n");
 
756
    fprintf(debug_file, "#\n#   Files that are only sources:\n");
 
757
    Lst_ForEach(allTargets, TargPrintOnlySrc, NULL);
 
758
    fprintf(debug_file, "#*** Global Variables:\n");
 
759
    Var_Dump(VAR_GLOBAL);
 
760
    fprintf(debug_file, "#*** Command-line Variables:\n");
 
761
    Var_Dump(VAR_CMD);
 
762
    fprintf(debug_file, "\n");
 
763
    Dir_PrintDirectories();
 
764
    fprintf(debug_file, "\n");
 
765
    Suff_PrintAll();
 
766
}
 
767
 
 
768
/*-
 
769
 *-----------------------------------------------------------------------
 
770
 * TargPropagateNode --
 
771
 *      Propagate information from a single node to related nodes if
 
772
 *      appropriate.
 
773
 *
 
774
 * Input:
 
775
 *      gnp             The node that we are processing.
 
776
 *
 
777
 * Results:
 
778
 *      Always returns 0, for the benefit of Lst_ForEach().
 
779
 *
 
780
 * Side Effects:
 
781
 *      Information is propagated from this node to cohort or child
 
782
 *      nodes.
 
783
 *
 
784
 *      If the node was defined with "::", then TargPropagateCohort()
 
785
 *      will be called for each cohort node.
 
786
 *
 
787
 *      If the node has recursive predecessors, then
 
788
 *      TargPropagateRecpred() will be called for each recursive
 
789
 *      predecessor.
 
790
 *-----------------------------------------------------------------------
 
791
 */
 
792
static int
 
793
TargPropagateNode(void *gnp, void *junk MAKE_ATTR_UNUSED)
 
794
{
 
795
    GNode         *gn = (GNode *)gnp;
 
796
 
 
797
    if (gn->type & OP_DOUBLEDEP)
 
798
        Lst_ForEach(gn->cohorts, TargPropagateCohort, gnp);
 
799
    return (0);
 
800
}
 
801
 
 
802
/*-
 
803
 *-----------------------------------------------------------------------
 
804
 * TargPropagateCohort --
 
805
 *      Propagate some bits in the type mask from a node to
 
806
 *      a related cohort node.
 
807
 *
 
808
 * Input:
 
809
 *      cnp             The node that we are processing.
 
810
 *      gnp             Another node that has cnp as a cohort.
 
811
 *
 
812
 * Results:
 
813
 *      Always returns 0, for the benefit of Lst_ForEach().
 
814
 *
 
815
 * Side Effects:
 
816
 *      cnp's type bitmask is modified to incorporate some of the
 
817
 *      bits from gnp's type bitmask.  (XXX need a better explanation.)
 
818
 *-----------------------------------------------------------------------
 
819
 */
 
820
static int
 
821
TargPropagateCohort(void *cgnp, void *pgnp)
 
822
{
 
823
    GNode         *cgn = (GNode *)cgnp;
 
824
    GNode         *pgn = (GNode *)pgnp;
 
825
 
 
826
    cgn->type |= pgn->type & ~OP_OPMASK;
 
827
    return (0);
 
828
}
 
829
 
 
830
/*-
 
831
 *-----------------------------------------------------------------------
 
832
 * Targ_Propagate --
 
833
 *      Propagate information between related nodes.  Should be called
 
834
 *      after the makefiles are parsed but before any action is taken.
 
835
 *
 
836
 * Results:
 
837
 *      none
 
838
 *
 
839
 * Side Effects:
 
840
 *      Information is propagated between related nodes throughout the
 
841
 *      graph.
 
842
 *-----------------------------------------------------------------------
 
843
 */
 
844
void
 
845
Targ_Propagate(void)
 
846
{
 
847
    Lst_ForEach(allTargets, TargPropagateNode, NULL);
 
848
}