summaryrefslogtreecommitdiffstats
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, 290 insertions, 361 deletions
diff --git a/usr.bin/make/parse.c b/usr.bin/make/parse.c
index e4d8446..669c68a 100644
--- a/usr.bin/make/parse.c
+++ b/usr.bin/make/parse.c
@@ -1,3 +1,5 @@
+/* $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.
@@ -37,7 +39,11 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)parse.c 8.6 (Berkeley) 6/13/95";
+#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
#endif /* not lint */
/*-
@@ -90,7 +96,6 @@ static char sccsid[] = "@(#)parse.c 8.6 (Berkeley) 6/13/95";
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
-#include <sys/wait.h>
#include "make.h"
#include "hash.h"
#include "dir.h"
@@ -162,17 +167,20 @@ 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
@@ -192,70 +200,44 @@ 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 },
-#define DOT_NULL 16
+{ ".NO_PARALLEL", NotParallel, 0 },
{ ".NULL", Null, 0 },
-#define DOT_OPTIONAL 17
{ ".OPTIONAL", Attribute, OP_OPTIONAL },
-#define DOT_ORDER 18
{ ".ORDER", Order, 0 },
-#define DOT_PATH 19
+{ ".PARALLEL", Parallel, 0 },
{ ".PATH", ExPath, 0 },
-#define DOT_PHONY 20
-{ ".PHONY", Attribute, OP_PHONY },
-#define DOT_PRECIOUS 21
+{ ".PHONY", Phony, OP_PHONY },
{ ".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 void ParseDoSrc __P((int, char *));
+static int ParseAddDep __P((ClientData, ClientData));
+static void ParseDoSrc __P((int, char *, Lst));
static int ParseFindMain __P((ClientData, ClientData));
static int ParseAddDir __P((ClientData, ClientData));
static int ParseClearPath __P((ClientData, ClientData));
@@ -293,7 +275,7 @@ ParseFindKeyword (str)
end,
cur;
register int diff;
-
+
start = 0;
end = (sizeof(parseKeywords)/sizeof(parseKeywords[0])) - 1;
@@ -309,12 +291,7 @@ ParseFindKeyword (str)
start = cur + 1;
}
} while (start <= end);
-
- cur = 0;
- for (++str; *str; str++)
- if (!isupper((unsigned char) *str))
- break;
- return *str ? -1 : DOT_RESERVED;
+ return (-1);
}
/*-
@@ -421,7 +398,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))
@@ -441,7 +418,7 @@ ParseDoOp (gnp, opp)
*/
register GNode *cohort;
LstNode ln;
-
+
cohort = Targ_NewGN(gn->name);
/*
* Duplicate links to parents so graph traversal is simple. Perhaps
@@ -465,7 +442,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;
@@ -474,6 +451,45 @@ 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
@@ -490,23 +506,31 @@ ParseDoOp (gnp, opp)
*---------------------------------------------------------------------
*/
static void
-ParseDoSrc (tOp, src)
+ParseDoSrc (tOp, src, allsrc)
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 */
+
{
- int op; /* operator (if any) from special source */
- GNode *gn;
+ GNode *gn = NULL;
- op = 0;
if (*src == '.' && isupper (src[1])) {
int keywd = ParseFindKeyword(src);
if (keywd != -1) {
- op = parseKeywords[keywd].op;
+ int op = parseKeywords[keywd].op;
+ if (op != 0) {
+ Lst_ForEach (targets, ParseDoOp, (ClientData)&op);
+ return;
+ }
+ if (parseKeywords[keywd].spec == Wait) {
+ waiting++;
+ return;
+ }
}
}
- if (op != 0) {
- Lst_ForEach (targets, ParseDoOp, (ClientData)&op);
- } else if (specType == Main) {
+
+ switch (specType) {
+ case 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
@@ -515,13 +539,15 @@ ParseDoSrc (tOp, src)
* 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)strdup(src));
+ (void) Lst_AtEnd (create, (ClientData)estrdup(src));
/*
* Add the name to the .TARGETS variable as well, so the user cna
* employ that, if desired.
*/
Var_Append(".TARGETS", src, VAR_GLOBAL);
- } else if (specType == Order) {
+ return;
+
+ case Order:
/*
* Create proper predecessor/successor links between the previous
* source and the current one.
@@ -535,7 +561,9 @@ ParseDoSrc (tOp, src)
* The current source now becomes the predecessor for the next one.
*/
predecessor = gn;
- } else {
+ break;
+
+ default:
/*
* 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
@@ -566,6 +594,13 @@ ParseDoSrc (tOp, src)
}
}
}
+ break;
+ }
+
+ gn->order = waiting;
+ (void)Lst_AtEnd(allsrc, (ClientData)gn);
+ if (waiting) {
+ Lst_ForEach(allsrc, ParseAddDep, (ClientData)gn);
}
}
@@ -688,17 +723,21 @@ 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 source names after expansion */
+ Lst sources; /* list of archive 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) &&
@@ -746,11 +785,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;
@@ -763,7 +802,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) {
@@ -771,7 +810,7 @@ ParseDoDependency (line)
Parse_Error(PARSE_FATAL, "Mismatched special targets");
return;
}
-
+
specType = parseKeywords[keywd].spec;
tOp = parseKeywords[keywd].op;
@@ -794,6 +833,7 @@ 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
@@ -830,7 +870,7 @@ ParseDoDependency (line)
case NotParallel:
{
extern int maxJobs;
-
+
maxJobs = 1;
break;
}
@@ -840,12 +880,6 @@ 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;
}
@@ -856,7 +890,7 @@ ParseDoDependency (line)
* modify.
*/
Lst path;
-
+
specType = ExPath;
path = Suff_GetPath (&line[5]);
if (path == NILLST) {
@@ -872,10 +906,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)) {
@@ -886,9 +920,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 {
/*
@@ -897,22 +931,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
@@ -920,7 +954,7 @@ ParseDoDependency (line)
*/
if (specType != Not && specType != ExPath) {
Boolean warn = FALSE;
-
+
while ((*cp != '!') && (*cp != ':') && *cp) {
if (*cp != ' ' && *cp != '\t') {
warn = TRUE;
@@ -987,7 +1021,7 @@ ParseDoDependency (line)
Lst_ForEach (targets, ParseDoOp, (ClientData)&op);
/*
- * Get to the first source
+ * Get to the first source
*/
while (*cp && isspace (*cp)) {
cp++;
@@ -1040,9 +1074,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) ||
@@ -1143,7 +1177,7 @@ ParseDoDependency (line)
while (!Lst_IsEmpty (sources)) {
gn = (GNode *) Lst_DeQueue (sources);
- ParseDoSrc (tOp, gn->name);
+ ParseDoSrc (tOp, gn->name, curSrcs);
}
Lst_Destroy (sources, NOFREE);
cp = line;
@@ -1153,7 +1187,7 @@ ParseDoDependency (line)
cp += 1;
}
- ParseDoSrc (tOp, line);
+ ParseDoSrc (tOp, line, curSrcs);
}
while (*cp && isspace (*cp)) {
cp++;
@@ -1161,7 +1195,7 @@ ParseDoDependency (line)
line = cp;
}
}
-
+
if (mainNode == NILGNODE) {
/*
* If we have yet to decide on a main target to make, in the
@@ -1172,6 +1206,10 @@ ParseDoDependency (line)
Lst_ForEach (targets, ParseFindMain, (ClientData)0);
}
+ /*
+ * Finally, destroy the list of sources
+ */
+ Lst_Destroy(curSrcs, NOFREE);
}
/*-
@@ -1196,60 +1234,80 @@ 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
*/
- while ((*line == ' ') || (*line == '\t')) {
- line++;
- }
+ for (;(*line == ' ') || (*line == '\t'); line++)
+ continue;
- while (*line != '=') {
- if (*line == '\0') {
+ for (; *line != '=' || level != 0; line++)
+ switch (*line) {
+ case '\0':
/*
* end-of-line -- can't be a variable assignment.
*/
- return (FALSE);
- } else if ((*line == ' ') || (*line == '\t')) {
+ return FALSE;
+
+ case ' ':
+ case '\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;
- } 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;
+ 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;
+ }
+ break;
}
- line++;
- }
- /*
- * 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);
- }
+ return haveName;
}
/*-
@@ -1282,9 +1340,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
*/
@@ -1343,6 +1401,17 @@ 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;
}
@@ -1374,156 +1443,38 @@ Parse_DoVar (line, ctxt)
Var_Set(line, cp, ctxt);
free(cp);
} else if (type == VAR_SHELL) {
- 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
+ Boolean freeCmd = FALSE; /* TRUE if the command needs to be freed, i.e.
+ * if any variable expansion was performed */
+ char *res, *err;
- /*
- * Set up arguments for shell
- */
- args[0] = "sh";
- args[1] = "-c";
- if (strchr(cp, '$') != (char *)NULL) {
+ if (strchr(cp, '$') != 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.
*/
- args[2] = Var_Subst(NULL, cp, VAR_CMD, TRUE);
+ cp = 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]);
- /*
- * 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;
+ res = Cmd_Exec(cp, &err);
+ Var_Set(line, res, ctxt);
+ free(res);
- /*
- * 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 (err)
+ Parse_Error(PARSE_WARNING, err, 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]);
- }
+ if (freeCmd)
+ free(cp);
} 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
@@ -1597,7 +1548,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
@@ -1681,17 +1632,20 @@ ParseDoInclude (file)
* leading path components and call Dir_FindFile to see if
* we can locate the beast.
*/
- char *prefEnd;
+ char *prefEnd, *Fname;
- prefEnd = strrchr (fname, '/');
+ /* Make a temporary copy of this, to be safe. */
+ Fname = estrdup(fname);
+
+ prefEnd = strrchr (Fname, '/');
if (prefEnd != (char *)NULL) {
char *newName;
-
+
*prefEnd = '\0';
if (file[0] == '/')
- newName = strdup(file);
+ newName = estrdup(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);
@@ -1701,6 +1655,7 @@ ParseDoInclude (file)
} else {
fullname = (char *)NULL;
}
+ free (Fname);
} else {
fullname = (char *)NULL;
}
@@ -1775,7 +1730,7 @@ ParseDoInclude (file)
*---------------------------------------------------------------------
* Parse_FromString --
* Start Parsing from the given string
- *
+ *
* Results:
* None
*
@@ -1798,14 +1753,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 = strdup(fname);
+ fname = estrdup(fname);
}
@@ -1814,7 +1769,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".
*
@@ -1877,7 +1832,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);
@@ -1997,7 +1952,7 @@ ParseEOF (opened)
/*-
*---------------------------------------------------------------------
* ParseReadc --
- * Read a character from the current file
+ * Read a character from the current file
*
* Results:
* The character that was read
@@ -2010,7 +1965,7 @@ ParseReadc()
{
if (curFILE)
return fgetc(curFILE);
-
+
if (curPTR && *curPTR->ptr)
return *curPTR->ptr++;
return EOF;
@@ -2020,7 +1975,7 @@ ParseReadc()
/*-
*---------------------------------------------------------------------
* ParseUnreadc --
- * Put back a character to the current file
+ * Put back a character to the current file
*
* Results:
* None.
@@ -2051,54 +2006,43 @@ ParseSkipLine(skip)
int skip; /* Skip lines that don't start with . */
{
char *line;
- int c, lastc = '\0', lineLength;
+ int c, lastc, lineLength = 0;
Buffer buf;
- c = ParseReadc();
+ buf = Buf_Init(MAKE_BSIZE);
- 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);
+ 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;
+ }
+
+ 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);
return line;
}
@@ -2164,11 +2108,11 @@ ParseReadLine ()
break;
}
}
-
+
if (c != EOF) {
lastc = c;
buf = Buf_Init(MAKE_BSIZE);
-
+
while (((c = ParseReadc ()) != '\n' || (lastc == '\\')) &&
(c != EOF))
{
@@ -2216,7 +2160,7 @@ test_char:
*/
ParseUnreadc('\t');
goto line_read;
- }
+ }
break;
case '=':
if (!semiNL) {
@@ -2242,7 +2186,11 @@ test_char:
break;
case '#':
if (!ignComment) {
- if (compatMake && (lastc != '\\')) {
+ if (
+#if 0
+ compatMake &&
+#endif
+ (lastc != '\\')) {
/*
* If the character is a hash mark and it isn't escaped
* (or we're being compatible), the thing is a comment.
@@ -2279,11 +2227,11 @@ test_char:
*/
Buf_AddByte (buf, (Byte)lastc);
lastc = c;
-
+
}
line_read:
lineno++;
-
+
if (lastc != '\0') {
Buf_AddByte (buf, (Byte)lastc);
}
@@ -2299,13 +2247,13 @@ test_char:
ep = line;
while (*ep)
++ep;
- while (ep > line && (ep[-1] == ' ' || ep[-1] == '\t')) {
+ while (ep > line + 1 && (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
@@ -2337,7 +2285,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;
}
@@ -2385,7 +2333,7 @@ ParseFinishLine()
inLine = FALSE;
}
}
-
+
/*-
*---------------------------------------------------------------------
@@ -2446,12 +2394,11 @@ Parse_File(name, stream)
goto nextLine;
}
}
- if (*line == '#' || *line == '\0') {
- /* If we're this far, the line must be a comment.
- (Empty lines are ignored as well) */
+ if (*line == '#') {
+ /* If we're this far, the line must be a comment. */
goto nextLine;
}
-
+
if (*line == '\t') {
/*
* If a line starts with a tab, it can only hope to be
@@ -2468,19 +2415,20 @@ 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 \"%.20s\"",
+ "Unassociated shell command \"%s\"",
cp);
}
}
#ifdef SYSVINCLUDE
- } else if (strncmp (line, "include", 7) == 0 &&
+ } else if (strncmp (line, "include", 7) == 0 &&
+ isspace((unsigned char) line[7]) &&
strchr(line, ':') == NULL) {
/*
* It's an S3/S5-style "include".
@@ -2505,7 +2453,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)) {
@@ -2521,7 +2469,7 @@ Parse_File(name, stream)
}
#endif
}
-
+
#ifndef POSIX
if (*cp == '\0') {
if (inLine) {
@@ -2538,16 +2486,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
}
@@ -2559,7 +2507,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);
@@ -2589,30 +2537,11 @@ 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
@@ -2625,7 +2554,7 @@ Parse_End()
Lst_Destroy(parseIncPath, Dir_Destroy);
Lst_Destroy(includes, NOFREE); /* Should be empty now */
}
-
+
/*-
*-----------------------------------------------------------------------
@@ -2649,7 +2578,7 @@ Parse_MainName()
main = Lst_Init (FALSE);
if (mainNode == NILGNODE) {
- Punt ("make: no target to make.\n");
+ Punt ("no target to make.");
/*NOTREACHED*/
} else if (mainNode->type & OP_DOUBLEDEP) {
(void) Lst_AtEnd (main, (ClientData)mainNode);
OpenPOWER on IntegriCloud