diff options
-rw-r--r-- | usr.bin/make/Makefile | 6 | ||||
-rw-r--r-- | usr.bin/make/cond.c | 277 | ||||
-rw-r--r-- | usr.bin/make/cond.h | 5 | ||||
-rw-r--r-- | usr.bin/make/cond_int.h | 4 | ||||
-rw-r--r-- | usr.bin/make/for.c | 9 | ||||
-rw-r--r-- | usr.bin/make/generate.c | 4 | ||||
-rw-r--r-- | usr.bin/make/parse.c | 52 |
7 files changed, 237 insertions, 120 deletions
diff --git a/usr.bin/make/Makefile b/usr.bin/make/Makefile index e5e0acd91ad..33174bfa2d2 100644 --- a/usr.bin/make/Makefile +++ b/usr.bin/make/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.34 2002/04/22 21:45:01 miod Exp $ +# $OpenBSD: Makefile,v 1.35 2002/06/11 21:12:11 espie Exp $ PROG= make CFLAGS+= -I${.OBJDIR} -I${.CURDIR} @@ -9,6 +9,7 @@ CFLAGS+=-DUSE_TIMESPEC CFLAGS+=-DHAS_BOOL_H CFLAGS+=-DHAS_PATHS_H CFLAGS+=-DHAS_EXTENDED_GETCWD +#CFLAGS+=-DHAS_STATS SRCS= arch.c buf.c cmd_exec.c compat.c cond.c dir.c error.c for.c \ init.c job.c lowparse.c main.c make.c memory.c parse.c \ @@ -28,7 +29,7 @@ CLEANFILES+= varhashconsts.h condhashconsts.h generate.o generate beforedepend: varhashconsts.h condhashconsts.h # may need tweaking if you add variable synonyms or change the hash function MAGICVARSLOTS=77 -MAGICCONDSLOTS=43 +MAGICCONDSLOTS=65 varhashconsts.h: generate ${.OBJDIR}/generate 1 ${MAGICVARSLOTS} >${.TARGET} @@ -47,6 +48,7 @@ regress: check # kludge for people who forget to make depend var.o: varhashconsts.h +cond.o: condhashconsts.h .if make(install) SUBDIR+= PSD.doc diff --git a/usr.bin/make/cond.c b/usr.bin/make/cond.c index 4f2333e40eb..7dc574f802a 100644 --- a/usr.bin/make/cond.c +++ b/usr.bin/make/cond.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: cond.c,v 1.27 2002/04/17 16:45:02 espie Exp $ */ +/* $OpenBSD: cond.c,v 1.28 2002/06/11 21:12:11 espie Exp $ */ /* $NetBSD: cond.c,v 1.7 1996/11/06 17:59:02 christos Exp $ */ /* @@ -50,6 +50,8 @@ #include "dir.h" #include "buf.h" #include "cond.h" +#include "cond_int.h" +#include "condhashconsts.h" #include "error.h" #include "var.h" #include "varname.h" @@ -59,6 +61,7 @@ #include "main.h" #include "gnode.h" #include "lst.h" +#include "ohash.h" /* The parsing of conditional expressions is based on this grammar: @@ -113,21 +116,37 @@ static Token CondHandleDefault(bool); static const char *find_cond(const char *); -static struct If { - char *form; /* Form of if */ - int formlen; /* Length of form */ - bool doNot; /* true if default function should be negated */ +struct If { + bool isElse; /* true for else forms */ + bool doNot; /* true for embedded negation */ bool (*defProc)(struct Name *); - /* Default function to apply */ -} ifs[] = { - { "ifdef", 5, false, CondDoDefined }, - { "ifndef", 6, true, CondDoDefined }, - { "ifmake", 6, false, CondDoMake }, - { "ifnmake", 7, true, CondDoMake }, - { "if", 2, false, CondDoDefined }, - { NULL, 0, false, NULL } + /* function to apply */ }; +static struct If ifs[] = { + { false, false, CondDoDefined }, /* if, ifdef */ + { false, true, CondDoDefined }, /* ifndef */ + { false, false, CondDoMake }, /* ifmake */ + { false, true, CondDoMake }, /* ifnmake */ + { true, false, CondDoDefined }, /* elif, elifdef */ + { true, true, CondDoDefined }, /* elifndef */ + { true, false, CondDoMake }, /* elifmake */ + { true, true, CondDoMake }, /* elifnmake */ + { true, false, NULL } +}; + +#define COND_IF_INDEX 0 +#define COND_IFDEF_INDEX 0 +#define COND_IFNDEF_INDEX 1 +#define COND_IFMAKE_INDEX 2 +#define COND_IFNMAKE_INDEX 3 +#define COND_ELIF_INDEX 4 +#define COND_ELIFDEF_INDEX 4 +#define COND_ELIFNDEF_INDEX 5 +#define COND_ELIFMAKE_INDEX 6 +#define COND_ELIFNMAKE_INDEX 7 +#define COND_ELSE_INDEX 8 + static bool condInvert; /* Invert the default function */ static bool (*condDefProc) /* Default function to apply */ (struct Name *); @@ -836,101 +855,196 @@ CondE(doEval) return l; } -/* A conditional line looks like this: - * <cond-type> <expr> +/* Evaluate conditional in line. + * returns COND_SKIP, COND_PARSE, COND_INVALID, COND_ISFOR, COND_ISINCLUDE, + * COND_ISUNDEF. + * A conditional line looks like this: + * <cond-type> <expr> * where <cond-type> is any of if, ifmake, ifnmake, ifdef, * ifndef, elif, elifmake, elifnmake, elifdef, elifndef * and <expr> consists of &&, ||, !, make(target), defined(variable) * and parenthetical groupings thereof. */ int -Cond_Eval(line) - const char *line; /* Line to parse */ +Cond_Eval(const char *line) { - struct If *ifp; - bool isElse; - bool value = false; - int level; /* Level at which to report errors. */ + /* find end of keyword */ + const char *end; + u_int32_t k; + size_t len; + struct If *ifp; + bool value = false; + int level; /* Level at which to report errors. */ level = PARSE_FATAL; - /* Stuff we are looking for can be if*, elif*, else, or endif. - * otherwise, this is not our turf. */ - - /* Find what type of if we're dealing with. The result is left - * in ifp and isElse is set true if it's an elif line. */ - if (line[0] == 'e' && line[1] == 'l') { - line += 2; - isElse = true; - } else if (strncmp(line, "endif", 5) == 0) { + for (end = line; islower(*end); end++) + ; + /* quick path: recognize special targets early on */ + if (*end == '.' || *end == ':') + return COND_INVALID; + len = end - line; + k = ohash_interval(line, &end); + switch(k % MAGICSLOTS2) { + case K_COND_IF % MAGICSLOTS2: + if (k == K_COND_IF && len == strlen(COND_IF) && + strncmp(line, COND_IF, len) == 0) { + ifp = ifs + COND_IF_INDEX; + } else + return COND_INVALID; + break; + case K_COND_IFDEF % MAGICSLOTS2: + if (k == K_COND_IFDEF && len == strlen(COND_IFDEF) && + strncmp(line, COND_IFDEF, len) == 0) { + ifp = ifs + COND_IFDEF_INDEX; + } else + return COND_INVALID; + break; + case K_COND_IFNDEF % MAGICSLOTS2: + if (k == K_COND_IFNDEF && len == strlen(COND_IFNDEF) && + strncmp(line, COND_IFNDEF, len) == 0) { + ifp = ifs + COND_IFNDEF_INDEX; + } else + return COND_INVALID; + break; + case K_COND_IFMAKE % MAGICSLOTS2: + if (k == K_COND_IFMAKE && len == strlen(COND_IFMAKE) && + strncmp(line, COND_IFMAKE, len) == 0) { + ifp = ifs + COND_IFMAKE_INDEX; + } else + return COND_INVALID; + break; + case K_COND_IFNMAKE % MAGICSLOTS2: + if (k == K_COND_IFNMAKE && len == strlen(COND_IFNMAKE) && + strncmp(line, COND_IFNMAKE, len) == 0) { + ifp = ifs + COND_IFNMAKE_INDEX; + } else + return COND_INVALID; + break; + case K_COND_ELIF % MAGICSLOTS2: + if (k == K_COND_ELIF && len == strlen(COND_ELIF) && + strncmp(line, COND_ELIF, len) == 0) { + ifp = ifs + COND_ELIF_INDEX; + } else + return COND_INVALID; + break; + case K_COND_ELIFDEF % MAGICSLOTS2: + if (k == K_COND_ELIFDEF && len == strlen(COND_ELIFDEF) && + strncmp(line, COND_ELIFDEF, len) == 0) { + ifp = ifs + COND_ELIFDEF_INDEX; + } else + return COND_INVALID; + break; + case K_COND_ELIFNDEF % MAGICSLOTS2: + if (k == K_COND_ELIFNDEF && len == strlen(COND_ELIFNDEF) && + strncmp(line, COND_ELIFNDEF, len) == 0) { + ifp = ifs + COND_ELIFNDEF_INDEX; + } else + return COND_INVALID; + break; + case K_COND_ELIFMAKE % MAGICSLOTS2: + if (k == K_COND_ELIFMAKE && len == strlen(COND_ELIFMAKE) && + strncmp(line, COND_ELIFMAKE, len) == 0) { + ifp = ifs + COND_ELIFMAKE_INDEX; + } else + return COND_INVALID; + break; + case K_COND_ELIFNMAKE % MAGICSLOTS2: + if (k == K_COND_ELIFNMAKE && len == strlen(COND_ELIFNMAKE) && + strncmp(line, COND_ELIFNMAKE, len) == 0) { + ifp = ifs + COND_ELIFNMAKE_INDEX; + } else + return COND_INVALID; + break; + case K_COND_ELSE % MAGICSLOTS2: + /* valid conditional whose value is the inverse + * of the previous if we parsed. */ + if (k == K_COND_ELSE && len == strlen(COND_ELSE) && + strncmp(line, COND_ELSE, len) == 0) { + if (condTop == MAXIF) { + Parse_Error(level, "if-less else"); + return COND_INVALID; + } else if (skipIfLevel == 0) { + value = !condStack[condTop].value; + ifp = ifs + COND_ELSE_INDEX; + } else + return COND_SKIP; + } else + return COND_INVALID; + break; + case K_COND_ENDIF % MAGICSLOTS2: + if (k == K_COND_ENDIF && len == strlen(COND_ENDIF) && + strncmp(line, COND_ENDIF, len) == 0) { /* End of a conditional section. If skipIfLevel is non-zero, that * conditional was skipped, so lines following it should also be * skipped. Hence, we return COND_SKIP. Otherwise, the conditional * was read so succeeding lines should be parsed (think about it...) * so we return COND_PARSE, unless this endif isn't paired with * a decent if. */ - if (skipIfLevel != 0) { - skipIfLevel -= 1; - return COND_SKIP; - } else { - if (condTop == MAXIF) { - Parse_Error(level, "if-less endif"); - return COND_INVALID; + if (skipIfLevel != 0) { + skipIfLevel -= 1; + return COND_SKIP; } else { - skipLine = false; - condTop += 1; - return COND_PARSE; + if (condTop == MAXIF) { + Parse_Error(level, "if-less endif"); + return COND_INVALID; + } else { + skipLine = false; + condTop += 1; + return COND_PARSE; + } } - } - } else - isElse = false; - - /* Figure out what sort of conditional it is -- what its default - * function is, etc. -- by looking in the table of valid "ifs" */ - for (ifp = ifs; ifp->form != NULL; ifp++) { - if (strncmp(ifp->form, line, ifp->formlen) == 0) - break; + } else + return COND_INVALID; + break; + /* Recognize other keywords there, to simplify parser's task */ + case K_COND_FOR % MAGICSLOTS2: + if (k == K_COND_FOR && len == strlen(COND_FOR) && + strncmp(line, COND_FOR, len) == 0) + return COND_ISFOR; + else + return COND_INVALID; + case K_COND_UNDEF % MAGICSLOTS2: + if (k == K_COND_UNDEF && len == strlen(COND_UNDEF) && + strncmp(line, COND_UNDEF, len) == 0) + return COND_ISUNDEF; + else + return COND_INVALID; + case K_COND_INCLUDE % MAGICSLOTS2: + if (k == K_COND_INCLUDE && len == strlen(COND_INCLUDE) && + strncmp(line, COND_INCLUDE, len) == 0) + return COND_ISINCLUDE; + else + return COND_INVALID; + default: + /* Not a valid conditional type. No error... */ + return COND_INVALID; } - if (ifp->form == NULL) { - /* Nothing fits. If the first word on the line is actually - * "else", it's a valid conditional whose value is the inverse - * of the previous if we parsed. */ - if (isElse && line[0] == 's' && line[1] == 'e') { - if (condTop == MAXIF) { - Parse_Error(level, "if-less else"); - return COND_INVALID; - } else if (skipIfLevel == 0) - value = !condStack[condTop].value; - else - return COND_SKIP; - } else - /* Not a valid conditional type. No error... */ + if (ifp->isElse) { + if (condTop == MAXIF) { + Parse_Error(level, "if-less elif"); return COND_INVALID; - } else { - if (isElse) { - if (condTop == MAXIF) { - Parse_Error(level, "if-less elif"); - return COND_INVALID; - } else if (skipIfLevel != 0) { - /* If skipping this conditional, just ignore the whole thing. - * If we don't, the user might be employing a variable that's - * undefined, for which there's an enclosing ifdef that - * we're skipping... */ - return COND_SKIP; - } - } else if (skipLine) { - /* Don't even try to evaluate a conditional that's not an else if - * we're skipping things... */ - skipIfLevel += 1; + } else if (skipIfLevel != 0) { + /* If skipping this conditional, just ignore the whole thing. + * If we don't, the user might be employing a variable that's + * undefined, for which there's an enclosing ifdef that + * we're skipping... */ return COND_SKIP; } + } else if (skipLine) { + /* Don't even try to evaluate a conditional that's not an else if + * we're skipping things... */ + skipIfLevel += 1; + return COND_SKIP; + } + if (ifp->defProc) { /* Initialize file-global variables for parsing. */ condDefProc = ifp->defProc; condInvert = ifp->doNot; - line += ifp->formlen; + line += len; while (*line == ' ' || *line == '\t') line++; @@ -960,7 +1074,8 @@ Cond_Eval(line) break; } } - if (!isElse) + + if (!ifp->isElse) condTop -= 1; else if (skipIfLevel != 0 || condStack[condTop].value) { /* If this is an else-type conditional, it should only take effect diff --git a/usr.bin/make/cond.h b/usr.bin/make/cond.h index 7a98b3af0d5..8369b35462e 100644 --- a/usr.bin/make/cond.h +++ b/usr.bin/make/cond.h @@ -1,7 +1,7 @@ #ifndef COND_H #define COND_H /* $OpenPackages$ */ -/* $OpenBSD: cond.h,v 1.1 2001/05/23 12:34:41 espie Exp $ */ +/* $OpenBSD: cond.h,v 1.2 2002/06/11 21:12:11 espie Exp $ */ /* * Copyright (c) 2001 Marc Espie. @@ -36,6 +36,9 @@ #define COND_PARSE 0 /* Parse the next lines */ #define COND_SKIP 1 /* Skip the next lines */ #define COND_INVALID 2 /* Not a conditional statement */ +#define COND_ISFOR 3 +#define COND_ISUNDEF 4 +#define COND_ISINCLUDE 5 /* whattodo = Cond_Eval(line); * Parses a conditional expression (without the leading dot), diff --git a/usr.bin/make/cond_int.h b/usr.bin/make/cond_int.h index d00bed129f4..146b0aff558 100644 --- a/usr.bin/make/cond_int.h +++ b/usr.bin/make/cond_int.h @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: cond_int.h,v 1.2 2001/05/23 12:34:41 espie Exp $ */ +/* $OpenBSD: cond_int.h,v 1.3 2002/06/11 21:12:11 espie Exp $ */ /* List of all keywords recognized by the make parser */ #define COND_IF "if" @@ -8,11 +8,13 @@ #define COND_IFMAKE "ifmake" #define COND_IFNMAKE "ifnmake" #define COND_ELSE "else" +#define COND_ELIF "elif" #define COND_ELIFDEF "elifdef" #define COND_ELIFNDEF "elifndef" #define COND_ELIFMAKE "elifmake" #define COND_ELIFNMAKE "elifnmake" #define COND_ENDIF "endif" #define COND_FOR "for" +#define COND_ENDFOR "endfor" #define COND_INCLUDE "include" #define COND_UNDEF "undef" diff --git a/usr.bin/make/for.c b/usr.bin/make/for.c index c71378497d2..fa97c94c7e4 100644 --- a/usr.bin/make/for.c +++ b/usr.bin/make/for.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: for.c,v 1.26 2001/05/29 12:53:40 espie Exp $ */ +/* $OpenBSD: for.c,v 1.27 2002/06/11 21:12:11 espie Exp $ */ /* $NetBSD: for.c,v 1.4 1996/11/06 17:59:05 christos Exp $ */ /* @@ -146,13 +146,6 @@ For_Eval(line) For *arg; unsigned long n; - /* If we are not in a for loop quickly determine if the statement is - * a for. */ - if (ptr[0] != 'f' || ptr[1] != 'o' || ptr[2] != 'r' || - !isspace(ptr[3])) - return NULL; - ptr += 4; - while (*ptr && isspace(*ptr)) ptr++; diff --git a/usr.bin/make/generate.c b/usr.bin/make/generate.c index 80e4d4a1668..4e5494d2041 100644 --- a/usr.bin/make/generate.c +++ b/usr.bin/make/generate.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: generate.c,v 1.4 2001/05/23 12:34:43 espie Exp $ */ +/* $OpenBSD: generate.c,v 1.5 2002/06/11 21:12:11 espie Exp $ */ /* * Copyright (c) 2001 Marc Espie. @@ -69,12 +69,14 @@ char *table_cond[] = { M(COND_IFMAKE), M(COND_IFNMAKE), M(COND_ELSE), + M(COND_ELIF), M(COND_ELIFDEF), M(COND_ELIFNDEF), M(COND_ELIFMAKE), M(COND_ELIFNMAKE), M(COND_ENDIF), M(COND_FOR), + M(COND_ENDFOR), M(COND_INCLUDE), M(COND_UNDEF), NULL diff --git a/usr.bin/make/parse.c b/usr.bin/make/parse.c index a4c4b54fe06..f7e90e12f70 100644 --- a/usr.bin/make/parse.c +++ b/usr.bin/make/parse.c @@ -1,5 +1,5 @@ /* $OpenPackages$ */ -/* $OpenBSD: parse.c,v 1.66 2001/11/11 12:35:02 espie Exp $ */ +/* $OpenBSD: parse.c,v 1.67 2002/06/11 21:12:11 espie Exp $ */ /* $NetBSD: parse.c,v 1.29 1997/03/10 21:20:04 christos Exp $ */ /* @@ -1406,35 +1406,31 @@ ParseIsCond(linebuf, copy, line) /* FALLTHROUGH */ case COND_PARSE: return true; - default: + case COND_ISFOR: { + For *loop; + + loop = For_Eval(line+3); + if (loop != NULL) { + bool ok; + do { + /* Find the matching endfor. */ + line = ParseReadLoopLine(linebuf); + if (line == NULL) { + Parse_Error(PARSE_FATAL, + "Unexpected end of file in for loop.\n"); + return false; + } + ok = For_Accumulate(loop, line); + } while (ok); + For_Run(loop); + return true; + } break; } - - { - For *loop; - - loop = For_Eval(line); - if (loop != NULL) { - bool ok; - do { - /* Find the matching endfor. */ - line = ParseReadLoopLine(linebuf); - if (line == NULL) { - Parse_Error(PARSE_FATAL, - "Unexpected end of file in for loop.\n"); - return false; - } - ok = For_Accumulate(loop, line); - } while (ok); - For_Run(loop); - return true; - } - } - - if (strncmp(line, "include", 7) == 0) { + case COND_ISINCLUDE: ParseDoInclude(line + 7); return true; - } else if (strncmp(line, "undef", 5) == 0) { + case COND_ISUNDEF: { char *cp; line+=5; @@ -1446,6 +1442,10 @@ ParseIsCond(linebuf, copy, line) Var_Delete(line); return true; } + default: + break; + } + return false; } |