1237578Sobrien/* $NetBSD: targ.c,v 1.57 2012/06/12 19:21:51 joerg 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 72237578Sobrienstatic char rcsid[] = "$NetBSD: targ.c,v 1.57 2012/06/12 19:21:51 joerg 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 79237578Sobrien__RCSID("$NetBSD: targ.c,v 1.57 2012/06/12 19:21:51 joerg 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); 295236769Sobrien if (gn->uname) 296236769Sobrien free(gn->uname); 297236769Sobrien if (gn->path) 298236769Sobrien free(gn->path); 299236769Sobrien /* gn->fname points to name allocated when file was opened, don't free */ 300236769Sobrien 301236769Sobrien Lst_Destroy(gn->iParents, NULL); 302236769Sobrien Lst_Destroy(gn->cohorts, NULL); 303236769Sobrien Lst_Destroy(gn->parents, NULL); 304236769Sobrien Lst_Destroy(gn->children, NULL); 305236769Sobrien Lst_Destroy(gn->order_succ, NULL); 306236769Sobrien Lst_Destroy(gn->order_pred, NULL); 307236769Sobrien Hash_DeleteTable(&gn->context); 308236769Sobrien Lst_Destroy(gn->commands, NULL); 309236769Sobrien free(gn); 310236769Sobrien} 311236769Sobrien#endif 312236769Sobrien 313236769Sobrien 314236769Sobrien/*- 315236769Sobrien *----------------------------------------------------------------------- 316236769Sobrien * Targ_FindNode -- 317236769Sobrien * Find a node in the list using the given name for matching 318236769Sobrien * 319236769Sobrien * Input: 320236769Sobrien * name the name to find 321236769Sobrien * flags flags governing events when target not 322236769Sobrien * found 323236769Sobrien * 324236769Sobrien * Results: 325236769Sobrien * The node in the list if it was. If it wasn't, return NULL of 326236769Sobrien * flags was TARG_NOCREATE or the newly created and initialized node 327236769Sobrien * if it was TARG_CREATE 328236769Sobrien * 329236769Sobrien * Side Effects: 330236769Sobrien * Sometimes a node is created and added to the list 331236769Sobrien *----------------------------------------------------------------------- 332236769Sobrien */ 333236769SobrienGNode * 334236769SobrienTarg_FindNode(const char *name, int flags) 335236769Sobrien{ 336236769Sobrien GNode *gn; /* node in that element */ 337236769Sobrien Hash_Entry *he = NULL; /* New or used hash entry for node */ 338236769Sobrien Boolean isNew; /* Set TRUE if Hash_CreateEntry had to create */ 339236769Sobrien /* an entry for the node */ 340236769Sobrien 341236769Sobrien if (!(flags & (TARG_CREATE | TARG_NOHASH))) { 342236769Sobrien he = Hash_FindEntry(&targets, name); 343236769Sobrien if (he == NULL) 344236769Sobrien return NULL; 345236769Sobrien return (GNode *)Hash_GetValue(he); 346236769Sobrien } 347236769Sobrien 348236769Sobrien if (!(flags & TARG_NOHASH)) { 349236769Sobrien he = Hash_CreateEntry(&targets, name, &isNew); 350236769Sobrien if (!isNew) 351236769Sobrien return (GNode *)Hash_GetValue(he); 352236769Sobrien } 353236769Sobrien 354236769Sobrien gn = Targ_NewGN(name); 355236769Sobrien if (!(flags & TARG_NOHASH)) 356236769Sobrien Hash_SetValue(he, gn); 357236769Sobrien Var_Append(".ALLTARGETS", name, VAR_GLOBAL); 358236769Sobrien (void)Lst_AtEnd(allTargets, gn); 359236769Sobrien if (doing_depend) 360236769Sobrien gn->flags |= FROM_DEPEND; 361236769Sobrien return gn; 362236769Sobrien} 363236769Sobrien 364236769Sobrien/*- 365236769Sobrien *----------------------------------------------------------------------- 366236769Sobrien * Targ_FindList -- 367236769Sobrien * Make a complete list of GNodes from the given list of names 368236769Sobrien * 369236769Sobrien * Input: 370236769Sobrien * name list of names to find 371236769Sobrien * flags flags used if no node is found for a given name 372236769Sobrien * 373236769Sobrien * Results: 374236769Sobrien * A complete list of graph nodes corresponding to all instances of all 375236769Sobrien * the names in names. 376236769Sobrien * 377236769Sobrien * Side Effects: 378236769Sobrien * If flags is TARG_CREATE, nodes will be created for all names in 379236769Sobrien * names which do not yet have graph nodes. If flags is TARG_NOCREATE, 380236769Sobrien * an error message will be printed for each name which can't be found. 381236769Sobrien * ----------------------------------------------------------------------- 382236769Sobrien */ 383236769SobrienLst 384236769SobrienTarg_FindList(Lst names, int flags) 385236769Sobrien{ 386236769Sobrien Lst nodes; /* result list */ 387236769Sobrien LstNode ln; /* name list element */ 388236769Sobrien GNode *gn; /* node in tLn */ 389236769Sobrien char *name; 390236769Sobrien 391236769Sobrien nodes = Lst_Init(FALSE); 392236769Sobrien 393236769Sobrien if (Lst_Open(names) == FAILURE) { 394236769Sobrien return (nodes); 395236769Sobrien } 396236769Sobrien while ((ln = Lst_Next(names)) != NULL) { 397236769Sobrien name = (char *)Lst_Datum(ln); 398236769Sobrien gn = Targ_FindNode(name, flags); 399236769Sobrien if (gn != NULL) { 400236769Sobrien /* 401236769Sobrien * Note: Lst_AtEnd must come before the Lst_Concat so the nodes 402236769Sobrien * are added to the list in the order in which they were 403236769Sobrien * encountered in the makefile. 404236769Sobrien */ 405236769Sobrien (void)Lst_AtEnd(nodes, gn); 406236769Sobrien } else if (flags == TARG_NOCREATE) { 407236769Sobrien Error("\"%s\" -- target unknown.", name); 408236769Sobrien } 409236769Sobrien } 410236769Sobrien Lst_Close(names); 411236769Sobrien return (nodes); 412236769Sobrien} 413236769Sobrien 414236769Sobrien/*- 415236769Sobrien *----------------------------------------------------------------------- 416236769Sobrien * Targ_Ignore -- 417236769Sobrien * Return true if should ignore errors when creating gn 418236769Sobrien * 419236769Sobrien * Input: 420236769Sobrien * gn node to check for 421236769Sobrien * 422236769Sobrien * Results: 423236769Sobrien * TRUE if should ignore errors 424236769Sobrien * 425236769Sobrien * Side Effects: 426236769Sobrien * None 427236769Sobrien *----------------------------------------------------------------------- 428236769Sobrien */ 429236769SobrienBoolean 430236769SobrienTarg_Ignore(GNode *gn) 431236769Sobrien{ 432236769Sobrien if (ignoreErrors || gn->type & OP_IGNORE) { 433236769Sobrien return (TRUE); 434236769Sobrien } else { 435236769Sobrien return (FALSE); 436236769Sobrien } 437236769Sobrien} 438236769Sobrien 439236769Sobrien/*- 440236769Sobrien *----------------------------------------------------------------------- 441236769Sobrien * Targ_Silent -- 442236769Sobrien * Return true if be silent when creating gn 443236769Sobrien * 444236769Sobrien * Input: 445236769Sobrien * gn node to check for 446236769Sobrien * 447236769Sobrien * Results: 448236769Sobrien * TRUE if should be silent 449236769Sobrien * 450236769Sobrien * Side Effects: 451236769Sobrien * None 452236769Sobrien *----------------------------------------------------------------------- 453236769Sobrien */ 454236769SobrienBoolean 455236769SobrienTarg_Silent(GNode *gn) 456236769Sobrien{ 457236769Sobrien if (beSilent || gn->type & OP_SILENT) { 458236769Sobrien return (TRUE); 459236769Sobrien } else { 460236769Sobrien return (FALSE); 461236769Sobrien } 462236769Sobrien} 463236769Sobrien 464236769Sobrien/*- 465236769Sobrien *----------------------------------------------------------------------- 466236769Sobrien * Targ_Precious -- 467236769Sobrien * See if the given target is precious 468236769Sobrien * 469236769Sobrien * Input: 470236769Sobrien * gn the node to check 471236769Sobrien * 472236769Sobrien * Results: 473236769Sobrien * TRUE if it is precious. FALSE otherwise 474236769Sobrien * 475236769Sobrien * Side Effects: 476236769Sobrien * None 477236769Sobrien *----------------------------------------------------------------------- 478236769Sobrien */ 479236769SobrienBoolean 480236769SobrienTarg_Precious(GNode *gn) 481236769Sobrien{ 482236769Sobrien if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP))) { 483236769Sobrien return (TRUE); 484236769Sobrien } else { 485236769Sobrien return (FALSE); 486236769Sobrien } 487236769Sobrien} 488236769Sobrien 489236769Sobrien/******************* DEBUG INFO PRINTING ****************/ 490236769Sobrien 491236769Sobrienstatic GNode *mainTarg; /* the main target, as set by Targ_SetMain */ 492236769Sobrien/*- 493236769Sobrien *----------------------------------------------------------------------- 494236769Sobrien * Targ_SetMain -- 495236769Sobrien * Set our idea of the main target we'll be creating. Used for 496236769Sobrien * debugging output. 497236769Sobrien * 498236769Sobrien * Input: 499236769Sobrien * gn The main target we'll create 500236769Sobrien * 501236769Sobrien * Results: 502236769Sobrien * None. 503236769Sobrien * 504236769Sobrien * Side Effects: 505236769Sobrien * "mainTarg" is set to the main target's node. 506236769Sobrien *----------------------------------------------------------------------- 507236769Sobrien */ 508236769Sobrienvoid 509236769SobrienTarg_SetMain(GNode *gn) 510236769Sobrien{ 511236769Sobrien mainTarg = gn; 512236769Sobrien} 513236769Sobrien 514236769Sobrienstatic int 515237578SobrienTargPrintName(void *gnp, void *pflags MAKE_ATTR_UNUSED) 516236769Sobrien{ 517236769Sobrien GNode *gn = (GNode *)gnp; 518236769Sobrien 519236769Sobrien fprintf(debug_file, "%s%s ", gn->name, gn->cohort_num); 520236769Sobrien 521236769Sobrien return 0; 522236769Sobrien} 523236769Sobrien 524236769Sobrien 525236769Sobrienint 526236769SobrienTarg_PrintCmd(void *cmd, void *dummy) 527236769Sobrien{ 528236769Sobrien fprintf(debug_file, "\t%s\n", (char *)cmd); 529236769Sobrien return (dummy ? 0 : 0); 530236769Sobrien} 531236769Sobrien 532236769Sobrien/*- 533236769Sobrien *----------------------------------------------------------------------- 534236769Sobrien * Targ_FmtTime -- 535236769Sobrien * Format a modification time in some reasonable way and return it. 536236769Sobrien * 537236769Sobrien * Results: 538236769Sobrien * The time reformatted. 539236769Sobrien * 540236769Sobrien * Side Effects: 541236769Sobrien * The time is placed in a static area, so it is overwritten 542236769Sobrien * with each call. 543236769Sobrien * 544236769Sobrien *----------------------------------------------------------------------- 545236769Sobrien */ 546236769Sobrienchar * 547236769SobrienTarg_FmtTime(time_t tm) 548236769Sobrien{ 549236769Sobrien struct tm *parts; 550236769Sobrien static char buf[128]; 551236769Sobrien 552236769Sobrien parts = localtime(&tm); 553236769Sobrien (void)strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts); 554236769Sobrien return(buf); 555236769Sobrien} 556236769Sobrien 557236769Sobrien/*- 558236769Sobrien *----------------------------------------------------------------------- 559236769Sobrien * Targ_PrintType -- 560236769Sobrien * Print out a type field giving only those attributes the user can 561236769Sobrien * set. 562236769Sobrien * 563236769Sobrien * Results: 564236769Sobrien * 565236769Sobrien * Side Effects: 566236769Sobrien * 567236769Sobrien *----------------------------------------------------------------------- 568236769Sobrien */ 569236769Sobrienvoid 570236769SobrienTarg_PrintType(int type) 571236769Sobrien{ 572236769Sobrien int tbit; 573236769Sobrien 574236769Sobrien#define PRINTBIT(attr) case CONCAT(OP_,attr): fprintf(debug_file, "." #attr " "); break 575236769Sobrien#define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG))fprintf(debug_file, "." #attr " "); break 576236769Sobrien 577236769Sobrien type &= ~OP_OPMASK; 578236769Sobrien 579236769Sobrien while (type) { 580236769Sobrien tbit = 1 << (ffs(type) - 1); 581236769Sobrien type &= ~tbit; 582236769Sobrien 583236769Sobrien switch(tbit) { 584236769Sobrien PRINTBIT(OPTIONAL); 585236769Sobrien PRINTBIT(USE); 586236769Sobrien PRINTBIT(EXEC); 587236769Sobrien PRINTBIT(IGNORE); 588236769Sobrien PRINTBIT(PRECIOUS); 589236769Sobrien PRINTBIT(SILENT); 590236769Sobrien PRINTBIT(MAKE); 591236769Sobrien PRINTBIT(JOIN); 592236769Sobrien PRINTBIT(INVISIBLE); 593236769Sobrien PRINTBIT(NOTMAIN); 594236769Sobrien PRINTDBIT(LIB); 595236769Sobrien /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */ 596236769Sobrien case OP_MEMBER: if (DEBUG(TARG))fprintf(debug_file, ".MEMBER "); break; 597236769Sobrien PRINTDBIT(ARCHV); 598236769Sobrien PRINTDBIT(MADE); 599236769Sobrien PRINTDBIT(PHONY); 600236769Sobrien } 601236769Sobrien } 602236769Sobrien} 603236769Sobrien 604236769Sobrienstatic const char * 605236769Sobrienmade_name(enum enum_made made) 606236769Sobrien{ 607236769Sobrien switch (made) { 608236769Sobrien case UNMADE: return "unmade"; 609236769Sobrien case DEFERRED: return "deferred"; 610236769Sobrien case REQUESTED: return "requested"; 611236769Sobrien case BEINGMADE: return "being made"; 612236769Sobrien case MADE: return "made"; 613236769Sobrien case UPTODATE: return "up-to-date"; 614236769Sobrien case ERROR: return "error when made"; 615236769Sobrien case ABORTED: return "aborted"; 616236769Sobrien default: return "unknown enum_made value"; 617236769Sobrien } 618236769Sobrien} 619236769Sobrien 620236769Sobrien/*- 621236769Sobrien *----------------------------------------------------------------------- 622236769Sobrien * TargPrintNode -- 623236769Sobrien * print the contents of a node 624236769Sobrien *----------------------------------------------------------------------- 625236769Sobrien */ 626236769Sobrienint 627236769SobrienTarg_PrintNode(void *gnp, void *passp) 628236769Sobrien{ 629236769Sobrien GNode *gn = (GNode *)gnp; 630236769Sobrien int pass = passp ? *(int *)passp : 0; 631236769Sobrien 632236769Sobrien fprintf(debug_file, "# %s%s, flags %x, type %x, made %d\n", 633236769Sobrien gn->name, gn->cohort_num, gn->flags, gn->type, gn->made); 634236769Sobrien if (gn->flags == 0) 635236769Sobrien return 0; 636236769Sobrien 637236769Sobrien if (!OP_NOP(gn->type)) { 638236769Sobrien fprintf(debug_file, "#\n"); 639236769Sobrien if (gn == mainTarg) { 640236769Sobrien fprintf(debug_file, "# *** MAIN TARGET ***\n"); 641236769Sobrien } 642236769Sobrien if (pass >= 2) { 643236769Sobrien if (gn->unmade) { 644236769Sobrien fprintf(debug_file, "# %d unmade children\n", gn->unmade); 645236769Sobrien } else { 646236769Sobrien fprintf(debug_file, "# No unmade children\n"); 647236769Sobrien } 648236769Sobrien if (! (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC))) { 649236769Sobrien if (gn->mtime != 0) { 650236769Sobrien fprintf(debug_file, "# last modified %s: %s\n", 651236769Sobrien Targ_FmtTime(gn->mtime), 652236769Sobrien made_name(gn->made)); 653236769Sobrien } else if (gn->made != UNMADE) { 654236769Sobrien fprintf(debug_file, "# non-existent (maybe): %s\n", 655236769Sobrien made_name(gn->made)); 656236769Sobrien } else { 657236769Sobrien fprintf(debug_file, "# unmade\n"); 658236769Sobrien } 659236769Sobrien } 660236769Sobrien if (!Lst_IsEmpty (gn->iParents)) { 661236769Sobrien fprintf(debug_file, "# implicit parents: "); 662236769Sobrien Lst_ForEach(gn->iParents, TargPrintName, NULL); 663236769Sobrien fprintf(debug_file, "\n"); 664236769Sobrien } 665236769Sobrien } else { 666236769Sobrien if (gn->unmade) 667236769Sobrien fprintf(debug_file, "# %d unmade children\n", gn->unmade); 668236769Sobrien } 669236769Sobrien if (!Lst_IsEmpty (gn->parents)) { 670236769Sobrien fprintf(debug_file, "# parents: "); 671236769Sobrien Lst_ForEach(gn->parents, TargPrintName, NULL); 672236769Sobrien fprintf(debug_file, "\n"); 673236769Sobrien } 674236769Sobrien if (!Lst_IsEmpty (gn->order_pred)) { 675236769Sobrien fprintf(debug_file, "# order_pred: "); 676236769Sobrien Lst_ForEach(gn->order_pred, TargPrintName, NULL); 677236769Sobrien fprintf(debug_file, "\n"); 678236769Sobrien } 679236769Sobrien if (!Lst_IsEmpty (gn->order_succ)) { 680236769Sobrien fprintf(debug_file, "# order_succ: "); 681236769Sobrien Lst_ForEach(gn->order_succ, TargPrintName, NULL); 682236769Sobrien fprintf(debug_file, "\n"); 683236769Sobrien } 684236769Sobrien 685236769Sobrien fprintf(debug_file, "%-16s", gn->name); 686236769Sobrien switch (gn->type & OP_OPMASK) { 687236769Sobrien case OP_DEPENDS: 688236769Sobrien fprintf(debug_file, ": "); break; 689236769Sobrien case OP_FORCE: 690236769Sobrien fprintf(debug_file, "! "); break; 691236769Sobrien case OP_DOUBLEDEP: 692236769Sobrien fprintf(debug_file, ":: "); break; 693236769Sobrien } 694236769Sobrien Targ_PrintType(gn->type); 695236769Sobrien Lst_ForEach(gn->children, TargPrintName, NULL); 696236769Sobrien fprintf(debug_file, "\n"); 697236769Sobrien Lst_ForEach(gn->commands, Targ_PrintCmd, NULL); 698236769Sobrien fprintf(debug_file, "\n\n"); 699236769Sobrien if (gn->type & OP_DOUBLEDEP) { 700236769Sobrien Lst_ForEach(gn->cohorts, Targ_PrintNode, &pass); 701236769Sobrien } 702236769Sobrien } 703236769Sobrien return (0); 704236769Sobrien} 705236769Sobrien 706236769Sobrien/*- 707236769Sobrien *----------------------------------------------------------------------- 708236769Sobrien * TargPrintOnlySrc -- 709236769Sobrien * Print only those targets that are just a source. 710236769Sobrien * 711236769Sobrien * Results: 712236769Sobrien * 0. 713236769Sobrien * 714236769Sobrien * Side Effects: 715236769Sobrien * The name of each file is printed preceded by #\t 716236769Sobrien * 717236769Sobrien *----------------------------------------------------------------------- 718236769Sobrien */ 719236769Sobrienstatic int 720237578SobrienTargPrintOnlySrc(void *gnp, void *dummy MAKE_ATTR_UNUSED) 721236769Sobrien{ 722236769Sobrien GNode *gn = (GNode *)gnp; 723236769Sobrien if (!OP_NOP(gn->type)) 724236769Sobrien return 0; 725236769Sobrien 726236769Sobrien fprintf(debug_file, "#\t%s [%s] ", 727236769Sobrien gn->name, gn->path ? gn->path : gn->name); 728236769Sobrien Targ_PrintType(gn->type); 729236769Sobrien fprintf(debug_file, "\n"); 730236769Sobrien 731236769Sobrien return 0; 732236769Sobrien} 733236769Sobrien 734236769Sobrien/*- 735236769Sobrien *----------------------------------------------------------------------- 736236769Sobrien * Targ_PrintGraph -- 737236769Sobrien * print the entire graph. heh heh 738236769Sobrien * 739236769Sobrien * Input: 740236769Sobrien * pass Which pass this is. 1 => no processing 741236769Sobrien * 2 => processing done 742236769Sobrien * 743236769Sobrien * Results: 744236769Sobrien * none 745236769Sobrien * 746236769Sobrien * Side Effects: 747236769Sobrien * lots o' output 748236769Sobrien *----------------------------------------------------------------------- 749236769Sobrien */ 750236769Sobrienvoid 751236769SobrienTarg_PrintGraph(int pass) 752236769Sobrien{ 753236769Sobrien fprintf(debug_file, "#*** Input graph:\n"); 754236769Sobrien Lst_ForEach(allTargets, Targ_PrintNode, &pass); 755236769Sobrien fprintf(debug_file, "\n\n"); 756236769Sobrien fprintf(debug_file, "#\n# Files that are only sources:\n"); 757236769Sobrien Lst_ForEach(allTargets, TargPrintOnlySrc, NULL); 758236769Sobrien fprintf(debug_file, "#*** Global Variables:\n"); 759236769Sobrien Var_Dump(VAR_GLOBAL); 760236769Sobrien fprintf(debug_file, "#*** Command-line Variables:\n"); 761236769Sobrien Var_Dump(VAR_CMD); 762236769Sobrien fprintf(debug_file, "\n"); 763236769Sobrien Dir_PrintDirectories(); 764236769Sobrien fprintf(debug_file, "\n"); 765236769Sobrien Suff_PrintAll(); 766236769Sobrien} 767236769Sobrien 768236769Sobrien/*- 769236769Sobrien *----------------------------------------------------------------------- 770236769Sobrien * TargPropagateNode -- 771236769Sobrien * Propagate information from a single node to related nodes if 772236769Sobrien * appropriate. 773236769Sobrien * 774236769Sobrien * Input: 775236769Sobrien * gnp The node that we are processing. 776236769Sobrien * 777236769Sobrien * Results: 778236769Sobrien * Always returns 0, for the benefit of Lst_ForEach(). 779236769Sobrien * 780236769Sobrien * Side Effects: 781236769Sobrien * Information is propagated from this node to cohort or child 782236769Sobrien * nodes. 783236769Sobrien * 784236769Sobrien * If the node was defined with "::", then TargPropagateCohort() 785236769Sobrien * will be called for each cohort node. 786236769Sobrien * 787236769Sobrien * If the node has recursive predecessors, then 788236769Sobrien * TargPropagateRecpred() will be called for each recursive 789236769Sobrien * predecessor. 790236769Sobrien *----------------------------------------------------------------------- 791236769Sobrien */ 792236769Sobrienstatic int 793237578SobrienTargPropagateNode(void *gnp, void *junk MAKE_ATTR_UNUSED) 794236769Sobrien{ 795236769Sobrien GNode *gn = (GNode *)gnp; 796236769Sobrien 797236769Sobrien if (gn->type & OP_DOUBLEDEP) 798236769Sobrien Lst_ForEach(gn->cohorts, TargPropagateCohort, gnp); 799236769Sobrien return (0); 800236769Sobrien} 801236769Sobrien 802236769Sobrien/*- 803236769Sobrien *----------------------------------------------------------------------- 804236769Sobrien * TargPropagateCohort -- 805236769Sobrien * Propagate some bits in the type mask from a node to 806236769Sobrien * a related cohort node. 807236769Sobrien * 808236769Sobrien * Input: 809236769Sobrien * cnp The node that we are processing. 810236769Sobrien * gnp Another node that has cnp as a cohort. 811236769Sobrien * 812236769Sobrien * Results: 813236769Sobrien * Always returns 0, for the benefit of Lst_ForEach(). 814236769Sobrien * 815236769Sobrien * Side Effects: 816236769Sobrien * cnp's type bitmask is modified to incorporate some of the 817236769Sobrien * bits from gnp's type bitmask. (XXX need a better explanation.) 818236769Sobrien *----------------------------------------------------------------------- 819236769Sobrien */ 820236769Sobrienstatic int 821236769SobrienTargPropagateCohort(void *cgnp, void *pgnp) 822236769Sobrien{ 823236769Sobrien GNode *cgn = (GNode *)cgnp; 824236769Sobrien GNode *pgn = (GNode *)pgnp; 825236769Sobrien 826236769Sobrien cgn->type |= pgn->type & ~OP_OPMASK; 827236769Sobrien return (0); 828236769Sobrien} 829236769Sobrien 830236769Sobrien/*- 831236769Sobrien *----------------------------------------------------------------------- 832236769Sobrien * Targ_Propagate -- 833236769Sobrien * Propagate information between related nodes. Should be called 834236769Sobrien * after the makefiles are parsed but before any action is taken. 835236769Sobrien * 836236769Sobrien * Results: 837236769Sobrien * none 838236769Sobrien * 839236769Sobrien * Side Effects: 840236769Sobrien * Information is propagated between related nodes throughout the 841236769Sobrien * graph. 842236769Sobrien *----------------------------------------------------------------------- 843236769Sobrien */ 844236769Sobrienvoid 845236769SobrienTarg_Propagate(void) 846236769Sobrien{ 847236769Sobrien Lst_ForEach(allTargets, TargPropagateNode, NULL); 848236769Sobrien} 849