diff options
author | 1999-12-16 17:07:20 +0000 | |
---|---|---|
committer | 1999-12-16 17:07:20 +0000 | |
commit | dcd42216be79e51028dbc6fa0be1a3837ec10dd3 (patch) | |
tree | a51e9e64017a5836e1743baa5d3f513a8f21d3df | |
parent | Allocate buffers as static data structures. (diff) | |
download | wireguard-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.h | 8 | ||||
-rw-r--r-- | usr.bin/make/for.c | 283 | ||||
-rw-r--r-- | usr.bin/make/parse.c | 30 |
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); |