diff options
Diffstat (limited to 'usr.bin/make/parse.c')
-rw-r--r-- | usr.bin/make/parse.c | 651 |
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); |