=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/make/for.c,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- src/usr.bin/make/for.c 1999/12/16 17:02:45 1.10 +++ src/usr.bin/make/for.c 1999/12/16 17:07:20 1.11 @@ -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 @@ * ... * .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. */ +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 */ +}; -/* - * 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)); +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 @@ 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 @@ * .for in * * 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; - level = PARSE_FATAL; + 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++; - if (forLevel == 0) { - char *endVar; - char *sub; - char *wrd; + /* We found a for loop, and now we are going to parse it. */ - 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; + /* 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++; - /* We found a for loop, and now we are going to parse it. */ - while (*ptr && isspace((unsigned char) *ptr)) - ptr++; + while (*ptr && isspace(*ptr)) + ptr++; - /* Grab the variable. */ - for (wrd = ptr; *ptr && !isspace((unsigned char) *ptr); ptr++) - continue; + /* 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 (ptr - wrd == 0) { - Parse_Error(level, "missing variable in for"); - return 0; - } - endVar = ptr++; + /* .for loop is go, collate what we need. */ + arg = emalloc(sizeof(*arg)); + arg->var = interval_dup(wrd, endVar); - while (*ptr && isspace((unsigned char) *ptr)) - ptr++; + /* 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); - /* 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; + 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); - /* .for loop is go, collate what we need. */ - forVar = interval_dup(wrd, endVar); + return arg; +} - /* 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); + +/*- + *----------------------------------------------------------------------- + * 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; - forLst = Lst_Init(FALSE); - build_words_list(forLst, sub); - free(sub); - forLineno = Parse_Getlineno(); - Buf_Init(&forBuf, 0); - forLevel++; - return 1; - } - else if (*ptr == '.') { + assert(arg->level > 0); - for (ptr++; *ptr && isspace((unsigned char) *ptr); ptr++) + 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 @@ 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 @@ /*- *----------------------------------------------------------------------- * 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; + arg->text = Buf_Retrieve(&arg->buf); - 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); + Lst_ForEach(arg->lst, ForExec, (ClientData)arg); + free(arg->var); + free(arg->text); + Lst_Destroy(arg->lst, (void (*) __P((ClientData)))free); + free(arg); }