diff options
Diffstat (limited to 'usr.bin/make/parse.c')
-rw-r--r-- | usr.bin/make/parse.c | 257 |
1 files changed, 176 insertions, 81 deletions
diff --git a/usr.bin/make/parse.c b/usr.bin/make/parse.c index a6a085a..e4d8446 100644 --- a/usr.bin/make/parse.c +++ b/usr.bin/make/parse.c @@ -37,7 +37,7 @@ */ #ifndef lint -static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94"; +static char sccsid[] = "@(#)parse.c 8.6 (Berkeley) 6/13/95"; #endif /* not lint */ /*- @@ -63,6 +63,8 @@ static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94"; * called before anything else in this module * is used. * + * Parse_End Cleanup the module + * * Parse_File Function used to parse a makefile. It must * be given the name of the file, which should * already have been opened, and a function @@ -104,6 +106,7 @@ static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94"; #define CONTINUE 1 #define DONE 0 static Lst targets; /* targets we're working on */ +static Lst targCmds; /* command lines for targets */ static Boolean inLine; /* true if currently in a dependency * line or its commands */ typedef struct { @@ -161,6 +164,7 @@ typedef enum { Order, /* .ORDER */ ExPath, /* .PATH */ Precious, /* .PRECIOUS */ + Reserved, /* .RESERVED or .[A-Z]* */ ExShell, /* .SHELL */ Silent, /* .SILENT */ SingleShell, /* .SINGLESHELL */ @@ -188,47 +192,78 @@ 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 }, -{ ".OPTIONAL", Attribute, OP_OPTIONAL }, +#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 { ".NULL", Null, 0 }, +#define DOT_OPTIONAL 17 +{ ".OPTIONAL", Attribute, OP_OPTIONAL }, +#define DOT_ORDER 18 { ".ORDER", Order, 0 }, +#define DOT_PATH 19 { ".PATH", ExPath, 0 }, +#define DOT_PHONY 20 +{ ".PHONY", Attribute, OP_PHONY }, +#define DOT_PRECIOUS 21 { ".PRECIOUS", Precious, OP_PRECIOUS }, +#define DOT_RECURSIVE 22 { ".RECURSIVE", Attribute, OP_MAKE }, +#define DOT_RESERVED 23 +{ ".RESERVED", Reserved, 0 }, +#define DOT_SHELL 24 { ".SHELL", ExShell, 0 }, +#define DOT_SILENT 25 { ".SILENT", Silent, OP_SILENT }, +#define DOT_SINGLESHELL 26 { ".SINGLESHELL", SingleShell, 0 }, +#define DOT_SUFFIXES 27 { ".SUFFIXES", Suffixes, 0 }, +#define DOT_USE 28 { ".USE", Attribute, OP_USE }, }; static int ParseFindKeyword __P((char *)); -static int ParseLinkSrc __P((GNode *, GNode *)); -static int ParseDoOp __P((GNode *, int)); +static int ParseLinkSrc __P((ClientData, ClientData)); +static int ParseDoOp __P((ClientData, ClientData)); static void ParseDoSrc __P((int, char *)); -static int ParseFindMain __P((GNode *)); -static int ParseAddDir __P((Lst, char *)); -static int ParseClearPath __P((Lst)); +static int ParseFindMain __P((ClientData, ClientData)); +static int ParseAddDir __P((ClientData, ClientData)); +static int ParseClearPath __P((ClientData, ClientData)); static void ParseDoDependency __P((char *)); -static int ParseAddCmd __P((GNode *, char *)); +static int ParseAddCmd __P((ClientData, ClientData)); static int ParseReadc __P((void)); static void ParseUnreadc __P((int)); -static int ParseHasCommands __P((GNode *)); +static void ParseHasCommands __P((ClientData)); static void ParseDoInclude __P((char *)); #ifdef SYSVINCLUDE static void ParseTraditionalInclude __P((char *)); @@ -274,7 +309,12 @@ ParseFindKeyword (str) start = cur + 1; } } while (start <= end); - return (-1); + + cur = 0; + for (++str; *str; str++) + if (!isupper((unsigned char) *str)) + break; + return *str ? -1 : DOT_RESERVED; } /*- @@ -292,7 +332,7 @@ ParseFindKeyword (str) /* VARARGS */ void #if __STDC__ -Parse_Error(int type, const char *fmt, ...) +Parse_Error(int type, char *fmt, ...) #else Parse_Error(va_alist) va_dcl @@ -338,10 +378,12 @@ Parse_Error(va_alist) *--------------------------------------------------------------------- */ static int -ParseLinkSrc (pgn, cgn) - GNode *pgn; /* The parent node */ - GNode *cgn; /* The child node */ +ParseLinkSrc (pgnp, cgnp) + ClientData pgnp; /* The parent node */ + ClientData cgnp; /* The child node */ { + GNode *pgn = (GNode *) pgnp; + GNode *cgn = (GNode *) cgnp; if (Lst_Member (pgn->children, (ClientData)cgn) == NILLNODE) { (void)Lst_AtEnd (pgn->children, (ClientData)cgn); if (specType == Not) { @@ -369,11 +411,13 @@ ParseLinkSrc (pgn, cgn) *--------------------------------------------------------------------- */ static int -ParseDoOp (gn, op) - GNode *gn; /* The node to which the operator is to be +ParseDoOp (gnp, opp) + ClientData gnp; /* The node to which the operator is to be * applied */ - int op; /* The operator to apply */ + ClientData opp; /* The operator to apply */ { + GNode *gn = (GNode *) gnp; + int op = *(int *) 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 @@ -461,7 +505,7 @@ ParseDoSrc (tOp, src) } } if (op != 0) { - Lst_ForEach (targets, ParseDoOp, (ClientData)op); + Lst_ForEach (targets, ParseDoOp, (ClientData)&op); } else if (specType == Main) { /* * If we have noted the existence of a .MAIN, it means we need @@ -541,15 +585,17 @@ ParseDoSrc (tOp, src) *----------------------------------------------------------------------- */ static int -ParseFindMain(gn) - GNode *gn; /* Node to examine */ +ParseFindMain(gnp, dummy) + ClientData gnp; /* Node to examine */ + ClientData dummy; { + GNode *gn = (GNode *) gnp; if ((gn->type & (OP_NOTMAIN|OP_USE|OP_EXEC|OP_TRANSFORM)) == 0) { mainNode = gn; Targ_SetMain(gn); - return (1); + return (dummy ? 1 : 1); } else { - return (0); + return (dummy ? 0 : 0); } } @@ -568,10 +614,10 @@ ParseFindMain(gn) */ static int ParseAddDir(path, name) - Lst path; - char *name; + ClientData path; + ClientData name; { - Dir_AddDir(path, name); + Dir_AddDir((Lst) path, (char *) name); return(0); } @@ -589,11 +635,12 @@ ParseAddDir(path, name) *----------------------------------------------------------------------- */ static int -ParseClearPath(path) - Lst path; +ParseClearPath(path, dummy) + ClientData path; + ClientData dummy; { - Dir_ClearPath(path); - return(0); + Dir_ClearPath((Lst) path); + return(dummy ? 0 : 0); } /*- @@ -634,9 +681,9 @@ static void ParseDoDependency (line) char *line; /* the line to parse */ { - register char *cp; /* our current position */ - register GNode *gn; /* a general purpose temporary node */ - register int op; /* the operator on the line */ + char *cp; /* our current position */ + GNode *gn; /* a general purpose temporary node */ + int op; /* the operator on the line */ char savec; /* a place to save a character */ Lst paths; /* List of search paths to alter when parsing * a list of .PATH targets */ @@ -793,6 +840,12 @@ ParseDoDependency (line) case Order: predecessor = NILGNODE; break; + case Reserved: + /* + * A posix reserved target that we don't know + * how to deal with. + */ + return; default: break; } @@ -931,7 +984,7 @@ ParseDoDependency (line) cp++; /* Advance beyond operator */ - Lst_ForEach (targets, ParseDoOp, (ClientData)op); + Lst_ForEach (targets, ParseDoOp, (ClientData)&op); /* * Get to the first source @@ -1225,20 +1278,20 @@ Parse_DoVar (line, ctxt) * assignment. This reduces error checks */ GNode *ctxt; /* Context in which to do the assignment */ { - char *cp; /* pointer into line */ + char *cp; /* pointer into line */ enum { VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL } type; /* Type of assignment */ char *opc; /* ptr to operator character to * null-terminate the variable name */ - /* + /* * Avoid clobbered variable warnings by forcing the compiler * to ``unregister'' variables - */ + */ #if __GNUC__ - (void) &cp; - (void) &line; -#endif + (void) &cp; + (void) &line; +#endif /* * Skip to variable name @@ -1328,13 +1381,14 @@ Parse_DoVar (line, ctxt) 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 +#endif + /* * Set up arguments for shell */ @@ -1402,7 +1456,7 @@ Parse_DoVar (line, ctxt) char result[BUFSIZ]; cc = read(fds[0], result, sizeof(result)); if (cc > 0) - Buf_AddBytes(buf, cc, (unsigned char *) result); + Buf_AddBytes(buf, cc, (Byte *) result); } while (cc > 0 || (cc == -1 && errno == EINTR)); @@ -1481,14 +1535,15 @@ Parse_DoVar (line, ctxt) * A new element is added to the commands list of the node. */ static int -ParseAddCmd(gn, cmd) - GNode *gn; /* the node to which the command is to be added */ - char *cmd; /* the command to add */ +ParseAddCmd(gnp, cmd) + ClientData gnp; /* the node to which the command is to be added */ + ClientData cmd; /* the command to add */ { - /* if target already supplied, ignore commands */ - if (!(gn->type & OP_HAS_COMMANDS)) - (void)Lst_AtEnd(gn->commands, (ClientData)cmd); - return(0); + GNode *gn = (GNode *) gnp; + /* if target already supplied, ignore commands */ + if (!(gn->type & OP_HAS_COMMANDS)) + (void)Lst_AtEnd(gn->commands, cmd); + return(0); } /*- @@ -1500,21 +1555,21 @@ ParseAddCmd(gn, cmd) * on multiple dependency lines. * * Results: - * Always 0. + * None * * Side Effects: * OP_HAS_COMMANDS may be set for the target. * *----------------------------------------------------------------------- */ -static int -ParseHasCommands(gn) - GNode *gn; /* Node to examine */ +static void +ParseHasCommands(gnp) + ClientData gnp; /* Node to examine */ { + GNode *gn = (GNode *) gnp; if (!Lst_IsEmpty(gn->commands)) { gn->type |= OP_HAS_COMMANDS; } - return(0); } /*- @@ -1633,7 +1688,10 @@ ParseDoInclude (file) char *newName; *prefEnd = '\0'; - newName = str_concat (fname, file, STR_ADDSLASH); + if (file[0] == '/') + newName = strdup(file); + else + newName = str_concat (fname, file, STR_ADDSLASH); fullname = Dir_FindFile (newName, parseIncPath); if (fullname == (char *)NULL) { fullname = Dir_FindFile(newName, dirSearchPath); @@ -1674,6 +1732,8 @@ ParseDoInclude (file) return; } + free(file); + /* * 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 @@ -2071,7 +2131,8 @@ ParseReadLine () * for the purposes of setting semiNL */ Boolean ignComment; /* TRUE if should ignore comments (in a * shell command */ - char *line; /* Result */ + char *line; /* Result */ + char *ep; /* to strip trailing blanks */ int lineLength; /* Length of result */ semiNL = FALSE; @@ -2181,7 +2242,7 @@ test_char: break; case '#': if (!ignComment) { - if (compatMake || (lastc != '\\')) { + if (compatMake && (lastc != '\\')) { /* * If the character is a hash mark and it isn't escaped * (or we're being compatible), the thing is a comment. @@ -2229,6 +2290,21 @@ test_char: Buf_AddByte (buf, (Byte)'\0'); line = (char *)Buf_GetAll (buf, &lineLength); Buf_Destroy (buf, FALSE); + + /* + * Strip trailing blanks and tabs from the line. + * Do not strip a blank or tab that is preceeded by + * a '\' + */ + ep = line; + while (*ep) + ++ep; + while (ep > line && (ep[-1] == ' ' || ep[-1] == '\t')) { + if (ep > line + 1 && ep[-2] == '\\') + break; + --ep; + } + *ep = 0; if (line[0] == '.') { /* @@ -2302,11 +2378,10 @@ test_char: static void ParseFinishLine() { - extern int Suff_EndTransform(); - if (inLine) { Lst_ForEach(targets, Suff_EndTransform, (ClientData)NULL); Lst_Destroy (targets, ParseHasCommands); + targets = NULL; inLine = FALSE; } } @@ -2356,11 +2431,12 @@ Parse_File(name, stream) goto nextLine; } else if (strncmp(cp, "undef", 5) == 0) { char *cp2; - for (cp += 5; isspace(*cp); cp++) { + for (cp += 5; isspace((unsigned char) *cp); cp++) { continue; } - for (cp2 = cp; !isspace(*cp2) && (*cp2 != '\0'); cp2++) { + for (cp2 = cp; !isspace((unsigned char) *cp2) && + (*cp2 != '\0'); cp2++) { continue; } @@ -2370,22 +2446,20 @@ Parse_File(name, stream) goto nextLine; } } - if (*line == '#') { - /* If we're this far, the line must be a comment. */ + if (*line == '#' || *line == '\0') { + /* If we're this far, the line must be a comment. + (Empty lines are ignored as well) */ goto nextLine; } - if (*line == '\t' -#ifdef POSIX - || *line == ' ' -#endif - ) - { + if (*line == '\t') { /* - * If a line starts with a tab (or space in POSIX-land), it - * can only hope to be a creation command. + * If a line starts with a tab, it can only hope to be + * a creation command. */ +#ifndef POSIX shellCommand: +#endif for (cp = line + 1; isspace (*cp); cp++) { continue; } @@ -2396,7 +2470,8 @@ Parse_File(name, stream) * in a dependency spec, add the command to the list of * commands of all targets in the dependency spec */ - Lst_ForEach (targets, ParseAddCmd, (ClientData)cp); + Lst_ForEach (targets, ParseAddCmd, cp); + Lst_AtEnd(targCmds, (ClientData) line); continue; } else { Parse_Error (PARSE_FATAL, @@ -2426,24 +2501,28 @@ Parse_File(name, stream) * If it doesn't have an operator and we're in a dependency * line's script, we assume it's actually a shell command * and add it to the current list of targets. - * - * Note that POSIX declares all lines that start with - * whitespace are shell commands, so there's no need to check - * here... */ +#ifndef POSIX Boolean nonSpace = FALSE; +#endif cp = line; + if (isspace((unsigned char) line[0])) { + while ((*cp != '\0') && isspace((unsigned char) *cp)) { + cp++; + } + if (*cp == '\0') { + goto nextLine; + } #ifndef POSIX - if (line[0] == ' ') { while ((*cp != ':') && (*cp != '!') && (*cp != '\0')) { - if (!isspace(*cp)) { - nonSpace = TRUE; - } + nonSpace = TRUE; cp++; } +#endif } +#ifndef POSIX if (*cp == '\0') { if (inLine) { Parse_Error (PARSE_WARNING, @@ -2463,6 +2542,9 @@ Parse_File(name, stream) /* * Need a non-circular list for the target nodes */ + if (targets) + Lst_Destroy(targets, NOFREE); + targets = Lst_Init (FALSE); inLine = TRUE; @@ -2515,6 +2597,7 @@ Parse_Init () 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 @@ -2532,6 +2615,18 @@ Parse_Init () } } +void +Parse_End() +{ + Lst_Destroy(targCmds, (void (*) __P((ClientData))) free); + if (targets) + Lst_Destroy(targets, NOFREE); + Lst_Destroy(sysIncPath, Dir_Destroy); + Lst_Destroy(parseIncPath, Dir_Destroy); + Lst_Destroy(includes, NOFREE); /* Should be empty now */ +} + + /*- *----------------------------------------------------------------------- * Parse_MainName -- |