summaryrefslogtreecommitdiff
path: root/usr.bin/make/parse.c
diff options
context:
space:
mode:
authorcgd <cgd@NetBSD.org>1994-03-05 00:34:29 +0000
committercgd <cgd@NetBSD.org>1994-03-05 00:34:29 +0000
commit3db59563ee7dca190481dfee041222f12ed3a64f (patch)
treeee00f5ed3bf2662f98775537e76f6ba74977a1f6 /usr.bin/make/parse.c
parent3e02952c52fd23241dc58d7a0165a865dd508bcd (diff)
fixes/improvements from Christos Zoulas <christos@deshaw.com>.
Diffstat (limited to 'usr.bin/make/parse.c')
-rw-r--r--usr.bin/make/parse.c614
1 files changed, 478 insertions, 136 deletions
diff --git a/usr.bin/make/parse.c b/usr.bin/make/parse.c
index 2aff1048d40..a933a6262f9 100644
--- a/usr.bin/make/parse.c
+++ b/usr.bin/make/parse.c
@@ -37,8 +37,8 @@
*/
#ifndef lint
-/*static char sccsid[] = "from: @(#)parse.c 5.18 (Berkeley) 2/19/91";*/
-static char rcsid[] = "$Id: parse.c,v 1.4 1994/01/13 21:01:59 jtc Exp $";
+/* from: static char sccsid[] = "@(#)parse.c 5.18 (Berkeley) 2/19/91"; */
+static char *rcsid = "$Id: parse.c,v 1.5 1994/03/05 00:35:04 cgd Exp $";
#endif /* not lint */
/*-
@@ -81,13 +81,19 @@ static char rcsid[] = "$Id: parse.c,v 1.4 1994/01/13 21:01:59 jtc Exp $";
* Parse_MainName Returns a Lst of the main target to create.
*/
+#if __STDC__
+#include <stdarg.h>
+#else
#include <varargs.h>
-#include <ctype.h>
+#endif
#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
#include <sys/wait.h>
#include "make.h"
+#include "hash.h"
+#include "dir.h"
+#include "job.h"
#include "buf.h"
#include "pathnames.h"
@@ -98,15 +104,19 @@ static char rcsid[] = "$Id: parse.c,v 1.4 1994/01/13 21:01:59 jtc Exp $";
*/
#define CONTINUE 1
#define DONE 0
-static int ParseEOF();
-
static Lst targets; /* targets we're working on */
static Boolean inLine; /* true if currently in a dependency
* line or its commands */
+typedef struct {
+ char *str;
+ char *ptr;
+} PTR;
static char *fname; /* name of current file (for errors) */
static int lineno; /* line number in current file */
-static FILE *curFILE; /* current makefile */
+static FILE *curFILE = NULL; /* current makefile */
+
+static PTR *curPTR = NULL; /* current makefile */
static int fatals = 0;
@@ -119,8 +129,9 @@ static GNode *mainNode; /* The main target to create. This is the
typedef struct IFile {
char *fname; /* name of previous file */
int lineno; /* saved line number */
- FILE * F; /* the open stream */
-} IFile;
+ FILE * F; /* the open stream */
+ PTR * p; /* the char pointer */
+} IFile;
static Lst includes; /* stack of IFiles generated by
* #includes */
@@ -144,20 +155,21 @@ typedef enum {
MFlags, /* .MFLAGS or .MAKEFLAGS */
Main, /* .MAIN and we don't have anything user-specified to
* make */
+ NoExport, /* .NOEXPORT */
Not, /* Not special */
NotParallel, /* .NOTPARALELL */
Null, /* .NULL */
Order, /* .ORDER */
- Path, /* .PATH */
+ ExPath, /* .PATH */
Precious, /* .PRECIOUS */
- Shell, /* .SHELL */
+ ExShell, /* .SHELL */
Silent, /* .SILENT */
SingleShell, /* .SINGLESHELL */
Suffixes, /* .SUFFIXES */
- Attribute, /* Generic attribute */
+ Attribute /* Generic attribute */
} ParseSpecial;
-ParseSpecial specType;
+static ParseSpecial specType;
/*
* Predecessor node for handling .ORDER. Initialized to NILGNODE when .ORDER
@@ -196,16 +208,37 @@ static struct {
{ ".NOTPARALLEL", NotParallel, 0 },
{ ".NULL", Null, 0 },
{ ".ORDER", Order, 0 },
-{ ".PATH", Path, 0 },
+{ ".PATH", ExPath, 0 },
{ ".PRECIOUS", Precious, OP_PRECIOUS },
{ ".RECURSIVE", Attribute, OP_MAKE },
-{ ".SHELL", Shell, 0 },
+{ ".SHELL", ExShell, 0 },
{ ".SILENT", Silent, OP_SILENT },
{ ".SINGLESHELL", SingleShell, 0 },
{ ".SUFFIXES", Suffixes, 0 },
{ ".USE", Attribute, OP_USE },
};
+static int ParseFindKeyword __P((char *));
+static int ParseLinkSrc __P((GNode *, GNode *));
+static int ParseDoOp __P((GNode *, int));
+static void ParseDoSrc __P((int, char *));
+static int ParseFindMain __P((GNode *));
+static int ParseAddDir __P((Lst, char *));
+static int ParseClearPath __P((Lst));
+static void ParseDoDependency __P((char *));
+static int ParseAddCmd __P((GNode *, char *));
+static int ParseReadc __P((void));
+static void ParseUnreadc __P((int));
+static int ParseHasCommands __P((GNode *));
+static void ParseDoInclude __P((char *));
+#ifdef SYSVINCLUDE
+static void ParseTraditionalInclude __P((char *));
+#endif
+static int ParseEOF __P((int));
+static char *ParseReadLine __P((void));
+static char *ParseSkipLine __P((int));
+static void ParseFinishLine __P((void));
+
/*-
*----------------------------------------------------------------------
* ParseFindKeyword --
@@ -259,18 +292,28 @@ ParseFindKeyword (str)
*/
/* VARARGS */
void
-Parse_Error(type, va_alist)
- int type; /* Error type (PARSE_WARNING, PARSE_FATAL) */
+#if __STDC__
+Parse_Error(int type, char *fmt, ...)
+#else
+Parse_Error(va_alist)
va_dcl
+#endif
{
va_list ap;
+#if __STDC__
+ va_start(ap, fmt);
+#else
+ int type; /* Error type (PARSE_WARNING, PARSE_FATAL) */
char *fmt;
+ va_start(ap);
+ type = va_arg(ap, int);
+ fmt = va_arg(ap, char *);
+#endif
+
(void)fprintf(stderr, "\"%s\", line %d: ", fname, lineno);
if (type == PARSE_WARNING)
(void)fprintf(stderr, "warning: ");
- va_start(ap);
- fmt = va_arg(ap, char *);
(void)vfprintf(stderr, fmt, ap);
va_end(ap);
(void)fprintf(stderr, "\n");
@@ -678,7 +721,7 @@ ParseDoDependency (line)
*/
int keywd = ParseFindKeyword(line);
if (keywd != -1) {
- if (specType == Path && parseKeywords[keywd].spec != Path) {
+ if (specType == ExPath && parseKeywords[keywd].spec != ExPath) {
Parse_Error(PARSE_FATAL, "Mismatched special targets");
return;
}
@@ -714,7 +757,7 @@ ParseDoDependency (line)
* .ORDER Must set initial predecessor to NIL
*/
switch (specType) {
- case Path:
+ case ExPath:
if (paths == NULL) {
paths = Lst_Init(FALSE);
}
@@ -746,11 +789,13 @@ ParseDoDependency (line)
break;
}
case SingleShell:
- /* backwards = 1; */
+ compatMake = 1;
break;
case Order:
predecessor = NILGNODE;
break;
+ default:
+ break;
}
} else if (strncmp (line, ".PATH", 5) == 0) {
/*
@@ -760,7 +805,7 @@ ParseDoDependency (line)
*/
Lst path;
- specType = Path;
+ specType = ExPath;
path = Suff_GetPath (&line[5]);
if (path == NILLST) {
Parse_Error (PARSE_FATAL,
@@ -812,7 +857,7 @@ ParseDoDependency (line)
(void)Lst_AtEnd (targets, (ClientData)gn);
}
- } else if (specType == Path && *line != '.' && *line != '\0') {
+ } else if (specType == ExPath && *line != '.' && *line != '\0') {
Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line);
}
@@ -821,7 +866,7 @@ ParseDoDependency (line)
* If it is a special type and not .PATH, it's the only target we
* allow on this line...
*/
- if (specType != Not && specType != Path) {
+ if (specType != Not && specType != ExPath) {
Boolean warn = FALSE;
while ((*cp != '!') && (*cp != ':') && *cp) {
@@ -920,9 +965,11 @@ ParseDoDependency (line)
case Silent:
beSilent = TRUE;
break;
- case Path:
+ case ExPath:
Lst_ForEach(paths, ParseClearPath, (ClientData)NULL);
break;
+ default:
+ break;
}
} else if (specType == MFlags) {
/*
@@ -932,7 +979,7 @@ ParseDoDependency (line)
*/
Main_ParseArgLine (line);
*line = '\0';
- } else if (specType == Shell) {
+ } else if (specType == ExShell) {
if (Job_ParseShell (line) != SUCCESS) {
Parse_Error (PARSE_FATAL, "improper shell specification");
return;
@@ -945,7 +992,7 @@ ParseDoDependency (line)
/*
* NOW GO FOR THE SOURCES
*/
- if ((specType == Suffixes) || (specType == Path) ||
+ if ((specType == Suffixes) || (specType == ExPath) ||
(specType == Includes) || (specType == Libs) ||
(specType == Null))
{
@@ -984,7 +1031,7 @@ ParseDoDependency (line)
case Suffixes:
Suff_AddSuffix (line);
break;
- case Path:
+ case ExPath:
Lst_ForEach(paths, ParseAddDir, (ClientData)line);
break;
case Includes:
@@ -996,6 +1043,8 @@ ParseDoDependency (line)
case Null:
Suff_SetNull (line);
break;
+ default:
+ break;
}
*cp = savec;
if (savec != '\0') {
@@ -1259,13 +1308,12 @@ Parse_DoVar (line, ctxt)
Boolean oldOldVars = oldVars;
oldVars = FALSE;
- cp = Var_Subst(cp, ctxt, FALSE);
+ cp = Var_Subst(NULL, cp, ctxt, FALSE);
oldVars = oldOldVars;
Var_Set(line, cp, ctxt);
free(cp);
} else if (type == VAR_SHELL) {
- char result[BUFSIZ]; /* Result of command */
char *args[4]; /* Args for invoking the shell */
int fds[2]; /* Pipe streams */
int cpid; /* Child PID */
@@ -1273,18 +1321,19 @@ Parse_DoVar (line, ctxt)
Boolean freeCmd; /* TRUE if the command needs to be freed, i.e.
* if any variable expansion was performed */
+
/*
* Set up arguments for shell
*/
args[0] = "sh";
args[1] = "-c";
- if (index(cp, '$') != (char *)NULL) {
+ 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.
*/
- args[2] = Var_Subst(cp, VAR_CMD, TRUE);
+ args[2] = Var_Subst(NULL, cp, VAR_CMD, TRUE);
freeCmd = TRUE;
} else {
args[2] = cp;
@@ -1326,34 +1375,44 @@ Parse_DoVar (line, ctxt)
} else {
int status;
int cc;
+ Buffer buf;
+ char *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, (unsigned char *) result);
+ }
+ while (cc > 0 || (cc == -1 && errno == EINTR));
+
/*
- * Wait for the process to exit.
- *
- * XXX: If the child writes more than a pipe's worth, we will
- * deadlock.
+ * Close the input side of the pipe.
*/
- while(((pid = wait(&status)) != cpid) && (pid >= 0)) {
- ;
- }
+ close(fds[0]);
/*
- * Read all the characters the child wrote.
+ * Wait for the process to exit.
*/
- cc = read(fds[0], result, sizeof(result));
+ while(((pid = wait(&status)) != cpid) && (pid >= 0))
+ continue;
+
+ res = (char *)Buf_GetAll (buf, &cc);
+ Buf_Destroy (buf, FALSE);
- if (cc < 0) {
+ 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");
- cc = 0;
}
if (status) {
@@ -1363,12 +1422,13 @@ Parse_DoVar (line, ctxt)
*/
Parse_Error(PARSE_WARNING, "\"%s\" returned non-zero", cp);
}
+
/*
* Null-terminate the result, convert newlines to spaces and
* install it in the variable.
*/
- result[cc] = '\0';
- cp = &result[cc] - 1;
+ res[cc] = '\0';
+ cp = &res[cc] - 1;
if (*cp == '\n') {
/*
@@ -1376,18 +1436,15 @@ Parse_DoVar (line, ctxt)
*/
*cp-- = '\0';
}
- while (cp >= result) {
+ while (cp >= res) {
if (*cp == '\n') {
*cp = ' ';
}
cp--;
}
- Var_Set(line, result, ctxt);
+ Var_Set(line, res, ctxt);
+ free(res);
- /*
- * Close the input side of the pipe.
- */
- close(fds[0]);
}
if (freeCmd) {
free(args[2]);
@@ -1410,7 +1467,7 @@ Parse_DoVar (line, ctxt)
* Side Effects:
* A new element is added to the commands list of the node.
*/
-static
+static int
ParseAddCmd(gn, cmd)
GNode *gn; /* the node to which the command is to be added */
char *cmd; /* the command to add */
@@ -1492,7 +1549,6 @@ ParseDoInclude (file)
{
char *fullname; /* full pathname of file */
IFile *oldFile; /* state associated with current file */
- Lst path; /* the path to use to find the file */
char endc; /* the character which ends the file spec */
char *cp; /* current position in file spec */
Boolean isSystem; /* TRUE if makefile is a system makefile */
@@ -1532,7 +1588,8 @@ ParseDoInclude (file)
if (*cp != endc) {
Parse_Error (PARSE_FATAL,
- "Unclosed .include filename. '%c' expected", endc);
+ "Unclosed %cinclude filename. '%c' expected",
+ '.', endc);
return;
}
*cp = '\0';
@@ -1541,7 +1598,7 @@ ParseDoInclude (file)
* Substitute for any variables in the file name before trying to
* find the thing.
*/
- file = Var_Subst (file, VAR_CMD, FALSE);
+ file = Var_Subst (NULL, file, VAR_CMD, FALSE);
/*
* Now we know the file's name and its search path, we attempt to
@@ -1558,7 +1615,7 @@ ParseDoInclude (file)
*/
char *prefEnd;
- prefEnd = rindex (fname, '/');
+ prefEnd = strrchr (fname, '/');
if (prefEnd != (char *)NULL) {
char *newName;
@@ -1615,6 +1672,7 @@ ParseDoInclude (file)
oldFile->fname = fname;
oldFile->F = curFILE;
+ oldFile->p = curPTR;
oldFile->lineno = lineno;
(void) Lst_AtFront (includes, (ClientData)oldFile);
@@ -1629,6 +1687,7 @@ ParseDoInclude (file)
lineno = 0;
curFILE = fopen (fullname, "r");
+ curPTR = NULL;
if (curFILE == (FILE * ) NULL) {
Parse_Error (PARSE_FATAL, "Cannot open %s", fullname);
/*
@@ -1638,6 +1697,189 @@ ParseDoInclude (file)
}
}
+
+/*-
+ *---------------------------------------------------------------------
+ * Parse_FromString --
+ * Start Parsing from the given string
+ *
+ * Results:
+ * None
+ *
+ * Side Effects:
+ * A structure is added to the includes Lst and readProc, lineno,
+ * fname and curFILE are altered for the new file
+ *---------------------------------------------------------------------
+ */
+void
+Parse_FromString(str)
+ char *str;
+{
+ IFile *oldFile; /* state associated with this file */
+
+ if (DEBUG(FOR))
+ (void) fprintf(stderr, "%s\n----\n", str);
+
+ oldFile = (IFile *) emalloc (sizeof (IFile));
+ oldFile->lineno = lineno;
+ 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);
+}
+
+
+#ifdef SYSVINCLUDE
+/*-
+ *---------------------------------------------------------------------
+ * ParseTraditionalInclude --
+ * Push to another file.
+ *
+ * The input is the line minus the "include". The file name is
+ * the string following the "include".
+ *
+ * Results:
+ * None
+ *
+ * Side Effects:
+ * A structure is added to the includes Lst and readProc, lineno,
+ * fname and curFILE are altered for the new file
+ *---------------------------------------------------------------------
+ */
+static void
+ParseTraditionalInclude (file)
+ char *file; /* file specification */
+{
+ char *fullname; /* full pathname of file */
+ IFile *oldFile; /* state associated with current file */
+ char *cp; /* current position in file spec */
+ char *prefEnd;
+
+ /*
+ * Skip over whitespace
+ */
+ while ((*file == ' ') || (*file == '\t')) {
+ file++;
+ }
+
+ if (*file == '\0') {
+ Parse_Error (PARSE_FATAL,
+ "Filename missing from \"include\"");
+ return;
+ }
+
+ /*
+ * Skip to end of line or next whitespace
+ */
+ for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) {
+ continue;
+ }
+
+ *cp = '\0';
+
+ /*
+ * Substitute for any variables in the file name before trying to
+ * find the thing.
+ */
+ file = Var_Subst (NULL, file, VAR_CMD, FALSE);
+
+ /*
+ * Now we know the file's name, we attempt to find the durn thing.
+ * A return of NULL indicates the file don't exist.
+ *
+ * Include files are first searched for relative to the including
+ * file's location. We don't want to cd there, of course, so we
+ * just tack on the old file's leading path components and call
+ * Dir_FindFile to see if we can locate the beast.
+ * XXX - this *does* search in the current directory, right?
+ */
+
+ prefEnd = strrchr (fname, '/');
+ if (prefEnd != (char *)NULL) {
+ char *newName;
+
+ *prefEnd = '\0';
+ newName = str_concat (fname, file, STR_ADDSLASH);
+ fullname = Dir_FindFile (newName, parseIncPath);
+ if (fullname == (char *)NULL) {
+ fullname = Dir_FindFile(newName, dirSearchPath);
+ }
+ free (newName);
+ *prefEnd = '/';
+ } else {
+ fullname = (char *)NULL;
+ }
+
+ if (fullname == (char *)NULL) {
+ /*
+ * System makefile or makefile wasn't found in same directory as
+ * included makefile. Search for it first on the -I search path,
+ * then on the .PATH search path, if not found in a -I directory.
+ * XXX: Suffix specific?
+ */
+ fullname = Dir_FindFile (file, parseIncPath);
+ if (fullname == (char *)NULL) {
+ fullname = Dir_FindFile(file, dirSearchPath);
+ }
+ }
+
+ if (fullname == (char *)NULL) {
+ /*
+ * Still haven't found the makefile. Look for it on the system
+ * path as a last resort.
+ */
+ fullname = Dir_FindFile(file, sysIncPath);
+ }
+
+ if (fullname == (char *) NULL) {
+ Parse_Error (PARSE_FATAL, "Could not find %s", file);
+ return;
+ }
+
+ /*
+ * Once we find the absolute path to the file, we get to save all the
+ * state from the current file before we can start reading this
+ * include file. The state is stored in an IFile structure which
+ * is placed on a list with other IFile structures. The list makes
+ * a very nice stack to track how we got here...
+ */
+ oldFile = (IFile *) emalloc (sizeof (IFile));
+ oldFile->fname = fname;
+
+ oldFile->F = curFILE;
+ oldFile->p = curPTR;
+ oldFile->lineno = lineno;
+
+ (void) Lst_AtFront (includes, (ClientData)oldFile);
+
+ /*
+ * Once the previous state has been saved, we can get down to reading
+ * the new file. We set up the name of the file to be the absolute
+ * name of the include file so error messages refer to the right
+ * place. Naturally enough, we start reading at line number 0.
+ */
+ fname = fullname;
+ lineno = 0;
+
+ curFILE = fopen (fullname, "r");
+ curPTR = NULL;
+ if (curFILE == (FILE * ) NULL) {
+ Parse_Error (PARSE_FATAL, "Cannot open %s", fullname);
+ /*
+ * Pop to previous file
+ */
+ (void) ParseEOF(1);
+ }
+}
+#endif
+
/*-
*---------------------------------------------------------------------
* ParseEOF --
@@ -1664,12 +1906,17 @@ ParseEOF (opened)
}
ifile = (IFile *) Lst_DeQueue (includes);
- free (fname);
+ free ((Address) fname);
fname = ifile->fname;
lineno = ifile->lineno;
- if (opened)
+ if (opened && curFILE)
(void) fclose (curFILE);
+ if (curPTR) {
+ free((Address) curPTR->str);
+ free((Address) curPTR);
+ }
curFILE = ifile->F;
+ curPTR = ifile->p;
free ((Address)ifile);
return (CONTINUE);
}
@@ -1677,24 +1924,110 @@ ParseEOF (opened)
/*-
*---------------------------------------------------------------------
* ParseReadc --
- * Read a character from the current file and update the line number
- * counter as necessary
+ * Read a character from the current file
*
* Results:
* The character that was read
*
* Side Effects:
- * The lineno counter is incremented if the character is a newline
*---------------------------------------------------------------------
*/
-#ifdef notdef
-static int parseReadChar;
+static int
+ParseReadc()
+{
+ if (curFILE)
+ return fgetc(curFILE);
+
+ if (curPTR && *curPTR->ptr)
+ return *curPTR->ptr++;
+ return EOF;
+}
-#define ParseReadc() (((parseReadChar = getc(curFILE)) == '\n') ? \
- (lineno++, '\n') : parseReadChar)
-#else
-#define ParseReadc() (getc(curFILE))
-#endif /* notdef */
+
+/*-
+ *---------------------------------------------------------------------
+ * ParseUnreadc --
+ * Put back a character to the current file
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ *---------------------------------------------------------------------
+ */
+static void
+ParseUnreadc(c)
+ int c;
+{
+ if (curFILE) {
+ ungetc(c, curFILE);
+ return;
+ }
+ if (curPTR) {
+ *--(curPTR->ptr) = c;
+ return;
+ }
+}
+
+
+/* ParseSkipLine():
+ * Grab the next line
+ */
+static char *
+ParseSkipLine(skip)
+ int skip; /* Skip lines that don't start with . */
+{
+ char *line;
+ int c, lastc = '\0', lineLength;
+ Buffer buf;
+
+ c = ParseReadc();
+
+ 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;
+}
/*-
@@ -1739,20 +2072,17 @@ ParseReadLine ()
* semi-colons as semi-colons (by leaving semiNL FALSE). This also
* discards completely blank lines.
*/
- while(1) {
+ for (;;) {
c = ParseReadc();
if (c == '\t') {
ignComment = ignDepOp = TRUE;
break;
- } else if (c == '.') {
- ignComment = TRUE;
- break;
} else if (c == '\n') {
lineno++;
} else if (c == '#') {
- ungetc(c, curFILE);
- break;
+ ParseUnreadc(c);
+ break;
} else {
/*
* Anything else breaks out without doing anything
@@ -1763,7 +2093,7 @@ ParseReadLine ()
if (c != EOF) {
lastc = c;
- buf = Buf_Init(BSIZE);
+ buf = Buf_Init(MAKE_BSIZE);
while (((c = ParseReadc ()) != '\n' || (lastc == '\\')) &&
(c != EOF))
@@ -1789,11 +2119,13 @@ test_char:
} else {
/*
* Check for comments, semiNL's, etc. -- easier than
- * ungetc(c, curFILE); continue;
+ * ParseUnreadc(c); continue;
*/
goto test_char;
}
+ /*NOTREACHED*/
break;
+
case ';':
/*
* Semi-colon: Need to see if it should be interpreted as a
@@ -1808,7 +2140,7 @@ test_char:
* harm, since the newline remains in the buffer and the
* whole line is ignored.
*/
- ungetc('\t', curFILE);
+ ParseUnreadc('\t');
goto line_read;
}
break;
@@ -1836,6 +2168,7 @@ test_char:
break;
case '#':
if (!ignComment) {
+ 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.
@@ -1845,6 +2178,14 @@ test_char:
c = ParseReadc();
} while ((c != '\n') && (c != EOF));
goto line_read;
+ } else {
+ /*
+ * Don't add the backslash. Just let the # get copied
+ * over.
+ */
+ lastc = c;
+ continue;
+ }
}
break;
case ':':
@@ -1883,62 +2224,47 @@ test_char:
*/
switch (Cond_Eval (line)) {
case COND_SKIP:
+ /*
+ * Skip to next conditional that evaluates to COND_PARSE.
+ */
do {
- /*
- * Skip to next conditional that evaluates to COND_PARSE.
- */
free (line);
- c = ParseReadc();
- /*
- * 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");
- return ((char *)NULL);
- }
-
- /*
- * Read the entire line into buf
- */
- buf = Buf_Init (BSIZE);
- 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);
- } while (Cond_Eval(line) != COND_PARSE);
+ line = ParseSkipLine(1);
+ } while (line && Cond_Eval(line) != COND_PARSE);
+ if (line == NULL)
+ break;
/*FALLTHRU*/
case COND_PARSE:
- free (line);
+ free ((Address) line);
line = ParseReadLine();
break;
+ case COND_INVALID:
+ if (For_Eval(line)) {
+ int ok;
+ free(line);
+ do {
+ /*
+ * Skip after the matching end
+ */
+ line = ParseSkipLine(0);
+ if (line == NULL) {
+ Parse_Error (PARSE_FATAL,
+ "Unexpected end of file in for loop.\n");
+ break;
+ }
+ ok = For_Eval(line);
+ free(line);
+ }
+ while (ok);
+ if (line != NULL)
+ For_Run();
+ line = ParseReadLine();
+ }
+ break;
}
}
-
return (line);
+
} else {
/*
* Hit end-of-file, so return a NULL line to indicate this.
@@ -2003,7 +2329,7 @@ Parse_File(name, stream)
fatals = 0;
do {
- while (line = ParseReadLine ()) {
+ while ((line = ParseReadLine ()) != NULL) {
if (*line == '.') {
/*
* Lines that begin with the special character are either
@@ -2036,10 +2362,15 @@ Parse_File(name, stream)
goto nextLine;
}
- if (*line == '\t') {
+ if (*line == '\t'
+#ifdef POSIX
+ || *line == ' '
+#endif
+ )
+ {
/*
- * If a line starts with a tab, it can only hope to be
- * a creation command.
+ * If a line starts with a tab (or space in POSIX-land), it
+ * can only hope to be a creation command.
*/
shellCommand:
for (cp = line + 1; isspace (*cp); cp++) {
@@ -2060,6 +2391,15 @@ Parse_File(name, stream)
cp);
}
}
+#ifdef SYSVINCLUDE
+ } else if (strncmp (line, "include", 7) == 0 &&
+ strchr(line, ':') == NULL) {
+ /*
+ * It's an S3/S5-style "include".
+ */
+ ParseTraditionalInclude (line + 7);
+ goto nextLine;
+#endif
} else if (Parse_IsVar (line)) {
ParseFinishLine();
Parse_DoVar (line, VAR_GLOBAL);
@@ -2103,7 +2443,7 @@ Parse_File(name, stream)
#endif
ParseFinishLine();
- cp = Var_Subst (line, VAR_CMD, TRUE);
+ cp = Var_Subst (NULL, line, VAR_CMD, TRUE);
free (line);
line = cp;
@@ -2151,9 +2491,10 @@ Parse_File(name, stream)
* the parseIncPath list is initialized...
*---------------------------------------------------------------------
*/
+void
Parse_Init ()
{
- char *cp, *start;
+ char *cp = NULL, *start;
/* avoid faults on read-only strings */
static char syspath[] = _PATH_DEFSYSPATH;
@@ -2167,9 +2508,8 @@ Parse_Init ()
* as dir1:...:dirn) to the system include path.
*/
for (start = syspath; *start != '\0'; start = cp) {
- for (cp = start; *cp != '\0' && *cp != ':'; cp++) {
- ;
- }
+ for (cp = start; *cp != '\0' && *cp != ':'; cp++)
+ continue;
if (*cp == '\0') {
Dir_AddDir(sysIncPath, start);
} else {
@@ -2204,8 +2544,10 @@ Parse_MainName()
Punt ("make: no target to make.\n");
/*NOTREACHED*/
} else if (mainNode->type & OP_DOUBLEDEP) {
+ (void) Lst_AtEnd (main, (ClientData)mainNode);
Lst_Concat(main, mainNode->cohorts, LST_CONCNEW);
}
- (void) Lst_AtEnd (main, (ClientData)mainNode);
+ else
+ (void) Lst_AtEnd (main, (ClientData)mainNode);
return (main);
}