version 1.42, 2000/06/10 01:41:06 |
version 1.43, 2000/06/17 14:38:18 |
|
|
#include "pathnames.h" |
#include "pathnames.h" |
|
|
#ifdef CLEANUP |
#ifdef CLEANUP |
static Lst fileNames; /* file names to free at end */ |
static LIST fileNames; /* file names to free at end */ |
#endif |
#endif |
|
|
/* |
/* |
|
|
#define DONE 0 |
#define DONE 0 |
static Lst targets; /* targets we're working on */ |
static Lst targets; /* targets we're working on */ |
#ifdef CLEANUP |
#ifdef CLEANUP |
static Lst targCmds; /* command lines for targets */ |
static LIST targCmds; /* command lines for targets */ |
#endif |
#endif |
static Boolean inLine; /* true if currently in a dependency |
static Boolean inLine; /* true if currently in a dependency |
* line or its commands */ |
* line or its commands */ |
|
|
PTR *p; /* the char pointer */ |
PTR *p; /* the char pointer */ |
} IFile; |
} IFile; |
|
|
static Lst includes; /* stack of IFiles generated by |
static LIST includes; /* stack of IFiles generated by |
* #includes */ |
* #includes */ |
Lst parseIncPath; /* list of directories for "..." includes */ |
LIST parseIncPath; /* list of directories for "..." includes */ |
Lst sysIncPath; /* list of directories for <...> includes */ |
LIST sysIncPath; /* list of directories for <...> includes */ |
|
|
/*- |
/*- |
* specType contains the SPECial TYPE of the current target. It is |
* specType contains the SPECial TYPE of the current target. It is |
|
|
{ |
{ |
GNode *pgn = (GNode *)pgnp; |
GNode *pgn = (GNode *)pgnp; |
GNode *cgn = (GNode *)cgnp; |
GNode *cgn = (GNode *)cgnp; |
if (Lst_Member(pgn->children, cgn) == NULL) { |
if (Lst_Member(&pgn->children, cgn) == NULL) { |
Lst_AtEnd(pgn->children, cgn); |
Lst_AtEnd(&pgn->children, cgn); |
if (specType == Not) |
if (specType == Not) |
Lst_AtEnd(cgn->parents, pgn); |
Lst_AtEnd(&cgn->parents, pgn); |
pgn->unmade += 1; |
pgn->unmade += 1; |
} |
} |
} |
} |
|
|
* anything with their local variables, but better safe than |
* anything with their local variables, but better safe than |
* sorry. |
* sorry. |
*/ |
*/ |
Lst_ForEach(gn->parents, ParseLinkSrc, cohort); |
Lst_ForEach(&gn->parents, ParseLinkSrc, cohort); |
cohort->type = OP_DOUBLEDEP|OP_INVISIBLE; |
cohort->type = OP_DOUBLEDEP|OP_INVISIBLE; |
Lst_AtEnd(gn->cohorts, cohort); |
Lst_AtEnd(&gn->cohorts, cohort); |
|
|
/* |
/* |
* Replace the node in the targets list with the new copy |
* Replace the node in the targets list with the new copy |
|
|
* but checking is tedious, and the debugging output can show the |
* but checking is tedious, and the debugging output can show the |
* problem |
* problem |
*/ |
*/ |
Lst_AtEnd(p->successors, s); |
Lst_AtEnd(&p->successors, s); |
Lst_AtEnd(s->preds, p); |
Lst_AtEnd(&s->preds, p); |
return 1; |
return 1; |
} |
} |
else |
else |
|
|
* invoked if the user didn't specify a target on the command |
* invoked if the user didn't specify a target on the command |
* line. This is to allow #ifmake's to succeed, or something... |
* line. This is to allow #ifmake's to succeed, or something... |
*/ |
*/ |
Lst_AtEnd(create, estrdup(src)); |
Lst_AtEnd(&create, estrdup(src)); |
/* |
/* |
* Add the name to the .TARGETS variable as well, so the user cna |
* Add the name to the .TARGETS variable as well, so the user cna |
* employ that, if desired. |
* employ that, if desired. |
|
|
*/ |
*/ |
gn = Targ_FindNode(src, TARG_CREATE); |
gn = Targ_FindNode(src, TARG_CREATE); |
if (predecessor != NULL) { |
if (predecessor != NULL) { |
Lst_AtEnd(predecessor->successors, gn); |
Lst_AtEnd(&predecessor->successors, gn); |
Lst_AtEnd(gn->preds, predecessor); |
Lst_AtEnd(&gn->preds, predecessor); |
} |
} |
/* |
/* |
* The current source now becomes the predecessor for the next one. |
* The current source now becomes the predecessor for the next one. |
|
|
register GNode *cohort; |
register GNode *cohort; |
register LstNode ln; |
register LstNode ln; |
|
|
for (ln=Lst_First(gn->cohorts); ln != NULL; ln = Lst_Succ(ln)){ |
for (ln=Lst_First(&gn->cohorts); ln != NULL; ln = Lst_Succ(ln)){ |
cohort = (GNode *)Lst_Datum(ln); |
cohort = (GNode *)Lst_Datum(ln); |
if (tOp) { |
if (tOp) { |
cohort->type |= tOp; |
cohort->type |= tOp; |
|
|
Lst paths; /* List of search paths to alter when parsing |
Lst paths; /* List of search paths to alter when parsing |
* a list of .PATH targets */ |
* a list of .PATH targets */ |
int tOp; /* operator from special target */ |
int tOp; /* operator from special target */ |
Lst sources; /* list of archive source names after |
LIST curTargs; /* list of target names to be found and added |
* expansion */ |
|
Lst curTargs; /* list of target names to be found and added |
|
* to the targets list */ |
* to the targets list */ |
Lst curSrcs; /* list of sources in order */ |
LIST curSrcs; /* list of sources in order */ |
|
|
tOp = 0; |
tOp = 0; |
|
|
|
|
waiting = 0; |
waiting = 0; |
paths = (Lst)NULL; |
paths = (Lst)NULL; |
|
|
curTargs = Lst_Init(); |
Lst_Init(&curTargs); |
curSrcs = Lst_Init(); |
Lst_Init(&curSrcs); |
|
|
do { |
do { |
for (cp = line; |
for (cp = line; |
|
|
*/ |
*/ |
switch (specType) { |
switch (specType) { |
case ExPath: |
case ExPath: |
if (paths == NULL) { |
if (paths == NULL) |
paths = Lst_Init(); |
paths = Lst_New(); |
} |
Lst_AtEnd(paths, &dirSearchPath); |
Lst_AtEnd(paths, dirSearchPath); |
|
break; |
break; |
case Main: |
case Main: |
if (!Lst_IsEmpty(create)) { |
if (!Lst_IsEmpty(&create)) { |
specType = Not; |
specType = Not; |
} |
} |
break; |
break; |
|
|
&line[5]); |
&line[5]); |
return; |
return; |
} else { |
} else { |
if (paths == NULL) { |
if (paths == NULL) |
paths = Lst_Init(); |
paths = Lst_New(); |
} |
|
Lst_AtEnd(paths, path); |
Lst_AtEnd(paths, path); |
} |
} |
} |
} |
|
|
* use Dir_Destroy in the destruction of the path as the |
* use Dir_Destroy in the destruction of the path as the |
* Dir module could have added a directory to the path... |
* Dir module could have added a directory to the path... |
*/ |
*/ |
Lst emptyPath = Lst_Init(); |
LIST emptyPath; |
|
|
|
Lst_Init(&emptyPath); |
|
|
Dir_Expand(line, emptyPath, curTargs); |
Dir_Expand(line, &emptyPath, &curTargs); |
|
|
Lst_Destroy(emptyPath, Dir_Destroy); |
Lst_Destroy(&emptyPath, Dir_Destroy); |
} else { |
} else { |
/* |
/* |
* No wildcards, but we want to avoid code duplication, |
* No wildcards, but we want to avoid code duplication, |
* so create a list with the word on it. |
* so create a list with the word on it. |
*/ |
*/ |
Lst_AtEnd(curTargs, line); |
Lst_AtEnd(&curTargs, line); |
} |
} |
|
|
while((targName = (char *)Lst_DeQueue(curTargs)) != NULL) { |
while((targName = (char *)Lst_DeQueue(&curTargs)) != NULL) { |
if (!Suff_IsTransform (targName)) { |
if (!Suff_IsTransform (targName)) { |
gn = Targ_FindNode (targName, TARG_CREATE); |
gn = Targ_FindNode (targName, TARG_CREATE); |
} else { |
} else { |
|
|
line = cp; |
line = cp; |
} while ((*line != '!') && (*line != ':') && *line); |
} while ((*line != '!') && (*line != ':') && *line); |
|
|
/* |
/* Don't need the list of target names any more */ |
* Don't need the list of target names anymore... |
Lst_Destroy(&curTargs, NOFREE); |
*/ |
|
Lst_Destroy(curTargs, NOFREE); |
|
|
|
if (!Lst_IsEmpty(targets)) { |
if (!Lst_IsEmpty(targets)) { |
switch(specType) { |
switch(specType) { |
|
|
} |
} |
line = cp; |
line = cp; |
} |
} |
if (paths) { |
if (paths) |
Lst_Destroy(paths, NOFREE); |
Lst_Delete(paths, NOFREE); |
} |
|
} else { |
} else { |
while (*line) { |
while (*line) { |
/* |
/* |
|
|
|
|
if (*cp == '(') { |
if (*cp == '(') { |
GNode *gn; |
GNode *gn; |
|
LIST sources; /* list of archive source names after |
|
* expansion */ |
|
|
sources = Lst_Init(); |
Lst_Init(&sources); |
if (Arch_ParseArchive (&line, sources, VAR_CMD) != SUCCESS) { |
if (Arch_ParseArchive(&line, &sources, VAR_CMD) != SUCCESS) { |
Parse_Error (PARSE_FATAL, |
Parse_Error (PARSE_FATAL, |
"Error in source archive spec \"%s\"", line); |
"Error in source archive spec \"%s\"", line); |
return; |
return; |
} |
} |
|
|
while ((gn = (GNode *)Lst_DeQueue(sources)) != NULL) |
while ((gn = (GNode *)Lst_DeQueue(&sources)) != NULL) |
ParseDoSrc(tOp, gn->name, curSrcs); |
ParseDoSrc(tOp, gn->name, &curSrcs); |
Lst_Destroy(sources, NOFREE); |
Lst_Destroy(&sources, NOFREE); |
cp = line; |
cp = line; |
} else { |
} else { |
if (*cp) { |
if (*cp) { |
|
|
cp += 1; |
cp += 1; |
} |
} |
|
|
ParseDoSrc (tOp, line, curSrcs); |
ParseDoSrc(tOp, line, &curSrcs); |
} |
} |
while (*cp && isspace (*cp)) { |
while (*cp && isspace (*cp)) { |
cp++; |
cp++; |
|
|
Lst_Find(targets, ParseFindMain, NULL); |
Lst_Find(targets, ParseFindMain, NULL); |
} |
} |
|
|
/* |
/* Finally, destroy the list of sources. */ |
* Finally, destroy the list of sources |
Lst_Destroy(&curSrcs, NOFREE); |
*/ |
|
Lst_Destroy(curSrcs, NOFREE); |
|
} |
} |
|
|
/*- |
/*- |
|
|
GNode *gn = (GNode *)gnp; |
GNode *gn = (GNode *)gnp; |
/* if target already supplied, ignore commands */ |
/* if target already supplied, ignore commands */ |
if (!(gn->type & OP_HAS_COMMANDS)) { |
if (!(gn->type & OP_HAS_COMMANDS)) { |
Lst_AtEnd(gn->commands, cmd); |
Lst_AtEnd(&gn->commands, cmd); |
if (!gn->lineno) { |
if (!gn->lineno) { |
gn->lineno = Parse_Getlineno(); |
gn->lineno = Parse_Getlineno(); |
gn->fname = Parse_Getfilename(); |
gn->fname = Parse_Getfilename(); |
|
|
void *gnp; /* Node to examine */ |
void *gnp; /* Node to examine */ |
{ |
{ |
GNode *gn = (GNode *) gnp; |
GNode *gn = (GNode *) gnp; |
if (!Lst_IsEmpty(gn->commands)) { |
if (!Lst_IsEmpty(&gn->commands)) { |
gn->type |= OP_HAS_COMMANDS; |
gn->type |= OP_HAS_COMMANDS; |
} |
} |
} |
} |
|
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
void |
void |
Parse_AddIncludeDir (dir) |
Parse_AddIncludeDir(dir) |
char *dir; /* The name of the directory to add */ |
char *dir; /* The name of the directory to add */ |
{ |
{ |
Dir_AddDir (parseIncPath, dir); |
Dir_AddDir(&parseIncPath, dir); |
} |
} |
|
|
/*- |
/*- |
|
|
newName = estrdup(file); |
newName = estrdup(file); |
else |
else |
newName = str_concat (Fname, file, STR_ADDSLASH); |
newName = str_concat (Fname, file, STR_ADDSLASH); |
fullname = Dir_FindFile (newName, parseIncPath); |
fullname = Dir_FindFile(newName, &parseIncPath); |
if (fullname == (char *)NULL) { |
if (fullname == (char *)NULL) { |
fullname = Dir_FindFile(newName, dirSearchPath); |
fullname = Dir_FindFile(newName, &dirSearchPath); |
} |
} |
free (newName); |
free (newName); |
*prefEnd = '/'; |
*prefEnd = '/'; |
|
|
* then on the .PATH search path, if not found in a -I directory. |
* then on the .PATH search path, if not found in a -I directory. |
* XXX: Suffix specific? |
* XXX: Suffix specific? |
*/ |
*/ |
fullname = Dir_FindFile (file, parseIncPath); |
fullname = Dir_FindFile(file, &parseIncPath); |
if (fullname == (char *)NULL) { |
if (fullname == (char *)NULL) { |
fullname = Dir_FindFile(file, dirSearchPath); |
fullname = Dir_FindFile(file, &dirSearchPath); |
} |
} |
} |
} |
|
|
|
|
* Still haven't found the makefile. Look for it on the system |
* Still haven't found the makefile. Look for it on the system |
* path as a last resort. |
* path as a last resort. |
*/ |
*/ |
fullname = Dir_FindFile(file, sysIncPath); |
fullname = Dir_FindFile(file, &sysIncPath); |
} |
} |
|
|
if (fullname == (char *) NULL) { |
if (fullname == (char *) NULL) { |
|
|
oldFile->p = curPTR; |
oldFile->p = curPTR; |
oldFile->lineno = lineno; |
oldFile->lineno = lineno; |
|
|
Lst_AtFront(includes, oldFile); |
Lst_AtFront(&includes, oldFile); |
|
|
/* |
/* |
* Once the previous state has been saved, we can get down to reading |
* Once the previous state has been saved, we can get down to reading |
|
|
*/ |
*/ |
fname = fullname; |
fname = fullname; |
#ifdef CLEANUP |
#ifdef CLEANUP |
Lst_AtEnd(fileNames, fname); |
Lst_AtEnd(&fileNames, fname); |
#endif |
#endif |
lineno = 0; |
lineno = 0; |
|
|
|
|
oldFile->F = curFILE; |
oldFile->F = curFILE; |
oldFile->p = curPTR; |
oldFile->p = curPTR; |
|
|
Lst_AtFront(includes, oldFile); |
Lst_AtFront(&includes, oldFile); |
|
|
curFILE = NULL; |
curFILE = NULL; |
curPTR = (PTR *) emalloc (sizeof (PTR)); |
curPTR = (PTR *) emalloc (sizeof (PTR)); |
|
|
|
|
*prefEnd = '\0'; |
*prefEnd = '\0'; |
newName = str_concat (fname, file, STR_ADDSLASH); |
newName = str_concat (fname, file, STR_ADDSLASH); |
fullname = Dir_FindFile (newName, parseIncPath); |
fullname = Dir_FindFile(newName, &parseIncPath); |
if (fullname == (char *)NULL) { |
if (fullname == NULL) |
fullname = Dir_FindFile(newName, dirSearchPath); |
fullname = Dir_FindFile(newName, &dirSearchPath); |
} |
|
free (newName); |
free (newName); |
*prefEnd = '/'; |
*prefEnd = '/'; |
} else { |
} else { |
|
|
* then on the .PATH search path, if not found in a -I directory. |
* then on the .PATH search path, if not found in a -I directory. |
* XXX: Suffix specific? |
* XXX: Suffix specific? |
*/ |
*/ |
fullname = Dir_FindFile (file, parseIncPath); |
fullname = Dir_FindFile(file, &parseIncPath); |
if (fullname == (char *)NULL) { |
if (fullname == NULL) |
fullname = Dir_FindFile(file, dirSearchPath); |
fullname = Dir_FindFile(file, &dirSearchPath); |
} |
|
} |
} |
|
|
if (fullname == (char *)NULL) { |
if (fullname == (char *)NULL) { |
|
|
* Still haven't found the makefile. Look for it on the system |
* Still haven't found the makefile. Look for it on the system |
* path as a last resort. |
* path as a last resort. |
*/ |
*/ |
fullname = Dir_FindFile(file, sysIncPath); |
fullname = Dir_FindFile(file, &sysIncPath); |
} |
} |
|
|
if (fullname == (char *) NULL) { |
if (fullname == (char *) NULL) { |
|
|
oldFile->p = curPTR; |
oldFile->p = curPTR; |
oldFile->lineno = lineno; |
oldFile->lineno = lineno; |
|
|
Lst_AtFront(includes, oldFile); |
Lst_AtFront(&includes, oldFile); |
|
|
/* |
/* |
* Once the previous state has been saved, we can get down to reading |
* Once the previous state has been saved, we can get down to reading |
|
|
*/ |
*/ |
fname = fullname; |
fname = fullname; |
#ifdef CLEANUP |
#ifdef CLEANUP |
lst_AtEnd(fileNames, fname); |
Lst_AtEnd(&fileNames, fname); |
#endif |
#endif |
lineno = 0; |
lineno = 0; |
|
|
|
|
{ |
{ |
IFile *ifile; /* the state on the top of the includes stack */ |
IFile *ifile; /* the state on the top of the includes stack */ |
|
|
if ((ifile = (IFile *)Lst_DeQueue(includes)) == NULL) |
if ((ifile = (IFile *)Lst_DeQueue(&includes)) == NULL) |
return DONE; |
return DONE; |
fname = ifile->fname; |
fname = ifile->fname; |
lineno = ifile->lineno; |
lineno = ifile->lineno; |
|
|
{ |
{ |
if (inLine) { |
if (inLine) { |
Lst_Every(targets, Suff_EndTransform); |
Lst_Every(targets, Suff_EndTransform); |
Lst_Destroy(targets, ParseHasCommands); |
Lst_Delete(targets, ParseHasCommands); |
targets = NULL; |
targets = NULL; |
inLine = FALSE; |
inLine = FALSE; |
} |
} |
|
|
inLine = FALSE; |
inLine = FALSE; |
fname = estrdup(name); |
fname = estrdup(name); |
#ifdef CLEANUP |
#ifdef CLEANUP |
Lst_AtEnd(fileNames, fname); |
Lst_AtEnd(&fileNames, fname); |
#endif |
#endif |
curFILE = stream; |
curFILE = stream; |
lineno = 0; |
lineno = 0; |
|
|
*/ |
*/ |
Lst_ForEach(targets, ParseAddCmd, cp); |
Lst_ForEach(targets, ParseAddCmd, cp); |
#ifdef CLEANUP |
#ifdef CLEANUP |
Lst_AtEnd(targCmds, line); |
Lst_AtEnd(&targCmds, line); |
#endif |
#endif |
continue; |
continue; |
} else { |
} else { |
|
|
* Need a non-circular list for the target nodes |
* Need a non-circular list for the target nodes |
*/ |
*/ |
if (targets) |
if (targets) |
Lst_Destroy(targets, NOFREE); |
Lst_Delete(targets, NOFREE); |
|
|
targets = Lst_Init(); |
targets = Lst_New(); |
inLine = TRUE; |
inLine = TRUE; |
|
|
ParseDoDependency (line); |
ParseDoDependency (line); |
|
|
* Parse_Init -- |
* Parse_Init -- |
* initialize the parsing module |
* initialize the parsing module |
* |
* |
* Results: |
|
* none |
|
* |
|
* Side Effects: |
* Side Effects: |
* the parseIncPath list is initialized... |
* the parseIncPath list is initialized... |
*--------------------------------------------------------------------- |
*--------------------------------------------------------------------- |
*/ |
*/ |
void |
void |
Parse_Init () |
Parse_Init() |
{ |
{ |
mainNode = NULL; |
mainNode = NULL; |
parseIncPath = Lst_Init(); |
Lst_Init(&parseIncPath); |
sysIncPath = Lst_Init(); |
Lst_Init(&sysIncPath); |
includes = Lst_Init(); |
Lst_Init(&includes); |
#ifdef CLEANUP |
#ifdef CLEANUP |
targCmds = Lst_Init(); |
Lst_Init(&targCmds); |
fileNames = Lst_Init(); |
Lst_Init(&fileNames); |
#endif |
#endif |
} |
} |
|
|
|
|
Parse_End() |
Parse_End() |
{ |
{ |
#ifdef CLEANUP |
#ifdef CLEANUP |
Lst_Destroy(targCmds, (SimpleProc)free); |
Lst_Destroy(&targCmds, (SimpleProc)free); |
Lst_Destroy(fileNames, (void (*) __P((ClientData))) free); |
Lst_Destroy(&fileNames, (void (*) __P((ClientData))) free); |
if (targets) |
if (targets) |
Lst_Destroy(targets, NOFREE); |
Lst_Delete(targets, NOFREE); |
Lst_Destroy(sysIncPath, Dir_Destroy); |
Lst_Destroy(&sysIncPath, Dir_Destroy); |
Lst_Destroy(parseIncPath, Dir_Destroy); |
Lst_Destroy(&parseIncPath, Dir_Destroy); |
Lst_Destroy(includes, NOFREE); /* Should be empty now */ |
Lst_Destroy(&includes, NOFREE); /* Should be empty now */ |
#endif |
#endif |
} |
} |
|
|
|
|
{ |
{ |
Lst listmain; /* result list */ |
Lst listmain; /* result list */ |
|
|
listmain = Lst_Init(); |
listmain = Lst_New(); |
|
|
if (mainNode == NULL) { |
if (mainNode == NULL) { |
Punt ("no target to make."); |
Punt ("no target to make."); |
/*NOTREACHED*/ |
/*NOTREACHED*/ |
} else if (mainNode->type & OP_DOUBLEDEP) { |
} else if (mainNode->type & OP_DOUBLEDEP) { |
Lst_AtEnd(listmain, mainNode); |
Lst_AtEnd(listmain, mainNode); |
Lst_Concat(listmain, mainNode->cohorts, LST_CONCNEW); |
Lst_Concat(listmain, &mainNode->cohorts, LST_CONCNEW); |
} |
} |
else |
else |
Lst_AtEnd(listmain, mainNode); |
Lst_AtEnd(listmain, mainNode); |