summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorespie <espie@openbsd.org>1999-12-16 17:07:20 +0000
committerespie <espie@openbsd.org>1999-12-16 17:07:20 +0000
commitdcd42216be79e51028dbc6fa0be1a3837ec10dd3 (patch)
treea51e9e64017a5836e1743baa5d3f513a8f21d3df
parentAllocate buffers as static data structures. (diff)
downloadwireguard-openbsd-dcd42216be79e51028dbc6fa0be1a3837ec10dd3.tar.xz
wireguard-openbsd-dcd42216be79e51028dbc6fa0be1a3837ec10dd3.zip
for.c becomes sane.
- split For_Eval into For_Eval (first line of loop) / For_Accumulate (remaining lines). - encapsulate state into a For structure, instead of brain damaged static variables that need copy. Very minor performance hit, specifically, For structure is allocated with malloc/free, instead of playing tricks with static/auto variables.
-rw-r--r--usr.bin/make/extern.h8
-rw-r--r--usr.bin/make/for.c283
-rw-r--r--usr.bin/make/parse.c30
3 files changed, 154 insertions, 167 deletions
diff --git a/usr.bin/make/extern.h b/usr.bin/make/extern.h
index 91bd4f3023b..fb090ac4dc4 100644
--- a/usr.bin/make/extern.h
+++ b/usr.bin/make/extern.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: extern.h,v 1.15 1999/12/09 18:20:06 espie Exp $ */
+/* $OpenBSD: extern.h,v 1.16 1999/12/16 17:07:20 espie Exp $ */
/* $NetBSD: nonints.h,v 1.12 1996/11/06 17:59:19 christos Exp $ */
/*-
@@ -63,8 +63,10 @@ void Cond_End __P((void));
#include "error.h"
/* for.c */
-int For_Eval __P((char *));
-void For_Run __P((void));
+typedef struct For_ For;
+For *For_Eval __P((char *));
+Boolean For_Accumulate __P((For *, const char *));
+void For_Run __P((For *));
/* main.c */
void Main_ParseArgLine __P((char *));
diff --git a/usr.bin/make/for.c b/usr.bin/make/for.c
index ff1cab7099b..acea5672605 100644
--- a/usr.bin/make/for.c
+++ b/usr.bin/make/for.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: for.c,v 1.10 1999/12/16 17:02:45 espie Exp $ */
+/* $OpenBSD: for.c,v 1.11 1999/12/16 17:07:20 espie Exp $ */
/* $NetBSD: for.c,v 1.4 1996/11/06 17:59:05 christos Exp $ */
/*
@@ -65,7 +65,7 @@
#if 0
static char sccsid[] = "@(#)for.c 8.1 (Berkeley) 6/6/93";
#else
-static char rcsid[] = "$OpenBSD: for.c,v 1.10 1999/12/16 17:02:45 espie Exp $";
+static char rcsid[] = "$OpenBSD: for.c,v 1.11 1999/12/16 17:07:20 espie Exp $";
#endif
#endif /* not lint */
@@ -92,30 +92,24 @@ static char rcsid[] = "$OpenBSD: for.c,v 1.10 1999/12/16 17:02:45 espie Exp $";
* ...
* .endfor
*
- * The trick is to look for the matching end inside for for loop
- * To do that, we count the current nesting level of the for loops.
- * and the .endfor statements, accumulating all the statements between
- * the initial .for loop and the matching .endfor;
- * then we evaluate the for loop for each variable in the varlist.
+ * The trick is to look for the matching .end inside .for loops.
+ * To do that, we keep track of the nesting level of .for loops
+ * and matching .endfor statements, accumulating all statements between
+ * the initial .for loop and the matching .endfor,
+ * then we evaluate the .for loop for each variable in the varlist.
*/
-static int forLevel = 0; /* Nesting level */
-static char *forVar; /* Iteration variable */
-static BUFFER forBuf; /* Commands in loop */
-static Lst forLst; /* List of items */
-static unsigned long forLineno; /* Line at beginning of loop */
-
-/*
- * State of a for loop.
- */
-typedef struct _For {
- Buffer buf; /* Unexpanded buffer */
- char* var; /* Index name */
- Lst lst; /* List of variables */
- unsigned long lineno;
-} For;
-
-static int ForExec __P((ClientData, ClientData));
+/* State of a for loop. */
+struct For_ {
+ char *text; /* unexpanded text */
+ char *var; /* Index name */
+ Lst lst; /* List of items */
+ BUFFER buf; /* Accumulating text */
+ unsigned long lineno; /* Line number at start of loop */
+ unsigned long level; /* Nesting level */
+};
+
+static int ForExec __P((ClientData, ClientData));
static void build_words_list __P((Lst, const char *));
/* Cut a string into words, stuff that into list. */
@@ -133,14 +127,13 @@ build_words_list(lst, s)
break;
for (wrd = s; *s != '\0' && !isspace(*s); s++)
continue;
- /* note that we fill the list backward, since
- * Parse_FromString stacks strings. */
+ /* note that we fill the list backward, since
+ * Parse_FromString stacks strings. */
Lst_AtFront(lst, (ClientData)interval_dup(wrd, s));
}
}
-
-/*-
+/*
*-----------------------------------------------------------------------
* For_Eval --
* Evaluate the for loop in the passed line. The line
@@ -148,124 +141,128 @@ build_words_list(lst, s)
* .for <variable> in <varlist>
*
* Results:
- * TRUE: We found a for loop, or we are inside a for loop
- * FALSE: We did not find a for loop, or we found the end of the for
- * for loop.
- *
- * Side Effects:
- * None.
- *
+ * Loop structure, to accumulate further lines.
+ * NULL if this was not a for loop after all.
*-----------------------------------------------------------------------
*/
-int
-For_Eval (line)
+
+For *
+For_Eval(line)
char *line; /* Line to parse */
{
- char *ptr = line;
- int level; /* Level at which to report errors. */
+ char *ptr = line;
+ char *wrd;
+ char *sub;
+ char *endVar;
+ For *arg;
+
+ for (ptr++; *ptr && isspace(*ptr); ptr++)
+ continue;
+ /* 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++;
+
+ /* We found a for loop, and now we are going to parse it. */
+
+ /* Grab the variable. */
+ for (wrd = ptr; *ptr && !isspace(*ptr); ptr++)
+ continue;
+ if (ptr - wrd == 0) {
+ Parse_Error(PARSE_FATAL, "missing variable in for");
+ return 0;
+ }
+ endVar = ptr++;
- level = PARSE_FATAL;
+ while (*ptr && isspace(*ptr))
+ ptr++;
+ /* Grab the `in'. */
+ if (ptr[0] != 'i' || ptr[1] != 'n' ||
+ !isspace(ptr[2])) {
+ Parse_Error(PARSE_FATAL, "missing `in' in for");
+ printf("%s\n", ptr);
+ return NULL;
+ }
+ ptr += 3;
- if (forLevel == 0) {
- char *endVar;
- char *sub;
- char *wrd;
+ /* .for loop is go, collate what we need. */
+ arg = emalloc(sizeof(*arg));
+ arg->var = interval_dup(wrd, endVar);
- for (ptr++; *ptr && isspace((unsigned char) *ptr); ptr++)
- continue;
- /* 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((unsigned char) ptr[3]))
- return FALSE;
- ptr += 3;
-
- /* We found a for loop, and now we are going to parse it. */
- while (*ptr && isspace((unsigned char) *ptr))
- ptr++;
-
- /* Grab the variable. */
- for (wrd = ptr; *ptr && !isspace((unsigned char) *ptr); ptr++)
- continue;
+ /* Make a list with the remaining words. */
+ sub = Var_Subst(NULL, ptr, VAR_GLOBAL, FALSE);
+ if (DEBUG(FOR))
+ (void)fprintf(stderr, "For: Iterator %s List %s\n", arg->var, sub);
- if (ptr - wrd == 0) {
- Parse_Error(level, "missing variable in for");
- return 0;
- }
- endVar = ptr++;
+ arg->lst = Lst_Init(FALSE);
+ build_words_list(arg->lst, sub);
+ free(sub);
+ arg->lineno = Parse_Getlineno();
+ arg->level = 1;
+ Buf_Init(&arg->buf, 0);
- while (*ptr && isspace((unsigned char) *ptr))
- ptr++;
+ return arg;
+}
- /* Grab the `in'. */
- if (ptr[0] != 'i' || ptr[1] != 'n' ||
- !isspace((unsigned char) ptr[2])) {
- Parse_Error(level, "missing `in' in for");
- printf("%s\n", ptr);
- return 0;
- }
- ptr += 3;
-
- /* .for loop is go, collate what we need. */
- forVar = interval_dup(wrd, endVar);
-
- /* Make a list with the remaining words. */
- sub = Var_Subst(NULL, ptr, VAR_GLOBAL, FALSE);
- if (DEBUG(FOR))
- (void)fprintf(stderr, "For: Iterator %s List %s\n", forVar, sub);
-
- forLst = Lst_Init(FALSE);
- build_words_list(forLst, sub);
- free(sub);
- forLineno = Parse_Getlineno();
- Buf_Init(&forBuf, 0);
- forLevel++;
- return 1;
- }
- else if (*ptr == '.') {
+
+/*-
+ *-----------------------------------------------------------------------
+ * For_Accumulate --
+ * Accumulate lines in a for loop, until we find the matching endfor.
+ *
+ * Results:
+ * TRUE: keep accumulating lines.
+ * FALSE: We found the matching .endfor
+ *
+ * Side Effects:
+ * Accumulate lines in arg.
+ *-----------------------------------------------------------------------
+ */
+Boolean
+For_Accumulate(arg, line)
+ For *arg;
+ const char *line; /* Line to parse */
+{
+ const char *ptr = line;
- for (ptr++; *ptr && isspace((unsigned char) *ptr); ptr++)
+ assert(arg->level > 0);
+
+ if (*ptr == '.') {
+
+ for (ptr++; *ptr && isspace(*ptr); ptr++)
continue;
if (strncmp(ptr, "endfor", 6) == 0 &&
- (isspace((unsigned char) ptr[6]) || !ptr[6])) {
+ (isspace(ptr[6]) || !ptr[6])) {
if (DEBUG(FOR))
- (void) fprintf(stderr, "For: end for %d\n", forLevel);
- if (--forLevel < 0) {
- Parse_Error(level, "for-less endfor");
- return 0;
- }
+ (void)fprintf(stderr, "For: end for %lu\n", arg->level);
+ /* If matching endfor, don't add line to buffer. */
+ if (--arg->level == 0)
+ return FALSE;
}
else if (strncmp(ptr, "for", 3) == 0 &&
- isspace((unsigned char) ptr[3])) {
- forLevel++;
+ isspace(ptr[3])) {
+ arg->level++;
if (DEBUG(FOR))
- (void) fprintf(stderr, "For: new loop %d\n", forLevel);
+ (void)fprintf(stderr, "For: new loop %lu\n", arg->level);
}
}
-
- if (forLevel != 0) {
- Buf_AddString(&forBuf, line);
- Buf_AddChar(&forBuf, '\n');
- return 1;
- }
- else {
- return 0;
- }
+ Buf_AddString(&arg->buf, line);
+ Buf_AddChar(&arg->buf, '\n');
+ return TRUE;
}
+
/*-
*-----------------------------------------------------------------------
* ForExec --
* Expand the for loop for this index and push it in the Makefile
- *
- * Results:
- * None.
- *
- * Side Effects:
- * None.
- *
*-----------------------------------------------------------------------
*/
static int
@@ -273,15 +270,15 @@ ForExec(namep, argp)
ClientData namep;
ClientData argp;
{
- char *name = (char *) namep;
- For *arg = (For *) argp;
+ char *name = (char *)namep;
+ For *arg = (For *)argp;
+
Var_Set(arg->var, name, VAR_GLOBAL);
if (DEBUG(FOR))
- (void) fprintf(stderr, "--- %s = %s\n", arg->var, name);
- Parse_FromString(Var_Subst(arg->var, Buf_Retrieve(arg->buf),
- VAR_GLOBAL, FALSE), arg->lineno);
+ (void)fprintf(stderr, "--- %s = %s\n", arg->var, name);
+ Parse_FromString(Var_Subst(arg->var, arg->text, VAR_GLOBAL, FALSE),
+ arg->lineno);
Var_Delete(arg->var, VAR_GLOBAL);
-
return 0;
}
@@ -289,33 +286,19 @@ ForExec(namep, argp)
/*-
*-----------------------------------------------------------------------
* For_Run --
- * Run the for loop, immitating the actions of an include file
- *
- * Results:
- * None.
- *
- * Side Effects:
- * None.
- *
+ * Run the for loop, pushing expanded lines for reparse
*-----------------------------------------------------------------------
*/
+
void
-For_Run()
+For_Run(arg)
+ For *arg;
{
- For arg;
-
- if (forVar == NULL || forLst == NULL)
- return;
- arg.var = forVar;
- arg.buf = &forBuf;
- arg.lst = forLst;
- arg.lineno = forLineno;
- forVar = NULL;
- forLst = NULL;
-
- Lst_ForEach(arg.lst, ForExec, (ClientData) &arg);
-
- free((Address)arg.var);
- Lst_Destroy(arg.lst, (void (*) __P((ClientData))) free);
- Buf_Destroy(arg.buf);
+ arg->text = Buf_Retrieve(&arg->buf);
+
+ Lst_ForEach(arg->lst, ForExec, (ClientData)arg);
+ free(arg->var);
+ free(arg->text);
+ Lst_Destroy(arg->lst, (void (*) __P((ClientData)))free);
+ free(arg);
}
diff --git a/usr.bin/make/parse.c b/usr.bin/make/parse.c
index 1320485b794..9de8d51c818 100644
--- a/usr.bin/make/parse.c
+++ b/usr.bin/make/parse.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.c,v 1.29 1999/12/16 17:02:45 espie Exp $ */
+/* $OpenBSD: parse.c,v 1.30 1999/12/16 17:07:21 espie Exp $ */
/* $NetBSD: parse.c,v 1.29 1997/03/10 21:20:04 christos Exp $ */
/*
@@ -43,7 +43,7 @@
#if 0
static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94";
#else
-static char rcsid[] = "$OpenBSD: parse.c,v 1.29 1999/12/16 17:02:45 espie Exp $";
+static char rcsid[] = "$OpenBSD: parse.c,v 1.30 1999/12/16 17:07:21 espie Exp $";
#endif
#endif /* not lint */
@@ -2375,28 +2375,30 @@ test_char:
line = ParseReadLine();
break;
case COND_INVALID:
- if (For_Eval(line)) {
- int ok;
+ {
+ For *loop;
+
+ loop = For_Eval(line);
+ if (loop != NULL) {
+ Boolean ok;
+
free(line);
do {
- /*
- * Skip after the matching end
- */
+ /* Find the matching endfor. */
line = ParseSkipLine(0);
if (line == NULL) {
- Parse_Error (PARSE_FATAL,
+ Parse_Error(PARSE_FATAL,
"Unexpected end of file in for loop.\n");
- break;
+ return line;
}
- ok = For_Eval(line);
+ ok = For_Accumulate(loop, line);
free(line);
- }
- while (ok);
- if (line != NULL)
- For_Run();
+ } while (ok);
+ For_Run(loop);
line = ParseReadLine();
}
break;
+ }
}
}
return (line);