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