summaryrefslogtreecommitdiff
path: root/usr.bin/make/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/make/parse.c')
-rw-r--r--usr.bin/make/parse.c651
1 files changed, 361 insertions, 290 deletions
diff --git a/usr.bin/make/parse.c b/usr.bin/make/parse.c
index 669c68a15436..e4d8446279bd 100644
--- a/usr.bin/make/parse.c
+++ b/usr.bin/make/parse.c
@@ -1,5 +1,3 @@
-/* $NetBSD: parse.c,v 1.26 1996/09/27 02:36:58 thorpej Exp $ */
-
/*
* Copyright (c) 1988, 1989, 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -39,11 +37,7 @@
*/
#ifndef lint
-#if 0
-static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94";
-#else
-static char rcsid[] = "$NetBSD: parse.c,v 1.26 1996/09/27 02:36:58 thorpej Exp $";
-#endif
+static char sccsid[] = "@(#)parse.c 8.6 (Berkeley) 6/13/95";
#endif /* not lint */
/*-
@@ -96,6 +90,7 @@ static char rcsid[] = "$NetBSD: parse.c,v 1.26 1996/09/27 02:36:58 thorpej Exp $
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
+#include <sys/wait.h>
#include "make.h"
#include "hash.h"
#include "dir.h"
@@ -167,20 +162,17 @@ typedef enum {
NotParallel, /* .NOTPARALELL */
Null, /* .NULL */
Order, /* .ORDER */
- Parallel, /* .PARALLEL */
ExPath, /* .PATH */
- Phony, /* .PHONY */
Precious, /* .PRECIOUS */
+ Reserved, /* .RESERVED or .[A-Z]* */
ExShell, /* .SHELL */
Silent, /* .SILENT */
SingleShell, /* .SINGLESHELL */
Suffixes, /* .SUFFIXES */
- Wait, /* .WAIT */
Attribute /* Generic attribute */
} ParseSpecial;
static ParseSpecial specType;
-static int waiting;
/*
* Predecessor node for handling .ORDER. Initialized to NILGNODE when .ORDER
@@ -200,44 +192,70 @@ static struct {
ParseSpecial spec; /* Type when used as a target */
int op; /* Operator when used as a source */
} parseKeywords[] = {
+#define DOT_BEGIN 0
{ ".BEGIN", Begin, 0 },
+#define DOT_DEFAULT 1
{ ".DEFAULT", Default, 0 },
+#define DOT_END 2
{ ".END", End, 0 },
+#define DOT_EXEC 3
{ ".EXEC", Attribute, OP_EXEC },
+#define DOT_IGNORE 4
{ ".IGNORE", Ignore, OP_IGNORE },
+#define DOT_INCLUDES 5
{ ".INCLUDES", Includes, 0 },
+#define DOT_INTERRUPT 6
{ ".INTERRUPT", Interrupt, 0 },
+#define DOT_INVISIBLE 7
{ ".INVISIBLE", Attribute, OP_INVISIBLE },
+#define DOT_JOIN 8
{ ".JOIN", Attribute, OP_JOIN },
+#define DOT_LIBS 9
{ ".LIBS", Libs, 0 },
+#define DOT_MAIN 10
{ ".MAIN", Main, 0 },
+#define DOT_MAKE 11
{ ".MAKE", Attribute, OP_MAKE },
+#define DOT_MAKEFLAGS 12
{ ".MAKEFLAGS", MFlags, 0 },
+#define DOT_MFLAGS 13
{ ".MFLAGS", MFlags, 0 },
+#define DOT_NOTMAIN 14
{ ".NOTMAIN", Attribute, OP_NOTMAIN },
+#define DOT_NOTPARALLEL 15
{ ".NOTPARALLEL", NotParallel, 0 },
-{ ".NO_PARALLEL", NotParallel, 0 },
+#define DOT_NULL 16
{ ".NULL", Null, 0 },
+#define DOT_OPTIONAL 17
{ ".OPTIONAL", Attribute, OP_OPTIONAL },
+#define DOT_ORDER 18
{ ".ORDER", Order, 0 },
-{ ".PARALLEL", Parallel, 0 },
+#define DOT_PATH 19
{ ".PATH", ExPath, 0 },
-{ ".PHONY", Phony, OP_PHONY },
+#define DOT_PHONY 20
+{ ".PHONY", Attribute, OP_PHONY },
+#define DOT_PRECIOUS 21
{ ".PRECIOUS", Precious, OP_PRECIOUS },
+#define DOT_RECURSIVE 22
{ ".RECURSIVE", Attribute, OP_MAKE },
+#define DOT_RESERVED 23
+{ ".RESERVED", Reserved, 0 },
+#define DOT_SHELL 24
{ ".SHELL", ExShell, 0 },
+#define DOT_SILENT 25
{ ".SILENT", Silent, OP_SILENT },
+#define DOT_SINGLESHELL 26
{ ".SINGLESHELL", SingleShell, 0 },
+#define DOT_SUFFIXES 27
{ ".SUFFIXES", Suffixes, 0 },
+#define DOT_USE 28
{ ".USE", Attribute, OP_USE },
-{ ".WAIT", Wait, 0 },
};
static int ParseFindKeyword __P((char *));
static int ParseLinkSrc __P((ClientData, ClientData));
static int ParseDoOp __P((ClientData, ClientData));
-static int ParseAddDep __P((ClientData, ClientData));
-static void ParseDoSrc __P((int, char *, Lst));
+static void ParseDoSrc __P((int, char *));
static int ParseFindMain __P((ClientData, ClientData));
static int ParseAddDir __P((ClientData, ClientData));
static int ParseClearPath __P((ClientData, ClientData));
@@ -275,7 +293,7 @@ ParseFindKeyword (str)
end,
cur;
register int diff;
-
+
start = 0;
end = (sizeof(parseKeywords)/sizeof(parseKeywords[0])) - 1;
@@ -291,7 +309,12 @@ ParseFindKeyword (str)
start = cur + 1;
}
} while (start <= end);
- return (-1);
+
+ cur = 0;
+ for (++str; *str; str++)
+ if (!isupper((unsigned char) *str))
+ break;
+ return *str ? -1 : DOT_RESERVED;
}
/*-
@@ -398,7 +421,7 @@ ParseDoOp (gnp, opp)
/*
* If the dependency mask of the operator and the node don't match and
* the node has actually had an operator applied to it before, and
- * the operator actually has some dependency information in it, complain.
+ * the operator actually has some dependency information in it, complain.
*/
if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) &&
!OP_NOP(gn->type) && !OP_NOP(op))
@@ -418,7 +441,7 @@ ParseDoOp (gnp, opp)
*/
register GNode *cohort;
LstNode ln;
-
+
cohort = Targ_NewGN(gn->name);
/*
* Duplicate links to parents so graph traversal is simple. Perhaps
@@ -442,7 +465,7 @@ ParseDoOp (gnp, opp)
}
/*
* We don't want to nuke any previous flags (whatever they were) so we
- * just OR the new operator into the old
+ * just OR the new operator into the old
*/
gn->type |= op;
@@ -451,45 +474,6 @@ ParseDoOp (gnp, opp)
/*-
*---------------------------------------------------------------------
- * ParseAddDep --
- * Check if the pair of GNodes given needs to be synchronized.
- * This has to be when two nodes are on different sides of a
- * .WAIT directive.
- *
- * Results:
- * Returns 1 if the two targets need to be ordered, 0 otherwise.
- * If it returns 1, the search can stop
- *
- * Side Effects:
- * A dependency can be added between the two nodes.
- *
- *---------------------------------------------------------------------
- */
-int
-ParseAddDep(pp, sp)
- ClientData pp;
- ClientData sp;
-{
- GNode *p = (GNode *) pp;
- GNode *s = (GNode *) sp;
-
- if (p->order < s->order) {
- /*
- * XXX: This can cause loops, and loops can cause unmade targets,
- * but checking is tedious, and the debugging output can show the
- * problem
- */
- (void)Lst_AtEnd(p->successors, (ClientData)s);
- (void)Lst_AtEnd(s->preds, (ClientData)p);
- return 0;
- }
- else
- return 1;
-}
-
-
-/*-
- *---------------------------------------------------------------------
* ParseDoSrc --
* Given the name of a source, figure out if it is an attribute
* and apply it to the targets if it is. Else decide if there is
@@ -506,31 +490,23 @@ ParseAddDep(pp, sp)
*---------------------------------------------------------------------
*/
static void
-ParseDoSrc (tOp, src, allsrc)
+ParseDoSrc (tOp, src)
int tOp; /* operator (if any) from special targets */
char *src; /* name of the source to handle */
- Lst allsrc; /* List of all sources to wait for */
-
{
- GNode *gn = NULL;
+ int op; /* operator (if any) from special source */
+ GNode *gn;
+ op = 0;
if (*src == '.' && isupper (src[1])) {
int keywd = ParseFindKeyword(src);
if (keywd != -1) {
- int op = parseKeywords[keywd].op;
- if (op != 0) {
- Lst_ForEach (targets, ParseDoOp, (ClientData)&op);
- return;
- }
- if (parseKeywords[keywd].spec == Wait) {
- waiting++;
- return;
- }
+ op = parseKeywords[keywd].op;
}
}
-
- switch (specType) {
- case Main:
+ if (op != 0) {
+ Lst_ForEach (targets, ParseDoOp, (ClientData)&op);
+ } else if (specType == Main) {
/*
* If we have noted the existence of a .MAIN, it means we need
* to add the sources of said target to the list of things
@@ -539,15 +515,13 @@ ParseDoSrc (tOp, src, allsrc)
* invoked if the user didn't specify a target on the command
* line. This is to allow #ifmake's to succeed, or something...
*/
- (void) Lst_AtEnd (create, (ClientData)estrdup(src));
+ (void) Lst_AtEnd (create, (ClientData)strdup(src));
/*
* Add the name to the .TARGETS variable as well, so the user cna
* employ that, if desired.
*/
Var_Append(".TARGETS", src, VAR_GLOBAL);
- return;
-
- case Order:
+ } else if (specType == Order) {
/*
* Create proper predecessor/successor links between the previous
* source and the current one.
@@ -561,9 +535,7 @@ ParseDoSrc (tOp, src, allsrc)
* The current source now becomes the predecessor for the next one.
*/
predecessor = gn;
- break;
-
- default:
+ } else {
/*
* If the source is not an attribute, we need to find/create
* a node for it. After that we can apply any operator to it
@@ -594,13 +566,6 @@ ParseDoSrc (tOp, src, allsrc)
}
}
}
- break;
- }
-
- gn->order = waiting;
- (void)Lst_AtEnd(allsrc, (ClientData)gn);
- if (waiting) {
- Lst_ForEach(allsrc, ParseAddDep, (ClientData)gn);
}
}
@@ -723,21 +688,17 @@ ParseDoDependency (line)
Lst paths; /* List of search paths to alter when parsing
* a list of .PATH targets */
int tOp; /* operator from special target */
- Lst sources; /* list of archive source names after
- * expansion */
+ Lst sources; /* list of source names after expansion */
Lst curTargs; /* list of target names to be found and added
* to the targets list */
- Lst curSrcs; /* list of sources in order */
tOp = 0;
specType = Not;
- waiting = 0;
paths = (Lst)NULL;
curTargs = Lst_Init(FALSE);
- curSrcs = Lst_Init(FALSE);
-
+
do {
for (cp = line;
*cp && !isspace (*cp) &&
@@ -785,11 +746,11 @@ ParseDoDependency (line)
}
}
savec = *cp;
-
+
if (!*cp) {
/*
* Ending a dependency line without an operator is a Bozo
- * no-no
+ * no-no
*/
Parse_Error (PARSE_FATAL, "Need an operator");
return;
@@ -802,7 +763,7 @@ ParseDoDependency (line)
if (*line == '.' && isupper (line[1])) {
/*
* See if the target is a special target that must have it
- * or its sources handled specially.
+ * or its sources handled specially.
*/
int keywd = ParseFindKeyword(line);
if (keywd != -1) {
@@ -810,7 +771,7 @@ ParseDoDependency (line)
Parse_Error(PARSE_FATAL, "Mismatched special targets");
return;
}
-
+
specType = parseKeywords[keywd].spec;
tOp = parseKeywords[keywd].op;
@@ -833,7 +794,6 @@ ParseDoDependency (line)
* life easier later, when we'll
* use Make_HandleUse to actually
* apply the .DEFAULT commands.
- * .PHONY The list of targets
* .BEGIN
* .END
* .INTERRUPT Are not to be considered the
@@ -870,7 +830,7 @@ ParseDoDependency (line)
case NotParallel:
{
extern int maxJobs;
-
+
maxJobs = 1;
break;
}
@@ -880,6 +840,12 @@ ParseDoDependency (line)
case Order:
predecessor = NILGNODE;
break;
+ case Reserved:
+ /*
+ * A posix reserved target that we don't know
+ * how to deal with.
+ */
+ return;
default:
break;
}
@@ -890,7 +856,7 @@ ParseDoDependency (line)
* modify.
*/
Lst path;
-
+
specType = ExPath;
path = Suff_GetPath (&line[5]);
if (path == NILLST) {
@@ -906,10 +872,10 @@ ParseDoDependency (line)
}
}
}
-
+
/*
* Have word in line. Get or create its node and stick it at
- * the end of the targets list
+ * the end of the targets list
*/
if ((specType == Not) && (*line != '\0')) {
if (Dir_HasWildcards(line)) {
@@ -920,9 +886,9 @@ ParseDoDependency (line)
* Dir module could have added a directory to the path...
*/
Lst emptyPath = Lst_Init(FALSE);
-
+
Dir_Expand(line, emptyPath, curTargs);
-
+
Lst_Destroy(emptyPath, Dir_Destroy);
} else {
/*
@@ -931,22 +897,22 @@ ParseDoDependency (line)
*/
(void)Lst_AtEnd(curTargs, (ClientData)line);
}
-
+
while(!Lst_IsEmpty(curTargs)) {
char *targName = (char *)Lst_DeQueue(curTargs);
-
+
if (!Suff_IsTransform (targName)) {
gn = Targ_FindNode (targName, TARG_CREATE);
} else {
gn = Suff_AddTransform (targName);
}
-
+
(void)Lst_AtEnd (targets, (ClientData)gn);
}
} else if (specType == ExPath && *line != '.' && *line != '\0') {
Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line);
}
-
+
*cp = savec;
/*
* If it is a special type and not .PATH, it's the only target we
@@ -954,7 +920,7 @@ ParseDoDependency (line)
*/
if (specType != Not && specType != ExPath) {
Boolean warn = FALSE;
-
+
while ((*cp != '!') && (*cp != ':') && *cp) {
if (*cp != ' ' && *cp != '\t') {
warn = TRUE;
@@ -1021,7 +987,7 @@ ParseDoDependency (line)
Lst_ForEach (targets, ParseDoOp, (ClientData)&op);
/*
- * Get to the first source
+ * Get to the first source
*/
while (*cp && isspace (*cp)) {
cp++;
@@ -1074,9 +1040,9 @@ ParseDoDependency (line)
} else if ((specType == NotParallel) || (specType == SingleShell)) {
*line = '\0';
}
-
+
/*
- * NOW GO FOR THE SOURCES
+ * NOW GO FOR THE SOURCES
*/
if ((specType == Suffixes) || (specType == ExPath) ||
(specType == Includes) || (specType == Libs) ||
@@ -1177,7 +1143,7 @@ ParseDoDependency (line)
while (!Lst_IsEmpty (sources)) {
gn = (GNode *) Lst_DeQueue (sources);
- ParseDoSrc (tOp, gn->name, curSrcs);
+ ParseDoSrc (tOp, gn->name);
}
Lst_Destroy (sources, NOFREE);
cp = line;
@@ -1187,7 +1153,7 @@ ParseDoDependency (line)
cp += 1;
}
- ParseDoSrc (tOp, line, curSrcs);
+ ParseDoSrc (tOp, line);
}
while (*cp && isspace (*cp)) {
cp++;
@@ -1195,7 +1161,7 @@ ParseDoDependency (line)
line = cp;
}
}
-
+
if (mainNode == NILGNODE) {
/*
* If we have yet to decide on a main target to make, in the
@@ -1206,10 +1172,6 @@ ParseDoDependency (line)
Lst_ForEach (targets, ParseFindMain, (ClientData)0);
}
- /*
- * Finally, destroy the list of sources
- */
- Lst_Destroy(curSrcs, NOFREE);
}
/*-
@@ -1234,80 +1196,60 @@ Parse_IsVar (line)
{
register Boolean wasSpace = FALSE; /* set TRUE if found a space */
register Boolean haveName = FALSE; /* Set TRUE if have a variable name */
- int level = 0;
-#define ISEQOPERATOR(c) \
- (((c) == '+') || ((c) == ':') || ((c) == '?') || ((c) == '!'))
/*
* Skip to variable name
*/
- for (;(*line == ' ') || (*line == '\t'); line++)
- continue;
+ while ((*line == ' ') || (*line == '\t')) {
+ line++;
+ }
- for (; *line != '=' || level != 0; line++)
- switch (*line) {
- case '\0':
+ while (*line != '=') {
+ if (*line == '\0') {
/*
* end-of-line -- can't be a variable assignment.
*/
- return FALSE;
-
- case ' ':
- case '\t':
+ return (FALSE);
+ } else if ((*line == ' ') || (*line == '\t')) {
/*
* there can be as much white space as desired so long as there is
- * only one word before the operator
+ * only one word before the operator
*/
wasSpace = TRUE;
- break;
-
- case '(':
- case '{':
- level++;
- break;
-
- case '}':
- case ')':
- level--;
- break;
-
- default:
- if (wasSpace && haveName) {
- if (ISEQOPERATOR(*line)) {
- /*
- * We must have a finished word
- */
- if (level != 0)
- return FALSE;
-
- /*
- * When an = operator [+?!:] is found, the next
- * character must be an = or it ain't a valid
- * assignment.
- */
- if (line[1] == '=')
- return haveName;
-#ifdef SUNSHCMD
- /*
- * This is a shell command
- */
- if (strncmp(line, ":sh", 3) == 0)
- return haveName;
-#endif
- }
- /*
- * This is the start of another word, so not assignment.
- */
- return FALSE;
- }
- else {
- haveName = TRUE;
- wasSpace = FALSE;
+ } else if (wasSpace && haveName) {
+ /*
+ * Stop when an = operator is found.
+ */
+ if ((*line == '+') || (*line == ':') || (*line == '?') ||
+ (*line == '!')) {
+ break;
}
- break;
+
+ /*
+ * This is the start of another word, so not assignment.
+ */
+ return (FALSE);
+ } else {
+ haveName = TRUE;
+ wasSpace = FALSE;
}
+ line++;
+ }
- return haveName;
+ /*
+ * A final check: if we stopped on a +, ?, ! or :, the next character must
+ * be an = or it ain't a valid assignment
+ */
+ if (((*line == '+') ||
+ (*line == '?') ||
+ (*line == ':') ||
+ (*line == '!')) &&
+ (line[1] != '='))
+ {
+ return (FALSE);
+ } else {
+ return (haveName);
+ }
}
/*-
@@ -1340,9 +1282,9 @@ Parse_DoVar (line, ctxt)
enum {
VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL
} type; /* Type of assignment */
- char *opc; /* ptr to operator character to
+ char *opc; /* ptr to operator character to
* null-terminate the variable name */
- /*
+ /*
* Avoid clobbered variable warnings by forcing the compiler
* to ``unregister'' variables
*/
@@ -1401,17 +1343,6 @@ Parse_DoVar (line, ctxt)
break;
default:
-#ifdef SUNSHCMD
- while (*opc != ':')
- if (--opc < line)
- break;
-
- if (strncmp(opc, ":sh", 3) == 0) {
- type = VAR_SHELL;
- *opc = '\0';
- break;
- }
-#endif
type = VAR_NORMAL;
break;
}
@@ -1443,38 +1374,156 @@ Parse_DoVar (line, ctxt)
Var_Set(line, cp, ctxt);
free(cp);
} else if (type == VAR_SHELL) {
- Boolean freeCmd = FALSE; /* TRUE if the command needs to be freed, i.e.
- * if any variable expansion was performed */
- char *res, *err;
+ char *args[4]; /* Args for invoking the shell */
+ int fds[2]; /* Pipe streams */
+ int cpid; /* Child PID */
+ int pid; /* PID from wait() */
+ Boolean freeCmd; /* TRUE if the command needs to be freed, i.e.
+ * if any variable expansion was performed */
+
+ /*
+ * Avoid clobbered variable warnings by forcing the compiler
+ * to ``unregister'' variables
+ */
+#if __GNUC__
+ (void) &freeCmd;
+#endif
- if (strchr(cp, '$') != NULL) {
+ /*
+ * Set up arguments for shell
+ */
+ args[0] = "sh";
+ args[1] = "-c";
+ if (strchr(cp, '$') != (char *)NULL) {
/*
* There's a dollar sign in the command, so perform variable
* expansion on the whole thing. The resulting string will need
* freeing when we're done, so set freeCmd to TRUE.
*/
- cp = Var_Subst(NULL, cp, VAR_CMD, TRUE);
+ args[2] = Var_Subst(NULL, cp, VAR_CMD, TRUE);
freeCmd = TRUE;
+ } else {
+ args[2] = cp;
+ freeCmd = FALSE;
}
+ args[3] = (char *)NULL;
+
+ /*
+ * Open a pipe for fetching its output
+ */
+ pipe(fds);
+
+ /*
+ * Fork
+ */
+ cpid = vfork();
+ if (cpid == 0) {
+ /*
+ * Close input side of pipe
+ */
+ close(fds[0]);
- res = Cmd_Exec(cp, &err);
- Var_Set(line, res, ctxt);
- free(res);
+ /*
+ * Duplicate the output stream to the shell's output, then
+ * shut the extra thing down. Note we don't fetch the error
+ * stream...why not? Why?
+ */
+ dup2(fds[1], 1);
+ close(fds[1]);
+
+ execv("/bin/sh", args);
+ _exit(1);
+ } else if (cpid < 0) {
+ /*
+ * Couldn't fork -- tell the user and make the variable null
+ */
+ Parse_Error(PARSE_WARNING, "Couldn't exec \"%s\"", cp);
+ Var_Set(line, "", ctxt);
+ } else {
+ int status;
+ int cc;
+ Buffer buf;
+ char *res;
- if (err)
- Parse_Error(PARSE_WARNING, err, cp);
+ /*
+ * No need for the writing half
+ */
+ close(fds[1]);
+
+ buf = Buf_Init (MAKE_BSIZE);
+
+ do {
+ char result[BUFSIZ];
+ cc = read(fds[0], result, sizeof(result));
+ if (cc > 0)
+ Buf_AddBytes(buf, cc, (Byte *) result);
+ }
+ while (cc > 0 || (cc == -1 && errno == EINTR));
+
+ /*
+ * Close the input side of the pipe.
+ */
+ close(fds[0]);
- if (freeCmd)
- free(cp);
+ /*
+ * Wait for the process to exit.
+ */
+ while(((pid = wait(&status)) != cpid) && (pid >= 0))
+ continue;
+
+ res = (char *)Buf_GetAll (buf, &cc);
+ Buf_Destroy (buf, FALSE);
+
+ if (cc == 0) {
+ /*
+ * Couldn't read the child's output -- tell the user and
+ * set the variable to null
+ */
+ Parse_Error(PARSE_WARNING, "Couldn't read shell's output");
+ }
+
+ if (status) {
+ /*
+ * Child returned an error -- tell the user but still use
+ * the result.
+ */
+ Parse_Error(PARSE_WARNING, "\"%s\" returned non-zero", cp);
+ }
+
+ /*
+ * Null-terminate the result, convert newlines to spaces and
+ * install it in the variable.
+ */
+ res[cc] = '\0';
+ cp = &res[cc] - 1;
+
+ if (*cp == '\n') {
+ /*
+ * A final newline is just stripped
+ */
+ *cp-- = '\0';
+ }
+ while (cp >= res) {
+ if (*cp == '\n') {
+ *cp = ' ';
+ }
+ cp--;
+ }
+ Var_Set(line, res, ctxt);
+ free(res);
+
+ }
+ if (freeCmd) {
+ free(args[2]);
+ }
} else {
/*
* Normal assignment -- just do it.
*/
- Var_Set(line, cp, ctxt);
+ Var_Set (line, cp, ctxt);
}
}
-
/*-
* ParseAddCmd --
* Lst_ForEach function to add a command line to all targets
@@ -1548,7 +1597,7 @@ Parse_AddIncludeDir (dir)
*---------------------------------------------------------------------
* ParseDoInclude --
* Push to another file.
- *
+ *
* The input is the line minus the #include. A file spec is a string
* enclosed in <> or "". The former is looked for only in sysIncPath.
* The latter in . and the directories specified by -I command line
@@ -1632,20 +1681,17 @@ ParseDoInclude (file)
* leading path components and call Dir_FindFile to see if
* we can locate the beast.
*/
- char *prefEnd, *Fname;
+ char *prefEnd;
- /* Make a temporary copy of this, to be safe. */
- Fname = estrdup(fname);
-
- prefEnd = strrchr (Fname, '/');
+ prefEnd = strrchr (fname, '/');
if (prefEnd != (char *)NULL) {
char *newName;
-
+
*prefEnd = '\0';
if (file[0] == '/')
- newName = estrdup(file);
+ newName = strdup(file);
else
- newName = str_concat (Fname, file, STR_ADDSLASH);
+ newName = str_concat (fname, file, STR_ADDSLASH);
fullname = Dir_FindFile (newName, parseIncPath);
if (fullname == (char *)NULL) {
fullname = Dir_FindFile(newName, dirSearchPath);
@@ -1655,7 +1701,6 @@ ParseDoInclude (file)
} else {
fullname = (char *)NULL;
}
- free (Fname);
} else {
fullname = (char *)NULL;
}
@@ -1730,7 +1775,7 @@ ParseDoInclude (file)
*---------------------------------------------------------------------
* Parse_FromString --
* Start Parsing from the given string
- *
+ *
* Results:
* None
*
@@ -1753,14 +1798,14 @@ Parse_FromString(str)
oldFile->fname = fname;
oldFile->F = curFILE;
oldFile->p = curPTR;
-
+
(void) Lst_AtFront (includes, (ClientData)oldFile);
curFILE = NULL;
curPTR = (PTR *) emalloc (sizeof (PTR));
curPTR->str = curPTR->ptr = str;
lineno = 0;
- fname = estrdup(fname);
+ fname = strdup(fname);
}
@@ -1769,7 +1814,7 @@ Parse_FromString(str)
*---------------------------------------------------------------------
* ParseTraditionalInclude --
* Push to another file.
- *
+ *
* The input is the line minus the "include". The file name is
* the string following the "include".
*
@@ -1832,7 +1877,7 @@ ParseTraditionalInclude (file)
prefEnd = strrchr (fname, '/');
if (prefEnd != (char *)NULL) {
char *newName;
-
+
*prefEnd = '\0';
newName = str_concat (fname, file, STR_ADDSLASH);
fullname = Dir_FindFile (newName, parseIncPath);
@@ -1952,7 +1997,7 @@ ParseEOF (opened)
/*-
*---------------------------------------------------------------------
* ParseReadc --
- * Read a character from the current file
+ * Read a character from the current file
*
* Results:
* The character that was read
@@ -1965,7 +2010,7 @@ ParseReadc()
{
if (curFILE)
return fgetc(curFILE);
-
+
if (curPTR && *curPTR->ptr)
return *curPTR->ptr++;
return EOF;
@@ -1975,7 +2020,7 @@ ParseReadc()
/*-
*---------------------------------------------------------------------
* ParseUnreadc --
- * Put back a character to the current file
+ * Put back a character to the current file
*
* Results:
* None.
@@ -2006,43 +2051,54 @@ ParseSkipLine(skip)
int skip; /* Skip lines that don't start with . */
{
char *line;
- int c, lastc, lineLength = 0;
+ int c, lastc = '\0', lineLength;
Buffer buf;
- buf = Buf_Init(MAKE_BSIZE);
-
- do {
- Buf_Discard(buf, lineLength);
- lastc = '\0';
-
- while (((c = ParseReadc()) != '\n' || lastc == '\\')
- && c != EOF) {
- if (c == '\n') {
- Buf_ReplaceLastByte(buf, (Byte)' ');
- lineno++;
-
- while ((c = ParseReadc()) == ' ' || c == '\t');
-
- if (c == EOF)
- break;
- }
-
- Buf_AddByte(buf, (Byte)c);
- lastc = c;
- }
+ c = ParseReadc();
- if (c == EOF) {
- Parse_Error(PARSE_FATAL, "Unclosed conditional/for loop");
- Buf_Destroy(buf, TRUE);
- return((char *)NULL);
- }
-
- lineno++;
- Buf_AddByte(buf, (Byte)'\0');
- line = (char *)Buf_GetAll(buf, &lineLength);
- } while (skip == 1 && line[0] != '.');
-
- Buf_Destroy(buf, FALSE);
+ if (skip) {
+ /*
+ * Skip lines until get to one that begins with a
+ * special char.
+ */
+ while ((c != '.') && (c != EOF)) {
+ while (((c != '\n') || (lastc == '\\')) && (c != EOF))
+ {
+ /*
+ * Advance to next unescaped newline
+ */
+ if ((lastc = c) == '\n') {
+ lineno++;
+ }
+ c = ParseReadc();
+ }
+ lineno++;
+
+ lastc = c;
+ c = ParseReadc ();
+ }
+ }
+
+ if (c == EOF) {
+ Parse_Error (PARSE_FATAL, "Unclosed conditional/for loop");
+ return ((char *)NULL);
+ }
+
+ /*
+ * Read the entire line into buf
+ */
+ buf = Buf_Init (MAKE_BSIZE);
+ if (c != '\n') {
+ do {
+ Buf_AddByte (buf, (Byte)c);
+ c = ParseReadc();
+ } while ((c != '\n') && (c != EOF));
+ }
+ lineno++;
+
+ Buf_AddByte (buf, (Byte)'\0');
+ line = (char *)Buf_GetAll (buf, &lineLength);
+ Buf_Destroy (buf, FALSE);
return line;
}
@@ -2108,11 +2164,11 @@ ParseReadLine ()
break;
}
}
-
+
if (c != EOF) {
lastc = c;
buf = Buf_Init(MAKE_BSIZE);
-
+
while (((c = ParseReadc ()) != '\n' || (lastc == '\\')) &&
(c != EOF))
{
@@ -2160,7 +2216,7 @@ test_char:
*/
ParseUnreadc('\t');
goto line_read;
- }
+ }
break;
case '=':
if (!semiNL) {
@@ -2186,11 +2242,7 @@ test_char:
break;
case '#':
if (!ignComment) {
- if (
-#if 0
- compatMake &&
-#endif
- (lastc != '\\')) {
+ if (compatMake && (lastc != '\\')) {
/*
* If the character is a hash mark and it isn't escaped
* (or we're being compatible), the thing is a comment.
@@ -2227,11 +2279,11 @@ test_char:
*/
Buf_AddByte (buf, (Byte)lastc);
lastc = c;
-
+
}
line_read:
lineno++;
-
+
if (lastc != '\0') {
Buf_AddByte (buf, (Byte)lastc);
}
@@ -2247,13 +2299,13 @@ test_char:
ep = line;
while (*ep)
++ep;
- while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) {
+ while (ep > line && (ep[-1] == ' ' || ep[-1] == '\t')) {
if (ep > line + 1 && ep[-2] == '\\')
break;
--ep;
}
*ep = 0;
-
+
if (line[0] == '.') {
/*
* The line might be a conditional. Ask the conditional module
@@ -2285,7 +2337,7 @@ test_char:
*/
line = ParseSkipLine(0);
if (line == NULL) {
- Parse_Error (PARSE_FATAL,
+ Parse_Error (PARSE_FATAL,
"Unexpected end of file in for loop.\n");
break;
}
@@ -2333,7 +2385,7 @@ ParseFinishLine()
inLine = FALSE;
}
}
-
+
/*-
*---------------------------------------------------------------------
@@ -2394,11 +2446,12 @@ Parse_File(name, stream)
goto nextLine;
}
}
- if (*line == '#') {
- /* If we're this far, the line must be a comment. */
+ if (*line == '#' || *line == '\0') {
+ /* If we're this far, the line must be a comment.
+ (Empty lines are ignored as well) */
goto nextLine;
}
-
+
if (*line == '\t') {
/*
* If a line starts with a tab, it can only hope to be
@@ -2415,20 +2468,19 @@ Parse_File(name, stream)
/*
* So long as it's not a blank line and we're actually
* in a dependency spec, add the command to the list of
- * commands of all targets in the dependency spec
+ * commands of all targets in the dependency spec
*/
Lst_ForEach (targets, ParseAddCmd, cp);
Lst_AtEnd(targCmds, (ClientData) line);
continue;
} else {
Parse_Error (PARSE_FATAL,
- "Unassociated shell command \"%s\"",
+ "Unassociated shell command \"%.20s\"",
cp);
}
}
#ifdef SYSVINCLUDE
- } else if (strncmp (line, "include", 7) == 0 &&
- isspace((unsigned char) line[7]) &&
+ } else if (strncmp (line, "include", 7) == 0 &&
strchr(line, ':') == NULL) {
/*
* It's an S3/S5-style "include".
@@ -2453,7 +2505,7 @@ Parse_File(name, stream)
#ifndef POSIX
Boolean nonSpace = FALSE;
#endif
-
+
cp = line;
if (isspace((unsigned char) line[0])) {
while ((*cp != '\0') && isspace((unsigned char) *cp)) {
@@ -2469,7 +2521,7 @@ Parse_File(name, stream)
}
#endif
}
-
+
#ifndef POSIX
if (*cp == '\0') {
if (inLine) {
@@ -2486,16 +2538,16 @@ Parse_File(name, stream)
cp = Var_Subst (NULL, line, VAR_CMD, TRUE);
free (line);
line = cp;
-
+
/*
- * Need a non-circular list for the target nodes
+ * Need a non-circular list for the target nodes
*/
if (targets)
Lst_Destroy(targets, NOFREE);
targets = Lst_Init (FALSE);
inLine = TRUE;
-
+
ParseDoDependency (line);
#ifndef POSIX
}
@@ -2507,7 +2559,7 @@ Parse_File(name, stream)
free (line);
}
/*
- * Reached EOF, but it may be just EOF of an include file...
+ * Reached EOF, but it may be just EOF of an include file...
*/
} while (ParseEOF(1) == CONTINUE);
@@ -2537,11 +2589,30 @@ Parse_File(name, stream)
void
Parse_Init ()
{
+ char *cp = NULL, *start;
+ /* avoid faults on read-only strings */
+ static char syspath[] = _PATH_DEFSYSPATH;
+
mainNode = NILGNODE;
parseIncPath = Lst_Init (FALSE);
sysIncPath = Lst_Init (FALSE);
includes = Lst_Init (FALSE);
targCmds = Lst_Init (FALSE);
+
+ /*
+ * Add the directories from the DEFSYSPATH (more than one may be given
+ * as dir1:...:dirn) to the system include path.
+ */
+ for (start = syspath; *start != '\0'; start = cp) {
+ for (cp = start; *cp != '\0' && *cp != ':'; cp++)
+ continue;
+ if (*cp == '\0') {
+ Dir_AddDir(sysIncPath, start);
+ } else {
+ *cp++ = '\0';
+ Dir_AddDir(sysIncPath, start);
+ }
+ }
}
void
@@ -2554,7 +2625,7 @@ Parse_End()
Lst_Destroy(parseIncPath, Dir_Destroy);
Lst_Destroy(includes, NOFREE); /* Should be empty now */
}
-
+
/*-
*-----------------------------------------------------------------------
@@ -2578,7 +2649,7 @@ Parse_MainName()
main = Lst_Init (FALSE);
if (mainNode == NILGNODE) {
- Punt ("no target to make.");
+ Punt ("make: no target to make.\n");
/*NOTREACHED*/
} else if (mainNode->type & OP_DOUBLEDEP) {
(void) Lst_AtEnd (main, (ClientData)mainNode);