1321964Ssjg/* $NetBSD: targ.c,v 1.62 2017/04/16 19:53:58 riastradh Exp $ */ 2236769Sobrien 3236769Sobrien/* 4236769Sobrien * Copyright (c) 1988, 1989, 1990, 1993 5236769Sobrien * The Regents of the University of California. All rights reserved. 6236769Sobrien * 7236769Sobrien * This code is derived from software contributed to Berkeley by 8236769Sobrien * Adam de Boor. 9236769Sobrien * 10236769Sobrien * Redistribution and use in source and binary forms, with or without 11236769Sobrien * modification, are permitted provided that the following conditions 12236769Sobrien * are met: 13236769Sobrien * 1. Redistributions of source code must retain the above copyright 14236769Sobrien * notice, this list of conditions and the following disclaimer. 15236769Sobrien * 2. Redistributions in binary form must reproduce the above copyright 16236769Sobrien * notice, this list of conditions and the following disclaimer in the 17236769Sobrien * documentation and/or other materials provided with the distribution. 18236769Sobrien * 3. Neither the name of the University nor the names of its contributors 19236769Sobrien * may be used to endorse or promote products derived from this software 20236769Sobrien * without specific prior written permission. 21236769Sobrien * 22236769Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23236769Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24236769Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25236769Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26236769Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27236769Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28236769Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29236769Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30236769Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31236769Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32236769Sobrien * SUCH DAMAGE. 33236769Sobrien */ 34236769Sobrien 35236769Sobrien/* 36236769Sobrien * Copyright (c) 1989 by Berkeley Softworks 37236769Sobrien * All rights reserved. 38236769Sobrien * 39236769Sobrien * This code is derived from software contributed to Berkeley by 40236769Sobrien * Adam de Boor. 41236769Sobrien * 42236769Sobrien * Redistribution and use in source and binary forms, with or without 43236769Sobrien * modification, are permitted provided that the following conditions 44236769Sobrien * are met: 45236769Sobrien * 1. Redistributions of source code must retain the above copyright 46236769Sobrien * notice, this list of conditions and the following disclaimer. 47236769Sobrien * 2. Redistributions in binary form must reproduce the above copyright 48236769Sobrien * notice, this list of conditions and the following disclaimer in the 49236769Sobrien * documentation and/or other materials provided with the distribution. 50236769Sobrien * 3. All advertising materials mentioning features or use of this software 51236769Sobrien * must display the following acknowledgement: 52236769Sobrien * This product includes software developed by the University of 53236769Sobrien * California, Berkeley and its contributors. 54236769Sobrien * 4. Neither the name of the University nor the names of its contributors 55236769Sobrien * may be used to endorse or promote products derived from this software 56236769Sobrien * without specific prior written permission. 57236769Sobrien * 58236769Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59236769Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60236769Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61236769Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62236769Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63236769Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64236769Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65236769Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66236769Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67236769Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68236769Sobrien * SUCH DAMAGE. 69236769Sobrien */ 70236769Sobrien 71236769Sobrien#ifndef MAKE_NATIVE 72321964Ssjgstatic char rcsid[] = "$NetBSD: targ.c,v 1.62 2017/04/16 19:53:58 riastradh Exp $"; 73236769Sobrien#else 74236769Sobrien#include <sys/cdefs.h> 75236769Sobrien#ifndef lint 76236769Sobrien#if 0 77236769Sobrienstatic char sccsid[] = "@(#)targ.c 8.2 (Berkeley) 3/19/94"; 78236769Sobrien#else 79321964Ssjg__RCSID("$NetBSD: targ.c,v 1.62 2017/04/16 19:53:58 riastradh Exp $"); 80236769Sobrien#endif 81236769Sobrien#endif /* not lint */ 82236769Sobrien#endif 83236769Sobrien 84236769Sobrien/*- 85236769Sobrien * targ.c -- 86236769Sobrien * Functions for maintaining the Lst allTargets. Target nodes are 87236769Sobrien * kept in two structures: a Lst, maintained by the list library, and a 88236769Sobrien * hash table, maintained by the hash library. 89236769Sobrien * 90236769Sobrien * Interface: 91236769Sobrien * Targ_Init Initialization procedure. 92236769Sobrien * 93236769Sobrien * Targ_End Cleanup the module 94236769Sobrien * 95236769Sobrien * Targ_List Return the list of all targets so far. 96236769Sobrien * 97236769Sobrien * Targ_NewGN Create a new GNode for the passed target 98236769Sobrien * (string). The node is *not* placed in the 99236769Sobrien * hash table, though all its fields are 100236769Sobrien * initialized. 101236769Sobrien * 102236769Sobrien * Targ_FindNode Find the node for a given target, creating 103236769Sobrien * and storing it if it doesn't exist and the 104236769Sobrien * flags are right (TARG_CREATE) 105236769Sobrien * 106236769Sobrien * Targ_FindList Given a list of names, find nodes for all 107236769Sobrien * of them. If a name doesn't exist and the 108236769Sobrien * TARG_NOCREATE flag was given, an error message 109236769Sobrien * is printed. Else, if a name doesn't exist, 110236769Sobrien * its node is created. 111236769Sobrien * 112236769Sobrien * Targ_Ignore Return TRUE if errors should be ignored when 113236769Sobrien * creating the given target. 114236769Sobrien * 115236769Sobrien * Targ_Silent Return TRUE if we should be silent when 116236769Sobrien * creating the given target. 117236769Sobrien * 118236769Sobrien * Targ_Precious Return TRUE if the target is precious and 119236769Sobrien * should not be removed if we are interrupted. 120236769Sobrien * 121236769Sobrien * Targ_Propagate Propagate information between related 122236769Sobrien * nodes. Should be called after the 123236769Sobrien * makefiles are parsed but before any 124236769Sobrien * action is taken. 125236769Sobrien * 126236769Sobrien * Debugging: 127236769Sobrien * Targ_PrintGraph Print out the entire graphm all variables 128236769Sobrien * and statistics for the directory cache. Should 129236769Sobrien * print something for suffixes, too, but... 130236769Sobrien */ 131236769Sobrien 132236769Sobrien#include <stdio.h> 133236769Sobrien#include <time.h> 134236769Sobrien 135236769Sobrien#include "make.h" 136236769Sobrien#include "hash.h" 137236769Sobrien#include "dir.h" 138236769Sobrien 139236769Sobrienstatic Lst allTargets; /* the list of all targets found so far */ 140236769Sobrien#ifdef CLEANUP 141236769Sobrienstatic Lst allGNs; /* List of all the GNodes */ 142236769Sobrien#endif 143236769Sobrienstatic Hash_Table targets; /* a hash table of same */ 144236769Sobrien 145236769Sobrien#define HTSIZE 191 /* initial size of hash table */ 146236769Sobrien 147236769Sobrienstatic int TargPrintOnlySrc(void *, void *); 148236769Sobrienstatic int TargPrintName(void *, void *); 149236769Sobrien#ifdef CLEANUP 150236769Sobrienstatic void TargFreeGN(void *); 151236769Sobrien#endif 152236769Sobrienstatic int TargPropagateCohort(void *, void *); 153236769Sobrienstatic int TargPropagateNode(void *, void *); 154236769Sobrien 155236769Sobrien/*- 156236769Sobrien *----------------------------------------------------------------------- 157236769Sobrien * Targ_Init -- 158236769Sobrien * Initialize this module 159236769Sobrien * 160236769Sobrien * Results: 161236769Sobrien * None 162236769Sobrien * 163236769Sobrien * Side Effects: 164236769Sobrien * The allTargets list and the targets hash table are initialized 165236769Sobrien *----------------------------------------------------------------------- 166236769Sobrien */ 167236769Sobrienvoid 168236769SobrienTarg_Init(void) 169236769Sobrien{ 170236769Sobrien allTargets = Lst_Init(FALSE); 171236769Sobrien Hash_InitTable(&targets, HTSIZE); 172236769Sobrien} 173236769Sobrien 174236769Sobrien/*- 175236769Sobrien *----------------------------------------------------------------------- 176236769Sobrien * Targ_End -- 177236769Sobrien * Finalize this module 178236769Sobrien * 179236769Sobrien * Results: 180236769Sobrien * None 181236769Sobrien * 182236769Sobrien * Side Effects: 183236769Sobrien * All lists and gnodes are cleared 184236769Sobrien *----------------------------------------------------------------------- 185236769Sobrien */ 186236769Sobrienvoid 187236769SobrienTarg_End(void) 188236769Sobrien{ 189236769Sobrien#ifdef CLEANUP 190236769Sobrien Lst_Destroy(allTargets, NULL); 191236769Sobrien if (allGNs) 192236769Sobrien Lst_Destroy(allGNs, TargFreeGN); 193236769Sobrien Hash_DeleteTable(&targets); 194236769Sobrien#endif 195236769Sobrien} 196236769Sobrien 197236769Sobrien/*- 198236769Sobrien *----------------------------------------------------------------------- 199236769Sobrien * Targ_List -- 200236769Sobrien * Return the list of all targets 201236769Sobrien * 202236769Sobrien * Results: 203236769Sobrien * The list of all targets. 204236769Sobrien * 205236769Sobrien * Side Effects: 206236769Sobrien * None 207236769Sobrien *----------------------------------------------------------------------- 208236769Sobrien */ 209236769SobrienLst 210236769SobrienTarg_List(void) 211236769Sobrien{ 212236769Sobrien return allTargets; 213236769Sobrien} 214236769Sobrien 215236769Sobrien/*- 216236769Sobrien *----------------------------------------------------------------------- 217236769Sobrien * Targ_NewGN -- 218236769Sobrien * Create and initialize a new graph node 219236769Sobrien * 220236769Sobrien * Input: 221236769Sobrien * name the name to stick in the new node 222236769Sobrien * 223236769Sobrien * Results: 224236769Sobrien * An initialized graph node with the name field filled with a copy 225236769Sobrien * of the passed name 226236769Sobrien * 227236769Sobrien * Side Effects: 228236769Sobrien * The gnode is added to the list of all gnodes. 229236769Sobrien *----------------------------------------------------------------------- 230236769Sobrien */ 231236769SobrienGNode * 232236769SobrienTarg_NewGN(const char *name) 233236769Sobrien{ 234236769Sobrien GNode *gn; 235236769Sobrien 236236769Sobrien gn = bmake_malloc(sizeof(GNode)); 237236769Sobrien gn->name = bmake_strdup(name); 238236769Sobrien gn->uname = NULL; 239236769Sobrien gn->path = NULL; 240236769Sobrien if (name[0] == '-' && name[1] == 'l') { 241236769Sobrien gn->type = OP_LIB; 242236769Sobrien } else { 243236769Sobrien gn->type = 0; 244236769Sobrien } 245236769Sobrien gn->unmade = 0; 246236769Sobrien gn->unmade_cohorts = 0; 247236769Sobrien gn->cohort_num[0] = 0; 248236769Sobrien gn->centurion = NULL; 249236769Sobrien gn->made = UNMADE; 250236769Sobrien gn->flags = 0; 251236769Sobrien gn->checked = 0; 252236769Sobrien gn->mtime = 0; 253236769Sobrien gn->cmgn = NULL; 254236769Sobrien gn->iParents = Lst_Init(FALSE); 255236769Sobrien gn->cohorts = Lst_Init(FALSE); 256236769Sobrien gn->parents = Lst_Init(FALSE); 257236769Sobrien gn->children = Lst_Init(FALSE); 258236769Sobrien gn->order_pred = Lst_Init(FALSE); 259236769Sobrien gn->order_succ = Lst_Init(FALSE); 260236769Sobrien Hash_InitTable(&gn->context, 0); 261236769Sobrien gn->commands = Lst_Init(FALSE); 262236769Sobrien gn->suffix = NULL; 263236769Sobrien gn->lineno = 0; 264236769Sobrien gn->fname = NULL; 265236769Sobrien 266236769Sobrien#ifdef CLEANUP 267236769Sobrien if (allGNs == NULL) 268236769Sobrien allGNs = Lst_Init(FALSE); 269236769Sobrien Lst_AtEnd(allGNs, gn); 270236769Sobrien#endif 271236769Sobrien 272236769Sobrien return (gn); 273236769Sobrien} 274236769Sobrien 275236769Sobrien#ifdef CLEANUP 276236769Sobrien/*- 277236769Sobrien *----------------------------------------------------------------------- 278236769Sobrien * TargFreeGN -- 279236769Sobrien * Destroy a GNode 280236769Sobrien * 281236769Sobrien * Results: 282236769Sobrien * None. 283236769Sobrien * 284236769Sobrien * Side Effects: 285236769Sobrien * None. 286236769Sobrien *----------------------------------------------------------------------- 287236769Sobrien */ 288236769Sobrienstatic void 289236769SobrienTargFreeGN(void *gnp) 290236769Sobrien{ 291236769Sobrien GNode *gn = (GNode *)gnp; 292236769Sobrien 293236769Sobrien 294236769Sobrien free(gn->name); 295321964Ssjg free(gn->uname); 296321964Ssjg free(gn->path); 297236769Sobrien /* gn->fname points to name allocated when file was opened, don't free */ 298236769Sobrien 299236769Sobrien Lst_Destroy(gn->iParents, NULL); 300236769Sobrien Lst_Destroy(gn->cohorts, NULL); 301236769Sobrien Lst_Destroy(gn->parents, NULL); 302236769Sobrien Lst_Destroy(gn->children, NULL); 303236769Sobrien Lst_Destroy(gn->order_succ, NULL); 304236769Sobrien Lst_Destroy(gn->order_pred, NULL); 305236769Sobrien Hash_DeleteTable(&gn->context); 306236769Sobrien Lst_Destroy(gn->commands, NULL); 307236769Sobrien free(gn); 308236769Sobrien} 309236769Sobrien#endif 310236769Sobrien 311236769Sobrien 312236769Sobrien/*- 313236769Sobrien *----------------------------------------------------------------------- 314236769Sobrien * Targ_FindNode -- 315236769Sobrien * Find a node in the list using the given name for matching 316236769Sobrien * 317236769Sobrien * Input: 318236769Sobrien * name the name to find 319236769Sobrien * flags flags governing events when target not 320236769Sobrien * found 321236769Sobrien * 322236769Sobrien * Results: 323236769Sobrien * The node in the list if it was. If it wasn't, return NULL of 324236769Sobrien * flags was TARG_NOCREATE or the newly created and initialized node 325236769Sobrien * if it was TARG_CREATE 326236769Sobrien * 327236769Sobrien * Side Effects: 328236769Sobrien * Sometimes a node is created and added to the list 329236769Sobrien *----------------------------------------------------------------------- 330236769Sobrien */ 331236769SobrienGNode * 332236769SobrienTarg_FindNode(const char *name, int flags) 333236769Sobrien{ 334236769Sobrien GNode *gn; /* node in that element */ 335236769Sobrien Hash_Entry *he = NULL; /* New or used hash entry for node */ 336236769Sobrien Boolean isNew; /* Set TRUE if Hash_CreateEntry had to create */ 337236769Sobrien /* an entry for the node */ 338236769Sobrien 339236769Sobrien if (!(flags & (TARG_CREATE | TARG_NOHASH))) { 340236769Sobrien he = Hash_FindEntry(&targets, name); 341236769Sobrien if (he == NULL) 342236769Sobrien return NULL; 343236769Sobrien return (GNode *)Hash_GetValue(he); 344236769Sobrien } 345236769Sobrien 346236769Sobrien if (!(flags & TARG_NOHASH)) { 347236769Sobrien he = Hash_CreateEntry(&targets, name, &isNew); 348236769Sobrien if (!isNew) 349236769Sobrien return (GNode *)Hash_GetValue(he); 350236769Sobrien } 351236769Sobrien 352236769Sobrien gn = Targ_NewGN(name); 353236769Sobrien if (!(flags & TARG_NOHASH)) 354236769Sobrien Hash_SetValue(he, gn); 355236769Sobrien Var_Append(".ALLTARGETS", name, VAR_GLOBAL); 356236769Sobrien (void)Lst_AtEnd(allTargets, gn); 357236769Sobrien if (doing_depend) 358236769Sobrien gn->flags |= FROM_DEPEND; 359236769Sobrien return gn; 360236769Sobrien} 361236769Sobrien 362236769Sobrien/*- 363236769Sobrien *----------------------------------------------------------------------- 364236769Sobrien * Targ_FindList -- 365236769Sobrien * Make a complete list of GNodes from the given list of names 366236769Sobrien * 367236769Sobrien * Input: 368236769Sobrien * name list of names to find 369236769Sobrien * flags flags used if no node is found for a given name 370236769Sobrien * 371236769Sobrien * Results: 372236769Sobrien * A complete list of graph nodes corresponding to all instances of all 373236769Sobrien * the names in names. 374236769Sobrien * 375236769Sobrien * Side Effects: 376236769Sobrien * If flags is TARG_CREATE, nodes will be created for all names in 377236769Sobrien * names which do not yet have graph nodes. If flags is TARG_NOCREATE, 378236769Sobrien * an error message will be printed for each name which can't be found. 379236769Sobrien * ----------------------------------------------------------------------- 380236769Sobrien */ 381236769SobrienLst 382236769SobrienTarg_FindList(Lst names, int flags) 383236769Sobrien{ 384236769Sobrien Lst nodes; /* result list */ 385236769Sobrien LstNode ln; /* name list element */ 386236769Sobrien GNode *gn; /* node in tLn */ 387236769Sobrien char *name; 388236769Sobrien 389236769Sobrien nodes = Lst_Init(FALSE); 390236769Sobrien 391236769Sobrien if (Lst_Open(names) == FAILURE) { 392236769Sobrien return (nodes); 393236769Sobrien } 394236769Sobrien while ((ln = Lst_Next(names)) != NULL) { 395236769Sobrien name = (char *)Lst_Datum(ln); 396236769Sobrien gn = Targ_FindNode(name, flags); 397236769Sobrien if (gn != NULL) { 398236769Sobrien /* 399236769Sobrien * Note: Lst_AtEnd must come before the Lst_Concat so the nodes 400236769Sobrien * are added to the list in the order in which they were 401236769Sobrien * encountered in the makefile. 402236769Sobrien */ 403236769Sobrien (void)Lst_AtEnd(nodes, gn); 404236769Sobrien } else if (flags == TARG_NOCREATE) { 405236769Sobrien Error("\"%s\" -- target unknown.", name); 406236769Sobrien } 407236769Sobrien } 408236769Sobrien Lst_Close(names); 409236769Sobrien return (nodes); 410236769Sobrien} 411236769Sobrien 412236769Sobrien/*- 413236769Sobrien *----------------------------------------------------------------------- 414236769Sobrien * Targ_Ignore -- 415236769Sobrien * Return true if should ignore errors when creating gn 416236769Sobrien * 417236769Sobrien * Input: 418236769Sobrien * gn node to check for 419236769Sobrien * 420236769Sobrien * Results: 421236769Sobrien * TRUE if should ignore errors 422236769Sobrien * 423236769Sobrien * Side Effects: 424236769Sobrien * None 425236769Sobrien *----------------------------------------------------------------------- 426236769Sobrien */ 427236769SobrienBoolean 428236769SobrienTarg_Ignore(GNode *gn) 429236769Sobrien{ 430236769Sobrien if (ignoreErrors || gn->type & OP_IGNORE) { 431236769Sobrien return (TRUE); 432236769Sobrien } else { 433236769Sobrien return (FALSE); 434236769Sobrien } 435236769Sobrien} 436236769Sobrien 437236769Sobrien/*- 438236769Sobrien *----------------------------------------------------------------------- 439236769Sobrien * Targ_Silent -- 440236769Sobrien * Return true if be silent when creating gn 441236769Sobrien * 442236769Sobrien * Input: 443236769Sobrien * gn node to check for 444236769Sobrien * 445236769Sobrien * Results: 446236769Sobrien * TRUE if should be silent 447236769Sobrien * 448236769Sobrien * Side Effects: 449236769Sobrien * None 450236769Sobrien *----------------------------------------------------------------------- 451236769Sobrien */ 452236769SobrienBoolean 453236769SobrienTarg_Silent(GNode *gn) 454236769Sobrien{ 455236769Sobrien if (beSilent || gn->type & OP_SILENT) { 456236769Sobrien return (TRUE); 457236769Sobrien } else { 458236769Sobrien return (FALSE); 459236769Sobrien } 460236769Sobrien} 461236769Sobrien 462236769Sobrien/*- 463236769Sobrien *----------------------------------------------------------------------- 464236769Sobrien * Targ_Precious -- 465236769Sobrien * See if the given target is precious 466236769Sobrien * 467236769Sobrien * Input: 468236769Sobrien * gn the node to check 469236769Sobrien * 470236769Sobrien * Results: 471236769Sobrien * TRUE if it is precious. FALSE otherwise 472236769Sobrien * 473236769Sobrien * Side Effects: 474236769Sobrien * None 475236769Sobrien *----------------------------------------------------------------------- 476236769Sobrien */ 477236769SobrienBoolean 478236769SobrienTarg_Precious(GNode *gn) 479236769Sobrien{ 480236769Sobrien if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP))) { 481236769Sobrien return (TRUE); 482236769Sobrien } else { 483236769Sobrien return (FALSE); 484236769Sobrien } 485236769Sobrien} 486236769Sobrien 487236769Sobrien/******************* DEBUG INFO PRINTING ****************/ 488236769Sobrien 489236769Sobrienstatic GNode *mainTarg; /* the main target, as set by Targ_SetMain */ 490236769Sobrien/*- 491236769Sobrien *----------------------------------------------------------------------- 492236769Sobrien * Targ_SetMain -- 493236769Sobrien * Set our idea of the main target we'll be creating. Used for 494236769Sobrien * debugging output. 495236769Sobrien * 496236769Sobrien * Input: 497236769Sobrien * gn The main target we'll create 498236769Sobrien * 499236769Sobrien * Results: 500236769Sobrien * None. 501236769Sobrien * 502236769Sobrien * Side Effects: 503236769Sobrien * "mainTarg" is set to the main target's node. 504236769Sobrien *----------------------------------------------------------------------- 505236769Sobrien */ 506236769Sobrienvoid 507236769SobrienTarg_SetMain(GNode *gn) 508236769Sobrien{ 509236769Sobrien mainTarg = gn; 510236769Sobrien} 511236769Sobrien 512236769Sobrienstatic int 513237578SobrienTargPrintName(void *gnp, void *pflags MAKE_ATTR_UNUSED) 514236769Sobrien{ 515236769Sobrien GNode *gn = (GNode *)gnp; 516236769Sobrien 517236769Sobrien fprintf(debug_file, "%s%s ", gn->name, gn->cohort_num); 518236769Sobrien 519236769Sobrien return 0; 520236769Sobrien} 521236769Sobrien 522236769Sobrien 523236769Sobrienint 524321964SsjgTarg_PrintCmd(void *cmd, void *dummy MAKE_ATTR_UNUSED) 525236769Sobrien{ 526236769Sobrien fprintf(debug_file, "\t%s\n", (char *)cmd); 527321964Ssjg return 0; 528236769Sobrien} 529236769Sobrien 530236769Sobrien/*- 531236769Sobrien *----------------------------------------------------------------------- 532236769Sobrien * Targ_FmtTime -- 533236769Sobrien * Format a modification time in some reasonable way and return it. 534236769Sobrien * 535236769Sobrien * Results: 536236769Sobrien * The time reformatted. 537236769Sobrien * 538236769Sobrien * Side Effects: 539236769Sobrien * The time is placed in a static area, so it is overwritten 540236769Sobrien * with each call. 541236769Sobrien * 542236769Sobrien *----------------------------------------------------------------------- 543236769Sobrien */ 544236769Sobrienchar * 545236769SobrienTarg_FmtTime(time_t tm) 546236769Sobrien{ 547236769Sobrien struct tm *parts; 548236769Sobrien static char buf[128]; 549236769Sobrien 550236769Sobrien parts = localtime(&tm); 551236769Sobrien (void)strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts); 552236769Sobrien return(buf); 553236769Sobrien} 554236769Sobrien 555236769Sobrien/*- 556236769Sobrien *----------------------------------------------------------------------- 557236769Sobrien * Targ_PrintType -- 558236769Sobrien * Print out a type field giving only those attributes the user can 559236769Sobrien * set. 560236769Sobrien * 561236769Sobrien * Results: 562236769Sobrien * 563236769Sobrien * Side Effects: 564236769Sobrien * 565236769Sobrien *----------------------------------------------------------------------- 566236769Sobrien */ 567236769Sobrienvoid 568236769SobrienTarg_PrintType(int type) 569236769Sobrien{ 570236769Sobrien int tbit; 571236769Sobrien 572236769Sobrien#define PRINTBIT(attr) case CONCAT(OP_,attr): fprintf(debug_file, "." #attr " "); break 573236769Sobrien#define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG))fprintf(debug_file, "." #attr " "); break 574236769Sobrien 575236769Sobrien type &= ~OP_OPMASK; 576236769Sobrien 577236769Sobrien while (type) { 578236769Sobrien tbit = 1 << (ffs(type) - 1); 579236769Sobrien type &= ~tbit; 580236769Sobrien 581236769Sobrien switch(tbit) { 582236769Sobrien PRINTBIT(OPTIONAL); 583236769Sobrien PRINTBIT(USE); 584236769Sobrien PRINTBIT(EXEC); 585236769Sobrien PRINTBIT(IGNORE); 586236769Sobrien PRINTBIT(PRECIOUS); 587236769Sobrien PRINTBIT(SILENT); 588236769Sobrien PRINTBIT(MAKE); 589236769Sobrien PRINTBIT(JOIN); 590236769Sobrien PRINTBIT(INVISIBLE); 591236769Sobrien PRINTBIT(NOTMAIN); 592236769Sobrien PRINTDBIT(LIB); 593236769Sobrien /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */ 594236769Sobrien case OP_MEMBER: if (DEBUG(TARG))fprintf(debug_file, ".MEMBER "); break; 595236769Sobrien PRINTDBIT(ARCHV); 596236769Sobrien PRINTDBIT(MADE); 597236769Sobrien PRINTDBIT(PHONY); 598236769Sobrien } 599236769Sobrien } 600236769Sobrien} 601236769Sobrien 602236769Sobrienstatic const char * 603236769Sobrienmade_name(enum enum_made made) 604236769Sobrien{ 605236769Sobrien switch (made) { 606236769Sobrien case UNMADE: return "unmade"; 607236769Sobrien case DEFERRED: return "deferred"; 608236769Sobrien case REQUESTED: return "requested"; 609236769Sobrien case BEINGMADE: return "being made"; 610236769Sobrien case MADE: return "made"; 611236769Sobrien case UPTODATE: return "up-to-date"; 612236769Sobrien case ERROR: return "error when made"; 613236769Sobrien case ABORTED: return "aborted"; 614236769Sobrien default: return "unknown enum_made value"; 615236769Sobrien } 616236769Sobrien} 617236769Sobrien 618236769Sobrien/*- 619236769Sobrien *----------------------------------------------------------------------- 620236769Sobrien * TargPrintNode -- 621236769Sobrien * print the contents of a node 622236769Sobrien *----------------------------------------------------------------------- 623236769Sobrien */ 624236769Sobrienint 625236769SobrienTarg_PrintNode(void *gnp, void *passp) 626236769Sobrien{ 627236769Sobrien GNode *gn = (GNode *)gnp; 628236769Sobrien int pass = passp ? *(int *)passp : 0; 629236769Sobrien 630236769Sobrien fprintf(debug_file, "# %s%s, flags %x, type %x, made %d\n", 631236769Sobrien gn->name, gn->cohort_num, gn->flags, gn->type, gn->made); 632236769Sobrien if (gn->flags == 0) 633236769Sobrien return 0; 634236769Sobrien 635236769Sobrien if (!OP_NOP(gn->type)) { 636236769Sobrien fprintf(debug_file, "#\n"); 637236769Sobrien if (gn == mainTarg) { 638236769Sobrien fprintf(debug_file, "# *** MAIN TARGET ***\n"); 639236769Sobrien } 640236769Sobrien if (pass >= 2) { 641236769Sobrien if (gn->unmade) { 642236769Sobrien fprintf(debug_file, "# %d unmade children\n", gn->unmade); 643236769Sobrien } else { 644236769Sobrien fprintf(debug_file, "# No unmade children\n"); 645236769Sobrien } 646236769Sobrien if (! (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC))) { 647236769Sobrien if (gn->mtime != 0) { 648236769Sobrien fprintf(debug_file, "# last modified %s: %s\n", 649236769Sobrien Targ_FmtTime(gn->mtime), 650236769Sobrien made_name(gn->made)); 651236769Sobrien } else if (gn->made != UNMADE) { 652236769Sobrien fprintf(debug_file, "# non-existent (maybe): %s\n", 653236769Sobrien made_name(gn->made)); 654236769Sobrien } else { 655236769Sobrien fprintf(debug_file, "# unmade\n"); 656236769Sobrien } 657236769Sobrien } 658236769Sobrien if (!Lst_IsEmpty (gn->iParents)) { 659236769Sobrien fprintf(debug_file, "# implicit parents: "); 660236769Sobrien Lst_ForEach(gn->iParents, TargPrintName, NULL); 661236769Sobrien fprintf(debug_file, "\n"); 662236769Sobrien } 663236769Sobrien } else { 664236769Sobrien if (gn->unmade) 665236769Sobrien fprintf(debug_file, "# %d unmade children\n", gn->unmade); 666236769Sobrien } 667236769Sobrien if (!Lst_IsEmpty (gn->parents)) { 668236769Sobrien fprintf(debug_file, "# parents: "); 669236769Sobrien Lst_ForEach(gn->parents, TargPrintName, NULL); 670236769Sobrien fprintf(debug_file, "\n"); 671236769Sobrien } 672236769Sobrien if (!Lst_IsEmpty (gn->order_pred)) { 673236769Sobrien fprintf(debug_file, "# order_pred: "); 674236769Sobrien Lst_ForEach(gn->order_pred, TargPrintName, NULL); 675236769Sobrien fprintf(debug_file, "\n"); 676236769Sobrien } 677236769Sobrien if (!Lst_IsEmpty (gn->order_succ)) { 678236769Sobrien fprintf(debug_file, "# order_succ: "); 679236769Sobrien Lst_ForEach(gn->order_succ, TargPrintName, NULL); 680236769Sobrien fprintf(debug_file, "\n"); 681236769Sobrien } 682236769Sobrien 683236769Sobrien fprintf(debug_file, "%-16s", gn->name); 684236769Sobrien switch (gn->type & OP_OPMASK) { 685236769Sobrien case OP_DEPENDS: 686236769Sobrien fprintf(debug_file, ": "); break; 687236769Sobrien case OP_FORCE: 688236769Sobrien fprintf(debug_file, "! "); break; 689236769Sobrien case OP_DOUBLEDEP: 690236769Sobrien fprintf(debug_file, ":: "); break; 691236769Sobrien } 692236769Sobrien Targ_PrintType(gn->type); 693236769Sobrien Lst_ForEach(gn->children, TargPrintName, NULL); 694236769Sobrien fprintf(debug_file, "\n"); 695236769Sobrien Lst_ForEach(gn->commands, Targ_PrintCmd, NULL); 696236769Sobrien fprintf(debug_file, "\n\n"); 697236769Sobrien if (gn->type & OP_DOUBLEDEP) { 698236769Sobrien Lst_ForEach(gn->cohorts, Targ_PrintNode, &pass); 699236769Sobrien } 700236769Sobrien } 701236769Sobrien return (0); 702236769Sobrien} 703236769Sobrien 704236769Sobrien/*- 705236769Sobrien *----------------------------------------------------------------------- 706236769Sobrien * TargPrintOnlySrc -- 707236769Sobrien * Print only those targets that are just a source. 708236769Sobrien * 709236769Sobrien * Results: 710236769Sobrien * 0. 711236769Sobrien * 712236769Sobrien * Side Effects: 713236769Sobrien * The name of each file is printed preceded by #\t 714236769Sobrien * 715236769Sobrien *----------------------------------------------------------------------- 716236769Sobrien */ 717236769Sobrienstatic int 718237578SobrienTargPrintOnlySrc(void *gnp, void *dummy MAKE_ATTR_UNUSED) 719236769Sobrien{ 720236769Sobrien GNode *gn = (GNode *)gnp; 721236769Sobrien if (!OP_NOP(gn->type)) 722236769Sobrien return 0; 723236769Sobrien 724236769Sobrien fprintf(debug_file, "#\t%s [%s] ", 725236769Sobrien gn->name, gn->path ? gn->path : gn->name); 726236769Sobrien Targ_PrintType(gn->type); 727236769Sobrien fprintf(debug_file, "\n"); 728236769Sobrien 729236769Sobrien return 0; 730236769Sobrien} 731236769Sobrien 732236769Sobrien/*- 733236769Sobrien *----------------------------------------------------------------------- 734236769Sobrien * Targ_PrintGraph -- 735236769Sobrien * print the entire graph. heh heh 736236769Sobrien * 737236769Sobrien * Input: 738236769Sobrien * pass Which pass this is. 1 => no processing 739236769Sobrien * 2 => processing done 740236769Sobrien * 741236769Sobrien * Results: 742236769Sobrien * none 743236769Sobrien * 744236769Sobrien * Side Effects: 745236769Sobrien * lots o' output 746236769Sobrien *----------------------------------------------------------------------- 747236769Sobrien */ 748236769Sobrienvoid 749236769SobrienTarg_PrintGraph(int pass) 750236769Sobrien{ 751236769Sobrien fprintf(debug_file, "#*** Input graph:\n"); 752236769Sobrien Lst_ForEach(allTargets, Targ_PrintNode, &pass); 753236769Sobrien fprintf(debug_file, "\n\n"); 754236769Sobrien fprintf(debug_file, "#\n# Files that are only sources:\n"); 755236769Sobrien Lst_ForEach(allTargets, TargPrintOnlySrc, NULL); 756236769Sobrien fprintf(debug_file, "#*** Global Variables:\n"); 757236769Sobrien Var_Dump(VAR_GLOBAL); 758236769Sobrien fprintf(debug_file, "#*** Command-line Variables:\n"); 759236769Sobrien Var_Dump(VAR_CMD); 760236769Sobrien fprintf(debug_file, "\n"); 761236769Sobrien Dir_PrintDirectories(); 762236769Sobrien fprintf(debug_file, "\n"); 763236769Sobrien Suff_PrintAll(); 764236769Sobrien} 765236769Sobrien 766236769Sobrien/*- 767236769Sobrien *----------------------------------------------------------------------- 768236769Sobrien * TargPropagateNode -- 769236769Sobrien * Propagate information from a single node to related nodes if 770236769Sobrien * appropriate. 771236769Sobrien * 772236769Sobrien * Input: 773236769Sobrien * gnp The node that we are processing. 774236769Sobrien * 775236769Sobrien * Results: 776236769Sobrien * Always returns 0, for the benefit of Lst_ForEach(). 777236769Sobrien * 778236769Sobrien * Side Effects: 779236769Sobrien * Information is propagated from this node to cohort or child 780236769Sobrien * nodes. 781236769Sobrien * 782236769Sobrien * If the node was defined with "::", then TargPropagateCohort() 783236769Sobrien * will be called for each cohort node. 784236769Sobrien * 785236769Sobrien * If the node has recursive predecessors, then 786236769Sobrien * TargPropagateRecpred() will be called for each recursive 787236769Sobrien * predecessor. 788236769Sobrien *----------------------------------------------------------------------- 789236769Sobrien */ 790236769Sobrienstatic int 791237578SobrienTargPropagateNode(void *gnp, void *junk MAKE_ATTR_UNUSED) 792236769Sobrien{ 793236769Sobrien GNode *gn = (GNode *)gnp; 794236769Sobrien 795236769Sobrien if (gn->type & OP_DOUBLEDEP) 796236769Sobrien Lst_ForEach(gn->cohorts, TargPropagateCohort, gnp); 797236769Sobrien return (0); 798236769Sobrien} 799236769Sobrien 800236769Sobrien/*- 801236769Sobrien *----------------------------------------------------------------------- 802236769Sobrien * TargPropagateCohort -- 803236769Sobrien * Propagate some bits in the type mask from a node to 804236769Sobrien * a related cohort node. 805236769Sobrien * 806236769Sobrien * Input: 807236769Sobrien * cnp The node that we are processing. 808236769Sobrien * gnp Another node that has cnp as a cohort. 809236769Sobrien * 810236769Sobrien * Results: 811236769Sobrien * Always returns 0, for the benefit of Lst_ForEach(). 812236769Sobrien * 813236769Sobrien * Side Effects: 814236769Sobrien * cnp's type bitmask is modified to incorporate some of the 815236769Sobrien * bits from gnp's type bitmask. (XXX need a better explanation.) 816236769Sobrien *----------------------------------------------------------------------- 817236769Sobrien */ 818236769Sobrienstatic int 819236769SobrienTargPropagateCohort(void *cgnp, void *pgnp) 820236769Sobrien{ 821236769Sobrien GNode *cgn = (GNode *)cgnp; 822236769Sobrien GNode *pgn = (GNode *)pgnp; 823236769Sobrien 824236769Sobrien cgn->type |= pgn->type & ~OP_OPMASK; 825236769Sobrien return (0); 826236769Sobrien} 827236769Sobrien 828236769Sobrien/*- 829236769Sobrien *----------------------------------------------------------------------- 830236769Sobrien * Targ_Propagate -- 831236769Sobrien * Propagate information between related nodes. Should be called 832236769Sobrien * after the makefiles are parsed but before any action is taken. 833236769Sobrien * 834236769Sobrien * Results: 835236769Sobrien * none 836236769Sobrien * 837236769Sobrien * Side Effects: 838236769Sobrien * Information is propagated between related nodes throughout the 839236769Sobrien * graph. 840236769Sobrien *----------------------------------------------------------------------- 841236769Sobrien */ 842236769Sobrienvoid 843236769SobrienTarg_Propagate(void) 844236769Sobrien{ 845236769Sobrien Lst_ForEach(allTargets, TargPropagateNode, NULL); 846236769Sobrien} 847