summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/make/Makefile6
-rw-r--r--usr.bin/make/cond.c277
-rw-r--r--usr.bin/make/cond.h5
-rw-r--r--usr.bin/make/cond_int.h4
-rw-r--r--usr.bin/make/for.c9
-rw-r--r--usr.bin/make/generate.c4
-rw-r--r--usr.bin/make/parse.c52
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;
}