version 1.26, 2000/09/14 13:32:08 |
version 1.27, 2000/09/14 13:40:03 |
|
|
|
|
/*- |
/*- |
* targ.c -- |
* targ.c -- |
* Functions for maintaining the Lst allTargets. Target nodes are |
* Target nodes are kept into a hash table. |
* kept in two structures: a Lst, maintained by the list library, and a |
|
* hash table, maintained by the hash library. |
|
* |
* |
* Interface: |
* Interface: |
* Targ_Init Initialization procedure. |
* Targ_Init Initialization procedure. |
|
|
* print something for suffixes, too, but... |
* print something for suffixes, too, but... |
*/ |
*/ |
|
|
|
#include <stddef.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <time.h> |
#include <time.h> |
#include "make.h" |
#include "make.h" |
#include "hash.h" |
#include "ohash.h" |
|
#include "hash.h" |
#include "dir.h" |
#include "dir.h" |
|
|
#ifndef lint |
#ifndef lint |
|
|
#endif |
#endif |
#endif /* not lint */ |
#endif /* not lint */ |
|
|
static LIST allTargets; /* the list of all targets found so far */ |
|
#ifdef CLEANUP |
#ifdef CLEANUP |
static LIST allGNs; /* List of all the GNodes */ |
static LIST allGNs; /* List of all the GNodes */ |
#endif |
#endif |
static Hash_Table targets; /* a hash table of same */ |
static struct hash targets; /* a hash table of same */ |
|
static struct hash_info gnode_info = { |
|
offsetof(GNode, name), |
|
NULL, hash_alloc, hash_free, element_alloc }; |
|
|
#define HTSIZE 191 /* initial size of hash table */ |
static void TargPrintOnlySrc __P((GNode *)); |
|
|
static void TargPrintOnlySrc __P((void *)); |
|
static void TargPrintName __P((void *)); |
static void TargPrintName __P((void *)); |
static void TargPrintNode __P((void *, void *)); |
static void TargPrintNode __P((GNode *, int)); |
#ifdef CLEANUP |
#ifdef CLEANUP |
static void TargFreeGN __P((void *)); |
static void TargFreeGN __P((void *)); |
#endif |
#endif |
|
|
* Initialize this module |
* Initialize this module |
* |
* |
* Side Effects: |
* Side Effects: |
* The allTargets list and the targets hash table are initialized |
* The targets hash table is initialized |
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
void |
void |
|
|
#ifdef CLEANUP |
#ifdef CLEANUP |
Lst_Init(&allGNs); |
Lst_Init(&allGNs); |
#endif |
#endif |
Lst_Init(&allTargets); |
/* A small make file already creates 200 targets. */ |
Hash_InitTable(&targets, HTSIZE); |
hash_init(&targets, 10, &gnode_info); |
} |
} |
|
|
/*- |
/*- |
|
|
* Targ_End -- |
* Targ_End -- |
* Finalize this module |
* Finalize this module |
* |
* |
* Results: |
|
* None |
|
* |
|
* Side Effects: |
* Side Effects: |
* All lists and gnodes are cleared |
* All lists and gnodes are cleared |
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
|
|
Targ_End () |
Targ_End () |
{ |
{ |
#ifdef CLEANUP |
#ifdef CLEANUP |
Lst_Destroy(&allTargets, NOFREE); |
|
Lst_Destroy(&allGNs, TargFreeGN); |
Lst_Destroy(&allGNs, TargFreeGN); |
Hash_DeleteTable(&targets); |
hash_delete(&targets); |
#endif |
#endif |
} |
} |
|
|
|
|
* of the passed name |
* of the passed name |
* |
* |
* Side Effects: |
* Side Effects: |
* The gnode is added to the list of all gnodes. |
* The gnode is added to the set of all gnodes. |
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
GNode * |
GNode * |
Targ_NewGN (name) |
Targ_NewGN(name, end) |
char *name; /* the name to stick in the new node */ |
const char *name; /* the name to stick in the new node */ |
|
const char *end; |
{ |
{ |
register GNode *gn; |
GNode *gn; |
|
|
gn = (GNode *) emalloc (sizeof (GNode)); |
gn = hash_create_entry(&gnode_info, name, &end); |
gn->name = estrdup (name); |
gn->path = NULL; |
gn->path = (char *) 0; |
|
if (name[0] == '-' && name[1] == 'l') { |
if (name[0] == '-' && name[1] == 'l') { |
gn->type = OP_LIB; |
gn->type = OP_LIB; |
} else { |
} else { |
|
|
Lst_AtEnd(&allGNs, gn); |
Lst_AtEnd(&allGNs, gn); |
#endif |
#endif |
|
|
return (gn); |
return gn; |
} |
} |
|
|
#ifdef CLEANUP |
#ifdef CLEANUP |
|
|
{ |
{ |
GNode *gn = (GNode *) gnp; |
GNode *gn = (GNode *) gnp; |
|
|
|
|
free(gn->name); |
|
efree(gn->path); |
efree(gn->path); |
Lst_Destroy(&gn->iParents, NOFREE); |
Lst_Destroy(&gn->iParents, NOFREE); |
Lst_Destroy(&gn->cohorts, NOFREE); |
Lst_Destroy(&gn->cohorts, NOFREE); |
|
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
GNode * |
GNode * |
Targ_FindNode (name, flags) |
Targ_FindNode(name, flags) |
char *name; /* the name to find */ |
const char *name; /* the name to find */ |
int flags; /* flags governing events when target not |
int flags; /* flags governing events when target not |
* found */ |
* found */ |
{ |
{ |
GNode *gn; /* node in that element */ |
const char *end = NULL; |
Hash_Entry *he; /* New or used hash entry for node */ |
GNode *gn; /* node in that element */ |
Boolean isNew; /* Set TRUE if Hash_CreateEntry had to create */ |
unsigned int slot; |
/* an entry for the node */ |
|
|
|
|
slot = hash_qlookupi(&targets, name, &end); |
|
|
if (flags & TARG_CREATE) { |
gn = hash_find(&targets, slot); |
he = Hash_CreateEntry (&targets, name, &isNew); |
|
if (isNew) { |
if (gn == NULL && (flags & TARG_CREATE)) { |
gn = Targ_NewGN (name); |
gn = Targ_NewGN(name, end); |
Hash_SetValue (he, gn); |
hash_insert(&targets, slot, gn); |
Lst_AtEnd(&allTargets, gn); |
|
} |
|
} else { |
|
he = Hash_FindEntry (&targets, name); |
|
} |
} |
|
|
if (he == NULL) { |
return gn; |
return (NULL); |
|
} else { |
|
return ((GNode *) Hash_GetValue (he)); |
|
} |
|
} |
} |
|
|
/*- |
/*- |
|
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
* Targ_Ignore -- |
* Targ_Ignore -- |
* Return true if should ignore errors when creating gn |
* Return true if should ignore errors when creating gn |
* |
|
* Results: |
|
* TRUE if should ignore errors |
|
* |
|
* Side Effects: |
|
* None |
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
Boolean |
Boolean |
Targ_Ignore (gn) |
Targ_Ignore(gn) |
GNode *gn; /* node to check for */ |
GNode *gn; /* node to check for */ |
{ |
{ |
if (ignoreErrors || gn->type & OP_IGNORE) { |
if (ignoreErrors || gn->type & OP_IGNORE) |
return (TRUE); |
return TRUE; |
} else { |
else |
return (FALSE); |
return FALSE; |
} |
|
} |
} |
|
|
/*- |
/*- |
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
* Targ_Silent -- |
* Targ_Silent -- |
* Return true if be silent when creating gn |
* Return true if be silent when creating gn |
* |
|
* Results: |
|
* TRUE if should be silent |
|
* |
|
* Side Effects: |
|
* None |
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
Boolean |
Boolean |
Targ_Silent (gn) |
Targ_Silent(gn) |
GNode *gn; /* node to check for */ |
GNode *gn; /* node to check for */ |
{ |
{ |
if (beSilent || gn->type & OP_SILENT) { |
if (beSilent || gn->type & OP_SILENT) |
return (TRUE); |
return TRUE; |
} else { |
else |
return (FALSE); |
return FALSE; |
} |
|
} |
} |
|
|
/*- |
/*- |
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
* Targ_Precious -- |
* Targ_Precious -- |
* See if the given target is precious |
* See if the given target is precious |
* |
|
* Results: |
|
* TRUE if it is precious. FALSE otherwise |
|
* |
|
* Side Effects: |
|
* None |
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
Boolean |
Boolean |
Targ_Precious (gn) |
Targ_Precious (gn) |
GNode *gn; /* the node to check */ |
GNode *gn; /* the node to check */ |
{ |
{ |
if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP))) { |
if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP))) |
return (TRUE); |
return TRUE; |
} else { |
else |
return (FALSE); |
return FALSE; |
} |
|
} |
} |
|
|
/******************* DEBUG INFO PRINTING ****************/ |
/******************* DEBUG INFO PRINTING ****************/ |
|
|
* Set our idea of the main target we'll be creating. Used for |
* Set our idea of the main target we'll be creating. Used for |
* debugging output. |
* debugging output. |
* |
* |
* Results: |
|
* None. |
|
* |
|
* Side Effects: |
* Side Effects: |
* "mainTarg" is set to the main target's node. |
* "mainTarg" is set to the main target's node. |
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
void |
void |
Targ_SetMain (gn) |
Targ_SetMain(gn) |
GNode *gn; /* The main target we'll create */ |
GNode *gn; /* The main target we'll create */ |
{ |
{ |
mainTarg = gn; |
mainTarg = gn; |
|
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
char * |
char * |
Targ_FmtTime (time) |
Targ_FmtTime(time) |
time_t time; |
time_t time; |
{ |
{ |
struct tm *parts; |
struct tm *parts; |
static char buf[128]; |
static char buf[128]; |
|
|
parts = localtime(&time); |
parts = localtime(&time); |
strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts); |
strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts); |
|
|
* Targ_PrintType -- |
* Targ_PrintType -- |
* Print out a type field giving only those attributes the user can |
* Print out a type field giving only those attributes the user can |
* set. |
* set. |
* |
|
* Results: |
|
* |
|
* Side Effects: |
|
* |
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
void |
void |
Targ_PrintType (type) |
Targ_PrintType(type) |
register int type; |
int type; |
{ |
{ |
register int tbit; |
int tbit; |
|
|
#ifdef __STDC__ |
#ifdef __STDC__ |
#define PRINTBIT(attr) case CONCAT(OP_,attr): printf("." #attr " "); break |
#define PRINTBIT(attr) case CONCAT(OP_,attr): printf("." #attr " "); break |
|
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
static void |
static void |
TargPrintNode(gnp, passp) |
TargPrintNode(gn, pass) |
void *gnp; |
GNode *gn; |
void *passp; |
int pass; |
{ |
{ |
GNode *gn = (GNode *)gnp; |
|
int pass = *(int *)passp; |
|
if (!OP_NOP(gn->type)) { |
if (!OP_NOP(gn->type)) { |
printf("#\n"); |
printf("#\n"); |
if (gn == mainTarg) |
if (gn == mainTarg) |
|
|
fputc('\n', stdout); |
fputc('\n', stdout); |
Lst_Every(&gn->commands, Targ_PrintCmd); |
Lst_Every(&gn->commands, Targ_PrintCmd); |
printf("\n\n"); |
printf("\n\n"); |
if (gn->type & OP_DOUBLEDEP) |
if (gn->type & OP_DOUBLEDEP) { |
Lst_ForEach(&gn->cohorts, TargPrintNode, &pass); |
LstNode ln; |
|
|
|
for (ln = Lst_First(&gn->cohorts); ln != NULL; ln = Lst_Adv(ln)) |
|
TargPrintNode((GNode *)Lst_Datum(ln), pass); |
|
} |
} |
} |
} |
} |
|
|
|
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
* TargPrintOnlySrc -- |
* TargPrintOnlySrc -- |
* Print only those targets that are just a source. |
* Print only those targets that are just a source. |
* |
|
* Side Effects: |
|
* The name of each file is printed preceeded by #\t |
|
* |
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
static void |
static void |
TargPrintOnlySrc(gnp) |
TargPrintOnlySrc(gn) |
void *gnp; |
GNode *gn; |
{ |
{ |
GNode *gn = (GNode *)gnp; |
|
|
|
if (OP_NOP(gn->type)) |
if (OP_NOP(gn->type)) |
printf("#\t%s [%s]\n", gn->name, gn->path ? gn->path : gn->name); |
printf("#\t%s [%s]\n", gn->name, gn->path ? gn->path : gn->name); |
} |
} |
|
|
/*- |
/*- |
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
* Targ_PrintGraph -- |
* Targ_PrintGraph -- |
* print the entire graph. heh heh |
* print the entire graph. |
* |
|
* Results: |
|
* none |
|
* |
|
* Side Effects: |
|
* lots o' output |
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
void |
void |
Targ_PrintGraph (pass) |
Targ_PrintGraph(pass) |
int pass; /* Which pass this is. 1 => no processing |
int pass; /* Which pass this is. 1 => no processing |
* 2 => processing done */ |
* 2 => processing done */ |
{ |
{ |
|
GNode *gn; |
|
unsigned int i; |
|
|
printf("#*** Input graph:\n"); |
printf("#*** Input graph:\n"); |
Lst_ForEach(&allTargets, TargPrintNode, &pass); |
for (gn = hash_first(&targets, &i); gn != NULL; |
|
gn = hash_next(&targets, &i)) |
|
TargPrintNode(gn, pass); |
printf("\n\n"); |
printf("\n\n"); |
printf("#\n# Files that are only sources:\n"); |
printf("#\n# Files that are only sources:\n"); |
Lst_Every(&allTargets, TargPrintOnlySrc); |
for (gn = hash_first(&targets, &i); gn != NULL; |
|
gn = hash_next(&targets, &i)) |
|
TargPrintOnlySrc(gn); |
printf("#*** Global Variables:\n"); |
printf("#*** Global Variables:\n"); |
Var_Dump(VAR_GLOBAL); |
Var_Dump(VAR_GLOBAL); |
printf("#*** Command-line Variables:\n"); |
printf("#*** Command-line Variables:\n"); |