targ.c revision 241146
1155408Srwatson/* $NetBSD: targ.c,v 1.57 2012/06/12 19:21:51 joerg Exp $ */ 2155408Srwatson 3155408Srwatson/* 4155408Srwatson * Copyright (c) 1988, 1989, 1990, 1993 5155408Srwatson * The Regents of the University of California. All rights reserved. 6155408Srwatson * 7155408Srwatson * This code is derived from software contributed to Berkeley by 8155408Srwatson * Adam de Boor. 9155408Srwatson * 10155408Srwatson * Redistribution and use in source and binary forms, with or without 11155408Srwatson * modification, are permitted provided that the following conditions 12155408Srwatson * are met: 13155408Srwatson * 1. Redistributions of source code must retain the above copyright 14155408Srwatson * notice, this list of conditions and the following disclaimer. 15155408Srwatson * 2. Redistributions in binary form must reproduce the above copyright 16155408Srwatson * notice, this list of conditions and the following disclaimer in the 17155408Srwatson * documentation and/or other materials provided with the distribution. 18155408Srwatson * 3. Neither the name of the University nor the names of its contributors 19155408Srwatson * may be used to endorse or promote products derived from this software 20155408Srwatson * without specific prior written permission. 21155408Srwatson * 22155408Srwatson * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23155408Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24155408Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25155408Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26155408Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27155408Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28155408Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29155408Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30155408Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31155408Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32155408Srwatson * SUCH DAMAGE. 33155408Srwatson */ 34155408Srwatson 35155408Srwatson/* 36155408Srwatson * Copyright (c) 1989 by Berkeley Softworks 37155408Srwatson * All rights reserved. 38155408Srwatson * 39155408Srwatson * This code is derived from software contributed to Berkeley by 40155408Srwatson * Adam de Boor. 41155408Srwatson * 42155408Srwatson * Redistribution and use in source and binary forms, with or without 43155408Srwatson * modification, are permitted provided that the following conditions 44155408Srwatson * are met: 45155408Srwatson * 1. Redistributions of source code must retain the above copyright 46155408Srwatson * notice, this list of conditions and the following disclaimer. 47155408Srwatson * 2. Redistributions in binary form must reproduce the above copyright 48155408Srwatson * notice, this list of conditions and the following disclaimer in the 49155408Srwatson * documentation and/or other materials provided with the distribution. 50155408Srwatson * 3. All advertising materials mentioning features or use of this software 51156880Srwatson * must display the following acknowledgement: 52155408Srwatson * This product includes software developed by the University of 53155408Srwatson * California, Berkeley and its contributors. 54155408Srwatson * 4. Neither the name of the University nor the names of its contributors 55155408Srwatson * may be used to endorse or promote products derived from this software 56155408Srwatson * without specific prior written permission. 57155408Srwatson * 58159269Srwatson * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59159269Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60155408Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61155408Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62155408Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63155408Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64155408Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65155408Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66155408Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67155408Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68159269Srwatson * SUCH DAMAGE. 69159269Srwatson */ 70155408Srwatson 71155408Srwatson#ifndef MAKE_NATIVE 72155408Srwatsonstatic char rcsid[] = "$NetBSD: targ.c,v 1.57 2012/06/12 19:21:51 joerg Exp $"; 73155408Srwatson#else 74156883Srwatson#include <sys/cdefs.h> 75156880Srwatson#ifndef lint 76155408Srwatson#if 0 77155408Srwatsonstatic char sccsid[] = "@(#)targ.c 8.2 (Berkeley) 3/19/94"; 78155408Srwatson#else 79155408Srwatson__RCSID("$NetBSD: targ.c,v 1.57 2012/06/12 19:21:51 joerg Exp $"); 80155408Srwatson#endif 81155408Srwatson#endif /* not lint */ 82155408Srwatson#endif 83155408Srwatson 84155408Srwatson/*- 85155408Srwatson * targ.c -- 86155408Srwatson * Functions for maintaining the Lst allTargets. Target nodes are 87155408Srwatson * kept in two structures: a Lst, maintained by the list library, and a 88159269Srwatson * hash table, maintained by the hash library. 89159269Srwatson * 90159269Srwatson * Interface: 91159269Srwatson * Targ_Init Initialization procedure. 92159269Srwatson * 93159269Srwatson * Targ_End Cleanup the module 94159269Srwatson * 95159269Srwatson * Targ_List Return the list of all targets so far. 96159269Srwatson * 97159269Srwatson * Targ_NewGN Create a new GNode for the passed target 98159269Srwatson * (string). The node is *not* placed in the 99159269Srwatson * hash table, though all its fields are 100159269Srwatson * initialized. 101159269Srwatson * 102159269Srwatson * Targ_FindNode Find the node for a given target, creating 103159269Srwatson * and storing it if it doesn't exist and the 104159269Srwatson * flags are right (TARG_CREATE) 105155408Srwatson * 106155408Srwatson * Targ_FindList Given a list of names, find nodes for all 107155408Srwatson * of them. If a name doesn't exist and the 108155408Srwatson * TARG_NOCREATE flag was given, an error message 109155408Srwatson * is printed. Else, if a name doesn't exist, 110155408Srwatson * its node is created. 111155408Srwatson * 112155408Srwatson * Targ_Ignore Return TRUE if errors should be ignored when 113155408Srwatson * creating the given target. 114155408Srwatson * 115155408Srwatson * Targ_Silent Return TRUE if we should be silent when 116155408Srwatson * creating the given target. 117155408Srwatson * 118155408Srwatson * Targ_Precious Return TRUE if the target is precious and 119155408Srwatson * should not be removed if we are interrupted. 120155408Srwatson * 121155408Srwatson * Targ_Propagate Propagate information between related 122155408Srwatson * nodes. Should be called after the 123155408Srwatson * makefiles are parsed but before any 124155408Srwatson * action is taken. 125159269Srwatson * 126159269Srwatson * Debugging: 127159269Srwatson * Targ_PrintGraph Print out the entire graphm all variables 128159269Srwatson * and statistics for the directory cache. Should 129159269Srwatson * print something for suffixes, too, but... 130159269Srwatson */ 131159269Srwatson 132159269Srwatson#include <stdio.h> 133159269Srwatson#include <time.h> 134159269Srwatson 135159269Srwatson#include "make.h" 136159269Srwatson#include "hash.h" 137159269Srwatson#include "dir.h" 138155408Srwatson 139155408Srwatsonstatic Lst allTargets; /* the list of all targets found so far */ 140159269Srwatson#ifdef CLEANUP 141159269Srwatsonstatic Lst allGNs; /* List of all the GNodes */ 142159269Srwatson#endif 143155408Srwatsonstatic Hash_Table targets; /* a hash table of same */ 144155408Srwatson 145155408Srwatson#define HTSIZE 191 /* initial size of hash table */ 146155408Srwatson 147159269Srwatsonstatic int TargPrintOnlySrc(void *, void *); 148155408Srwatsonstatic int TargPrintName(void *, void *); 149155408Srwatson#ifdef CLEANUP 150155408Srwatsonstatic void TargFreeGN(void *); 151155408Srwatson#endif 152155408Srwatsonstatic int TargPropagateCohort(void *, void *); 153155408Srwatsonstatic int TargPropagateNode(void *, void *); 154159269Srwatson 155159269Srwatson/*- 156159269Srwatson *----------------------------------------------------------------------- 157155408Srwatson * Targ_Init -- 158155408Srwatson * Initialize this module 159155408Srwatson * 160155408Srwatson * Results: 161155408Srwatson * None 162155408Srwatson * 163155408Srwatson * Side Effects: 164155408Srwatson * The allTargets list and the targets hash table are initialized 165155408Srwatson *----------------------------------------------------------------------- 166155408Srwatson */ 167155408Srwatsonvoid 168155408SrwatsonTarg_Init(void) 169155408Srwatson{ 170155408Srwatson allTargets = Lst_Init(FALSE); 171155408Srwatson Hash_InitTable(&targets, HTSIZE); 172155408Srwatson} 173155408Srwatson 174155408Srwatson/*- 175161582Srwatson *----------------------------------------------------------------------- 176155408Srwatson * Targ_End -- 177155408Srwatson * Finalize this module 178155408Srwatson * 179159269Srwatson * Results: 180155408Srwatson * None 181155408Srwatson * 182155408Srwatson * Side Effects: 183155408Srwatson * All lists and gnodes are cleared 184155408Srwatson *----------------------------------------------------------------------- 185161582Srwatson */ 186155408Srwatsonvoid 187155408SrwatsonTarg_End(void) 188155408Srwatson{ 189161582Srwatson#ifdef CLEANUP 190161582Srwatson Lst_Destroy(allTargets, NULL); 191161582Srwatson if (allGNs) 192161582Srwatson Lst_Destroy(allGNs, TargFreeGN); 193161582Srwatson Hash_DeleteTable(&targets); 194161582Srwatson#endif 195161582Srwatson} 196161582Srwatson 197161582Srwatson/*- 198161582Srwatson *----------------------------------------------------------------------- 199155408Srwatson * Targ_List -- 200155408Srwatson * Return the list of all targets 201155408Srwatson * 202155408Srwatson * Results: 203155408Srwatson * The list of all targets. 204155408Srwatson * 205155408Srwatson * Side Effects: 206155408Srwatson * None 207155408Srwatson *----------------------------------------------------------------------- 208155408Srwatson */ 209155408SrwatsonLst 210155408SrwatsonTarg_List(void) 211155408Srwatson{ 212155408Srwatson return allTargets; 213155408Srwatson} 214155408Srwatson 215155408Srwatson/*- 216155408Srwatson *----------------------------------------------------------------------- 217155408Srwatson * Targ_NewGN -- 218155408Srwatson * Create and initialize a new graph node 219159269Srwatson * 220159269Srwatson * Input: 221159269Srwatson * name the name to stick in the new node 222159269Srwatson * 223159269Srwatson * Results: 224159269Srwatson * An initialized graph node with the name field filled with a copy 225159269Srwatson * of the passed name 226159269Srwatson * 227159269Srwatson * Side Effects: 228159269Srwatson * The gnode is added to the list of all gnodes. 229159269Srwatson *----------------------------------------------------------------------- 230159269Srwatson */ 231159269SrwatsonGNode * 232159269SrwatsonTarg_NewGN(const char *name) 233159269Srwatson{ 234159269Srwatson GNode *gn; 235159269Srwatson 236159269Srwatson gn = bmake_malloc(sizeof(GNode)); 237159269Srwatson gn->name = bmake_strdup(name); 238159269Srwatson gn->uname = NULL; 239159269Srwatson gn->path = NULL; 240159269Srwatson if (name[0] == '-' && name[1] == 'l') { 241159269Srwatson gn->type = OP_LIB; 242159269Srwatson } else { 243159269Srwatson gn->type = 0; 244159269Srwatson } 245159269Srwatson gn->unmade = 0; 246159269Srwatson gn->unmade_cohorts = 0; 247159269Srwatson gn->cohort_num[0] = 0; 248159269Srwatson gn->centurion = NULL; 249159269Srwatson gn->made = UNMADE; 250159269Srwatson gn->flags = 0; 251159269Srwatson gn->checked = 0; 252159269Srwatson gn->mtime = 0; 253159269Srwatson gn->cmgn = NULL; 254159269Srwatson gn->iParents = Lst_Init(FALSE); 255159269Srwatson gn->cohorts = Lst_Init(FALSE); 256159269Srwatson gn->parents = Lst_Init(FALSE); 257159269Srwatson gn->children = Lst_Init(FALSE); 258159269Srwatson gn->order_pred = Lst_Init(FALSE); 259159269Srwatson gn->order_succ = Lst_Init(FALSE); 260159269Srwatson Hash_InitTable(&gn->context, 0); 261159269Srwatson gn->commands = Lst_Init(FALSE); 262159269Srwatson gn->suffix = NULL; 263159269Srwatson gn->lineno = 0; 264159269Srwatson gn->fname = NULL; 265159269Srwatson 266159269Srwatson#ifdef CLEANUP 267159269Srwatson if (allGNs == NULL) 268159269Srwatson allGNs = Lst_Init(FALSE); 269159269Srwatson Lst_AtEnd(allGNs, gn); 270159269Srwatson#endif 271159269Srwatson 272159269Srwatson return (gn); 273159269Srwatson} 274159269Srwatson 275159269Srwatson#ifdef CLEANUP 276159269Srwatson/*- 277159269Srwatson *----------------------------------------------------------------------- 278159269Srwatson * TargFreeGN -- 279159269Srwatson * Destroy a GNode 280159269Srwatson * 281159269Srwatson * Results: 282159269Srwatson * None. 283159269Srwatson * 284159269Srwatson * Side Effects: 285159269Srwatson * None. 286159269Srwatson *----------------------------------------------------------------------- 287159269Srwatson */ 288159269Srwatsonstatic void 289159269SrwatsonTargFreeGN(void *gnp) 290159269Srwatson{ 291159269Srwatson GNode *gn = (GNode *)gnp; 292159269Srwatson 293159269Srwatson 294159269Srwatson free(gn->name); 295159269Srwatson if (gn->uname) 296159269Srwatson free(gn->uname); 297159269Srwatson if (gn->path) 298159269Srwatson free(gn->path); 299159269Srwatson /* gn->fname points to name allocated when file was opened, don't free */ 300159269Srwatson 301159269Srwatson Lst_Destroy(gn->iParents, NULL); 302159269Srwatson Lst_Destroy(gn->cohorts, NULL); 303159269Srwatson Lst_Destroy(gn->parents, NULL); 304159269Srwatson Lst_Destroy(gn->children, NULL); 305159269Srwatson Lst_Destroy(gn->order_succ, NULL); 306159269Srwatson Lst_Destroy(gn->order_pred, NULL); 307159269Srwatson Hash_DeleteTable(&gn->context); 308159269Srwatson Lst_Destroy(gn->commands, NULL); 309159269Srwatson free(gn); 310159269Srwatson} 311159269Srwatson#endif 312159269Srwatson 313159269Srwatson 314159269Srwatson/*- 315159269Srwatson *----------------------------------------------------------------------- 316159269Srwatson * Targ_FindNode -- 317159269Srwatson * Find a node in the list using the given name for matching 318159269Srwatson * 319159269Srwatson * Input: 320159269Srwatson * name the name to find 321159269Srwatson * flags flags governing events when target not 322159269Srwatson * found 323159269Srwatson * 324159269Srwatson * Results: 325159269Srwatson * The node in the list if it was. If it wasn't, return NULL of 326159269Srwatson * flags was TARG_NOCREATE or the newly created and initialized node 327159269Srwatson * if it was TARG_CREATE 328159269Srwatson * 329159269Srwatson * Side Effects: 330159269Srwatson * Sometimes a node is created and added to the list 331159269Srwatson *----------------------------------------------------------------------- 332159269Srwatson */ 333159269SrwatsonGNode * 334159269SrwatsonTarg_FindNode(const char *name, int flags) 335159269Srwatson{ 336159269Srwatson GNode *gn; /* node in that element */ 337159269Srwatson Hash_Entry *he = NULL; /* New or used hash entry for node */ 338159269Srwatson Boolean isNew; /* Set TRUE if Hash_CreateEntry had to create */ 339159269Srwatson /* an entry for the node */ 340159269Srwatson 341159269Srwatson if (!(flags & (TARG_CREATE | TARG_NOHASH))) { 342159269Srwatson he = Hash_FindEntry(&targets, name); 343159269Srwatson if (he == NULL) 344159269Srwatson return NULL; 345159269Srwatson return (GNode *)Hash_GetValue(he); 346159269Srwatson } 347159269Srwatson 348159269Srwatson if (!(flags & TARG_NOHASH)) { 349159269Srwatson he = Hash_CreateEntry(&targets, name, &isNew); 350159269Srwatson if (!isNew) 351159269Srwatson return (GNode *)Hash_GetValue(he); 352159269Srwatson } 353159269Srwatson 354159269Srwatson gn = Targ_NewGN(name); 355159269Srwatson if (!(flags & TARG_NOHASH)) 356159269Srwatson Hash_SetValue(he, gn); 357159269Srwatson Var_Append(".ALLTARGETS", name, VAR_GLOBAL); 358159269Srwatson (void)Lst_AtEnd(allTargets, gn); 359159269Srwatson if (doing_depend) 360159269Srwatson gn->flags |= FROM_DEPEND; 361159269Srwatson return gn; 362159269Srwatson} 363159269Srwatson 364159269Srwatson/*- 365159269Srwatson *----------------------------------------------------------------------- 366159269Srwatson * Targ_FindList -- 367159269Srwatson * Make a complete list of GNodes from the given list of names 368159269Srwatson * 369159269Srwatson * Input: 370159269Srwatson * name list of names to find 371159269Srwatson * flags flags used if no node is found for a given name 372159269Srwatson * 373159269Srwatson * Results: 374159269Srwatson * A complete list of graph nodes corresponding to all instances of all 375159269Srwatson * the names in names. 376159269Srwatson * 377159269Srwatson * Side Effects: 378159269Srwatson * If flags is TARG_CREATE, nodes will be created for all names in 379159269Srwatson * names which do not yet have graph nodes. If flags is TARG_NOCREATE, 380159269Srwatson * an error message will be printed for each name which can't be found. 381159269Srwatson * ----------------------------------------------------------------------- 382159269Srwatson */ 383159269SrwatsonLst 384159269SrwatsonTarg_FindList(Lst names, int flags) 385159269Srwatson{ 386159269Srwatson Lst nodes; /* result list */ 387159269Srwatson LstNode ln; /* name list element */ 388159269Srwatson GNode *gn; /* node in tLn */ 389159269Srwatson char *name; 390159269Srwatson 391159269Srwatson nodes = Lst_Init(FALSE); 392159269Srwatson 393159269Srwatson if (Lst_Open(names) == FAILURE) { 394159269Srwatson return (nodes); 395159269Srwatson } 396159269Srwatson while ((ln = Lst_Next(names)) != NULL) { 397159269Srwatson name = (char *)Lst_Datum(ln); 398155408Srwatson gn = Targ_FindNode(name, flags); 399155408Srwatson if (gn != NULL) { 400155408Srwatson /* 401155408Srwatson * Note: Lst_AtEnd must come before the Lst_Concat so the nodes 402155408Srwatson * are added to the list in the order in which they were 403155408Srwatson * encountered in the makefile. 404155408Srwatson */ 405155408Srwatson (void)Lst_AtEnd(nodes, gn); 406155408Srwatson } else if (flags == TARG_NOCREATE) { 407155408Srwatson Error("\"%s\" -- target unknown.", name); 408155408Srwatson } 409155408Srwatson } 410155408Srwatson Lst_Close(names); 411155408Srwatson return (nodes); 412156292Srwatson} 413155408Srwatson 414155408Srwatson/*- 415155408Srwatson *----------------------------------------------------------------------- 416155408Srwatson * Targ_Ignore -- 417155408Srwatson * Return true if should ignore errors when creating gn 418155408Srwatson * 419155408Srwatson * Input: 420155408Srwatson * gn node to check for 421155408Srwatson * 422155408Srwatson * Results: 423155408Srwatson * TRUE if should ignore errors 424155408Srwatson * 425155408Srwatson * Side Effects: 426155408Srwatson * None 427155408Srwatson *----------------------------------------------------------------------- 428155408Srwatson */ 429155408SrwatsonBoolean 430155408SrwatsonTarg_Ignore(GNode *gn) 431155428Srwatson{ 432155408Srwatson if (ignoreErrors || gn->type & OP_IGNORE) { 433155408Srwatson return (TRUE); 434155408Srwatson } else { 435155408Srwatson return (FALSE); 436155408Srwatson } 437155408Srwatson} 438155408Srwatson 439155408Srwatson/*- 440161582Srwatson *----------------------------------------------------------------------- 441155408Srwatson * Targ_Silent -- 442155408Srwatson * Return true if be silent when creating gn 443155408Srwatson * 444155408Srwatson * Input: 445155408Srwatson * gn node to check for 446155408Srwatson * 447155408Srwatson * Results: 448155408Srwatson * TRUE if should be silent 449155408Srwatson * 450159269Srwatson * Side Effects: 451159269Srwatson * None 452155408Srwatson *----------------------------------------------------------------------- 453155408Srwatson */ 454155408SrwatsonBoolean 455155408SrwatsonTarg_Silent(GNode *gn) 456155408Srwatson{ 457155408Srwatson if (beSilent || gn->type & OP_SILENT) { 458155408Srwatson return (TRUE); 459155408Srwatson } else { 460155408Srwatson return (FALSE); 461155408Srwatson } 462159269Srwatson} 463159269Srwatson 464159269Srwatson/*- 465159269Srwatson *----------------------------------------------------------------------- 466159269Srwatson * Targ_Precious -- 467159269Srwatson * See if the given target is precious 468159269Srwatson * 469159269Srwatson * Input: 470159269Srwatson * gn the node to check 471159269Srwatson * 472159269Srwatson * Results: 473159269Srwatson * TRUE if it is precious. FALSE otherwise 474159269Srwatson * 475159269Srwatson * Side Effects: 476159269Srwatson * None 477159269Srwatson *----------------------------------------------------------------------- 478159269Srwatson */ 479159269SrwatsonBoolean 480159269SrwatsonTarg_Precious(GNode *gn) 481159269Srwatson{ 482159269Srwatson if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP))) { 483159269Srwatson return (TRUE); 484159269Srwatson } else { 485159269Srwatson return (FALSE); 486159269Srwatson } 487159269Srwatson} 488159269Srwatson 489159269Srwatson/******************* DEBUG INFO PRINTING ****************/ 490159269Srwatson 491159269Srwatsonstatic GNode *mainTarg; /* the main target, as set by Targ_SetMain */ 492155408Srwatson/*- 493155408Srwatson *----------------------------------------------------------------------- 494155408Srwatson * Targ_SetMain -- 495155408Srwatson * Set our idea of the main target we'll be creating. Used for 496155408Srwatson * debugging output. 497155408Srwatson * 498155408Srwatson * Input: 499159269Srwatson * gn The main target we'll create 500155408Srwatson * 501159269Srwatson * Results: 502155408Srwatson * None. 503155408Srwatson * 504155408Srwatson * Side Effects: 505155408Srwatson * "mainTarg" is set to the main target's node. 506155408Srwatson *----------------------------------------------------------------------- 507155408Srwatson */ 508155408Srwatsonvoid 509155408SrwatsonTarg_SetMain(GNode *gn) 510155408Srwatson{ 511155408Srwatson mainTarg = gn; 512155408Srwatson} 513155408Srwatson 514155408Srwatsonstatic int 515155408SrwatsonTargPrintName(void *gnp, void *pflags MAKE_ATTR_UNUSED) 516155408Srwatson{ 517155408Srwatson GNode *gn = (GNode *)gnp; 518155408Srwatson 519155408Srwatson fprintf(debug_file, "%s%s ", gn->name, gn->cohort_num); 520155408Srwatson 521155408Srwatson return 0; 522155408Srwatson} 523155408Srwatson 524155408Srwatson 525155408Srwatsonint 526155408SrwatsonTarg_PrintCmd(void *cmd, void *dummy) 527155408Srwatson{ 528155408Srwatson fprintf(debug_file, "\t%s\n", (char *)cmd); 529155408Srwatson return (dummy ? 0 : 0); 530155408Srwatson} 531155408Srwatson 532155408Srwatson/*- 533155408Srwatson *----------------------------------------------------------------------- 534155408Srwatson * Targ_FmtTime -- 535155408Srwatson * Format a modification time in some reasonable way and return it. 536161582Srwatson * 537161582Srwatson * Results: 538159269Srwatson * The time reformatted. 539159269Srwatson * 540159269Srwatson * Side Effects: 541159269Srwatson * The time is placed in a static area, so it is overwritten 542159269Srwatson * with each call. 543159269Srwatson * 544159269Srwatson *----------------------------------------------------------------------- 545159269Srwatson */ 546159269Srwatsonchar * 547159269SrwatsonTarg_FmtTime(time_t tm) 548159269Srwatson{ 549159269Srwatson struct tm *parts; 550159269Srwatson static char buf[128]; 551161582Srwatson 552161582Srwatson parts = localtime(&tm); 553161582Srwatson (void)strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts); 554155408Srwatson return(buf); 555155408Srwatson} 556155408Srwatson 557159269Srwatson/*- 558155408Srwatson *----------------------------------------------------------------------- 559155408Srwatson * Targ_PrintType -- 560155408Srwatson * Print out a type field giving only those attributes the user can 561155408Srwatson * set. 562159269Srwatson * 563155408Srwatson * Results: 564155408Srwatson * 565159269Srwatson * Side Effects: 566155408Srwatson * 567155408Srwatson *----------------------------------------------------------------------- 568155408Srwatson */ 569155408Srwatsonvoid 570155408SrwatsonTarg_PrintType(int type) 571155408Srwatson{ 572155408Srwatson int tbit; 573155408Srwatson 574155408Srwatson#define PRINTBIT(attr) case CONCAT(OP_,attr): fprintf(debug_file, "." #attr " "); break 575155408Srwatson#define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG))fprintf(debug_file, "." #attr " "); break 576155408Srwatson 577159269Srwatson type &= ~OP_OPMASK; 578159269Srwatson 579159269Srwatson while (type) { 580159269Srwatson tbit = 1 << (ffs(type) - 1); 581159269Srwatson type &= ~tbit; 582159269Srwatson 583159269Srwatson switch(tbit) { 584159269Srwatson PRINTBIT(OPTIONAL); 585159269Srwatson PRINTBIT(USE); 586159269Srwatson PRINTBIT(EXEC); 587159269Srwatson PRINTBIT(IGNORE); 588159269Srwatson PRINTBIT(PRECIOUS); 589159269Srwatson PRINTBIT(SILENT); 590159269Srwatson PRINTBIT(MAKE); 591159269Srwatson PRINTBIT(JOIN); 592159269Srwatson PRINTBIT(INVISIBLE); 593161582Srwatson PRINTBIT(NOTMAIN); 594159269Srwatson PRINTDBIT(LIB); 595155408Srwatson /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */ 596155408Srwatson case OP_MEMBER: if (DEBUG(TARG))fprintf(debug_file, ".MEMBER "); break; 597155408Srwatson PRINTDBIT(ARCHV); 598155408Srwatson PRINTDBIT(MADE); 599155408Srwatson PRINTDBIT(PHONY); 600155408Srwatson } 601155408Srwatson } 602155408Srwatson} 603155408Srwatson 604155408Srwatsonstatic const char * 605155408Srwatsonmade_name(enum enum_made made) 606155408Srwatson{ 607155408Srwatson switch (made) { 608155408Srwatson case UNMADE: return "unmade"; 609155408Srwatson case DEFERRED: return "deferred"; 610155408Srwatson case REQUESTED: return "requested"; 611155408Srwatson case BEINGMADE: return "being made"; 612155408Srwatson case MADE: return "made"; 613155408Srwatson case UPTODATE: return "up-to-date"; 614155408Srwatson case ERROR: return "error when made"; 615155408Srwatson case ABORTED: return "aborted"; 616155408Srwatson default: return "unknown enum_made value"; 617155408Srwatson } 618155408Srwatson} 619155408Srwatson 620155408Srwatson/*- 621155408Srwatson *----------------------------------------------------------------------- 622155408Srwatson * TargPrintNode -- 623155408Srwatson * print the contents of a node 624155408Srwatson *----------------------------------------------------------------------- 625155408Srwatson */ 626155408Srwatsonint 627155408SrwatsonTarg_PrintNode(void *gnp, void *passp) 628155408Srwatson{ 629155408Srwatson GNode *gn = (GNode *)gnp; 630155408Srwatson int pass = passp ? *(int *)passp : 0; 631155408Srwatson 632155408Srwatson fprintf(debug_file, "# %s%s, flags %x, type %x, made %d\n", 633155408Srwatson gn->name, gn->cohort_num, gn->flags, gn->type, gn->made); 634155408Srwatson if (gn->flags == 0) 635155408Srwatson return 0; 636155408Srwatson 637155408Srwatson if (!OP_NOP(gn->type)) { 638155408Srwatson fprintf(debug_file, "#\n"); 639155408Srwatson if (gn == mainTarg) { 640155408Srwatson fprintf(debug_file, "# *** MAIN TARGET ***\n"); 641155408Srwatson } 642155408Srwatson if (pass >= 2) { 643155408Srwatson if (gn->unmade) { 644155408Srwatson fprintf(debug_file, "# %d unmade children\n", gn->unmade); 645155408Srwatson } else { 646155408Srwatson fprintf(debug_file, "# No unmade children\n"); 647155408Srwatson } 648155408Srwatson if (! (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC))) { 649155408Srwatson if (gn->mtime != 0) { 650155408Srwatson fprintf(debug_file, "# last modified %s: %s\n", 651155408Srwatson Targ_FmtTime(gn->mtime), 652155408Srwatson made_name(gn->made)); 653155408Srwatson } else if (gn->made != UNMADE) { 654155408Srwatson fprintf(debug_file, "# non-existent (maybe): %s\n", 655155408Srwatson made_name(gn->made)); 656155408Srwatson } else { 657155408Srwatson fprintf(debug_file, "# unmade\n"); 658155408Srwatson } 659155408Srwatson } 660155408Srwatson if (!Lst_IsEmpty (gn->iParents)) { 661155408Srwatson fprintf(debug_file, "# implicit parents: "); 662155408Srwatson Lst_ForEach(gn->iParents, TargPrintName, NULL); 663155408Srwatson fprintf(debug_file, "\n"); 664155408Srwatson } 665155408Srwatson } else { 666155408Srwatson if (gn->unmade) 667155408Srwatson fprintf(debug_file, "# %d unmade children\n", gn->unmade); 668155408Srwatson } 669155408Srwatson if (!Lst_IsEmpty (gn->parents)) { 670155408Srwatson fprintf(debug_file, "# parents: "); 671155408Srwatson Lst_ForEach(gn->parents, TargPrintName, NULL); 672155408Srwatson fprintf(debug_file, "\n"); 673155408Srwatson } 674155408Srwatson if (!Lst_IsEmpty (gn->order_pred)) { 675155408Srwatson fprintf(debug_file, "# order_pred: "); 676155408Srwatson Lst_ForEach(gn->order_pred, TargPrintName, NULL); 677155408Srwatson fprintf(debug_file, "\n"); 678155408Srwatson } 679156880Srwatson if (!Lst_IsEmpty (gn->order_succ)) { 680156880Srwatson fprintf(debug_file, "# order_succ: "); 681155408Srwatson Lst_ForEach(gn->order_succ, TargPrintName, NULL); 682155408Srwatson fprintf(debug_file, "\n"); 683155408Srwatson } 684155408Srwatson 685155408Srwatson fprintf(debug_file, "%-16s", gn->name); 686155408Srwatson switch (gn->type & OP_OPMASK) { 687155408Srwatson case OP_DEPENDS: 688155408Srwatson fprintf(debug_file, ": "); break; 689159269Srwatson case OP_FORCE: 690155408Srwatson fprintf(debug_file, "! "); break; 691159269Srwatson case OP_DOUBLEDEP: 692159269Srwatson fprintf(debug_file, ":: "); break; 693159269Srwatson } 694155408Srwatson Targ_PrintType(gn->type); 695155408Srwatson Lst_ForEach(gn->children, TargPrintName, NULL); 696155408Srwatson fprintf(debug_file, "\n"); 697159269Srwatson Lst_ForEach(gn->commands, Targ_PrintCmd, NULL); 698159269Srwatson fprintf(debug_file, "\n\n"); 699159269Srwatson if (gn->type & OP_DOUBLEDEP) { 700159269Srwatson Lst_ForEach(gn->cohorts, Targ_PrintNode, &pass); 701159269Srwatson } 702159269Srwatson } 703155408Srwatson return (0); 704155408Srwatson} 705155408Srwatson 706155408Srwatson/*- 707155408Srwatson *----------------------------------------------------------------------- 708155408Srwatson * TargPrintOnlySrc -- 709155408Srwatson * Print only those targets that are just a source. 710155408Srwatson * 711155408Srwatson * Results: 712155408Srwatson * 0. 713155408Srwatson * 714155408Srwatson * Side Effects: 715155408Srwatson * The name of each file is printed preceded by #\t 716155408Srwatson * 717155408Srwatson *----------------------------------------------------------------------- 718155408Srwatson */ 719155408Srwatsonstatic int 720155408SrwatsonTargPrintOnlySrc(void *gnp, void *dummy MAKE_ATTR_UNUSED) 721155408Srwatson{ 722155408Srwatson GNode *gn = (GNode *)gnp; 723155408Srwatson if (!OP_NOP(gn->type)) 724155408Srwatson return 0; 725155408Srwatson 726155408Srwatson fprintf(debug_file, "#\t%s [%s] ", 727155408Srwatson gn->name, gn->path ? gn->path : gn->name); 728155408Srwatson Targ_PrintType(gn->type); 729155408Srwatson fprintf(debug_file, "\n"); 730155408Srwatson 731155408Srwatson return 0; 732155408Srwatson} 733155408Srwatson 734155408Srwatson/*- 735155408Srwatson *----------------------------------------------------------------------- 736155408Srwatson * Targ_PrintGraph -- 737155408Srwatson * print the entire graph. heh heh 738155408Srwatson * 739155408Srwatson * Input: 740155408Srwatson * pass Which pass this is. 1 => no processing 741155408Srwatson * 2 => processing done 742156880Srwatson * 743155408Srwatson * Results: 744156880Srwatson * none 745156880Srwatson * 746156880Srwatson * Side Effects: 747156880Srwatson * lots o' output 748156880Srwatson *----------------------------------------------------------------------- 749156880Srwatson */ 750156880Srwatsonvoid 751156880SrwatsonTarg_PrintGraph(int pass) 752156880Srwatson{ 753156880Srwatson fprintf(debug_file, "#*** Input graph:\n"); 754156880Srwatson Lst_ForEach(allTargets, Targ_PrintNode, &pass); 755156880Srwatson fprintf(debug_file, "\n\n"); 756156880Srwatson fprintf(debug_file, "#\n# Files that are only sources:\n"); 757156880Srwatson Lst_ForEach(allTargets, TargPrintOnlySrc, NULL); 758156880Srwatson fprintf(debug_file, "#*** Global Variables:\n"); 759156880Srwatson Var_Dump(VAR_GLOBAL); 760156880Srwatson fprintf(debug_file, "#*** Command-line Variables:\n"); 761156880Srwatson Var_Dump(VAR_CMD); 762156880Srwatson fprintf(debug_file, "\n"); 763156880Srwatson Dir_PrintDirectories(); 764156884Srwatson fprintf(debug_file, "\n"); 765156884Srwatson Suff_PrintAll(); 766156884Srwatson} 767156884Srwatson 768156884Srwatson/*- 769156884Srwatson *----------------------------------------------------------------------- 770156884Srwatson * TargPropagateNode -- 771156884Srwatson * Propagate information from a single node to related nodes if 772156884Srwatson * appropriate. 773156884Srwatson * 774159269Srwatson * Input: 775159269Srwatson * gnp The node that we are processing. 776159269Srwatson * 777159269Srwatson * Results: 778159269Srwatson * Always returns 0, for the benefit of Lst_ForEach(). 779159269Srwatson * 780159269Srwatson * Side Effects: 781159269Srwatson * Information is propagated from this node to cohort or child 782159269Srwatson * nodes. 783159269Srwatson * 784159269Srwatson * If the node was defined with "::", then TargPropagateCohort() 785159269Srwatson * will be called for each cohort node. 786159269Srwatson * 787159269Srwatson * If the node has recursive predecessors, then 788159269Srwatson * TargPropagateRecpred() will be called for each recursive 789159269Srwatson * predecessor. 790159269Srwatson *----------------------------------------------------------------------- 791159269Srwatson */ 792159269Srwatsonstatic int 793159269SrwatsonTargPropagateNode(void *gnp, void *junk MAKE_ATTR_UNUSED) 794159269Srwatson{ 795159269Srwatson GNode *gn = (GNode *)gnp; 796159269Srwatson 797159269Srwatson if (gn->type & OP_DOUBLEDEP) 798159269Srwatson Lst_ForEach(gn->cohorts, TargPropagateCohort, gnp); 799159269Srwatson return (0); 800159269Srwatson} 801159269Srwatson 802159269Srwatson/*- 803159269Srwatson *----------------------------------------------------------------------- 804159269Srwatson * TargPropagateCohort -- 805159269Srwatson * Propagate some bits in the type mask from a node to 806159269Srwatson * a related cohort node. 807159269Srwatson * 808159269Srwatson * Input: 809159269Srwatson * cnp The node that we are processing. 810159269Srwatson * gnp Another node that has cnp as a cohort. 811159269Srwatson * 812159269Srwatson * Results: 813159269Srwatson * Always returns 0, for the benefit of Lst_ForEach(). 814159269Srwatson * 815159269Srwatson * Side Effects: 816159269Srwatson * cnp's type bitmask is modified to incorporate some of the 817159269Srwatson * bits from gnp's type bitmask. (XXX need a better explanation.) 818159269Srwatson *----------------------------------------------------------------------- 819159269Srwatson */ 820159269Srwatsonstatic int 821159269SrwatsonTargPropagateCohort(void *cgnp, void *pgnp) 822159269Srwatson{ 823159269Srwatson GNode *cgn = (GNode *)cgnp; 824159269Srwatson GNode *pgn = (GNode *)pgnp; 825159269Srwatson 826159269Srwatson cgn->type |= pgn->type & ~OP_OPMASK; 827159269Srwatson return (0); 828159269Srwatson} 829159269Srwatson 830159269Srwatson/*- 831159269Srwatson *----------------------------------------------------------------------- 832159269Srwatson * Targ_Propagate -- 833159269Srwatson * Propagate information between related nodes. Should be called 834159269Srwatson * after the makefiles are parsed but before any action is taken. 835159269Srwatson * 836159269Srwatson * Results: 837159269Srwatson * none 838159269Srwatson * 839159269Srwatson * Side Effects: 840159269Srwatson * Information is propagated between related nodes throughout the 841159269Srwatson * graph. 842159269Srwatson *----------------------------------------------------------------------- 843159269Srwatson */ 844159269Srwatsonvoid 845159269SrwatsonTarg_Propagate(void) 846159269Srwatson{ 847159269Srwatson Lst_ForEach(allTargets, TargPropagateNode, NULL); 848159269Srwatson} 849159269Srwatson