diff options
| author | cgd <cgd@NetBSD.org> | 1994-03-05 00:34:29 +0000 |
|---|---|---|
| committer | cgd <cgd@NetBSD.org> | 1994-03-05 00:34:29 +0000 |
| commit | 3db59563ee7dca190481dfee041222f12ed3a64f (patch) | |
| tree | ee00f5ed3bf2662f98775537e76f6ba74977a1f6 /usr.bin/make/parse.c | |
| parent | 3e02952c52fd23241dc58d7a0165a865dd508bcd (diff) | |
fixes/improvements from Christos Zoulas <christos@deshaw.com>.
Diffstat (limited to 'usr.bin/make/parse.c')
| -rw-r--r-- | usr.bin/make/parse.c | 614 |
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); } |
