version 1.24, 2001/05/03 13:41:05 |
version 1.25, 2001/05/23 12:34:42 |
|
|
* SUCH DAMAGE. |
* SUCH DAMAGE. |
*/ |
*/ |
|
|
/*- |
#include <assert.h> |
* for.c -- |
#include <ctype.h> |
* Functions to handle loops in a makefile. |
#include <stddef.h> |
* |
#include <stdio.h> |
* Interface: |
#include <string.h> |
* For_Eval Evaluate the .for in the passed line. |
#include "config.h" |
* For_Accumulate Add lines to an accumulating loop |
#include "defines.h" |
* For_Run Run accumulated loop |
#include "buf.h" |
* |
#include "for.h" |
*/ |
#include "lst.h" |
|
#include "error.h" |
|
#include "var.h" |
|
#include "lowparse.h" |
|
#include "str.h" |
|
#include "memory.h" |
|
|
#include <ctype.h> |
|
#include <assert.h> |
|
#include <stddef.h> |
|
#include "make.h" |
|
#include "buf.h" |
|
|
|
#ifndef lint |
|
#if 0 |
|
static char sccsid[] = "@(#)for.c 8.1 (Berkeley) 6/6/93"; |
|
#else |
|
UNUSED |
|
static char rcsid[] = "$OpenBSD$"; |
|
#endif |
|
#endif /* not lint */ |
|
|
|
/* |
/* |
* For statements are of the form: |
* For statements are of the form: |
* |
* |
|
|
|
|
/* State of a for loop. */ |
/* State of a for loop. */ |
struct For_ { |
struct For_ { |
char *text; /* unexpanded text */ |
char *text; /* Unexpanded text */ |
LIST vars; /* list of variables */ |
LIST vars; /* List of variables */ |
LstNode var; /* current var */ |
LstNode var; /* Current var */ |
int nvars; /* total number of vars */ |
int nvars; /* Total number of vars */ |
LIST lst; /* List of items */ |
LIST lst; /* List of items */ |
size_t guess; /* Estimated expansion size */ |
size_t guess; /* Estimated expansion size */ |
BUFFER buf; /* Accumulating text */ |
BUFFER buf; /* Accumulating text */ |
unsigned long lineno; /* Line number at start of loop */ |
unsigned long lineno; /* Line number at start of loop */ |
unsigned long level; /* Nesting level */ |
unsigned long level; /* Nesting level */ |
Boolean freeold; |
bool freeold; |
}; |
}; |
|
|
|
/* ForExec(value, handle); |
|
* Expands next variable in loop sequence described by handle to value. */ |
static void ForExec(void *, void *); |
static void ForExec(void *, void *); |
|
|
|
/* n = build_words_list(lst, s); |
|
* Cuts string into words, pushes words into list, in reverse order, |
|
* because Parse_FromString works as a stack. |
|
* Returns the number of words. */ |
static unsigned long build_words_list(Lst, const char *); |
static unsigned long build_words_list(Lst, const char *); |
|
|
/* Cut a string into words, stuff that into list. */ |
|
static unsigned long |
static unsigned long |
build_words_list(lst, s) |
build_words_list(lst, s) |
Lst lst; |
Lst lst; |
|
|
end = s; |
end = s; |
|
|
while ((wrd = iterate_words(&end)) != NULL) { |
while ((wrd = iterate_words(&end)) != NULL) { |
Lst_AtFront(lst, escape_dup(wrd, end, "\"'")); |
Lst_AtFront(lst, escape_dupi(wrd, end, "\"'")); |
n++; |
n++; |
} |
} |
return n; |
return n; |
} |
} |
|
|
/* |
|
*----------------------------------------------------------------------- |
|
* For_Eval -- |
|
* Evaluate the for loop in the passed line. The line |
|
* looks like this: |
|
* .for <variable> in <varlist> |
|
* |
|
* Results: |
|
* Loop structure, to accumulate further lines. |
|
* NULL if this was not a for loop after all. |
|
*----------------------------------------------------------------------- |
|
*/ |
|
|
|
For * |
For * |
For_Eval(line) |
For_Eval(line) |
const char *line; /* Line to parse */ |
const char *line; /* Line to parse */ |
|
|
endVar = ptr++; |
endVar = ptr++; |
while (*ptr && isspace(*ptr)) |
while (*ptr && isspace(*ptr)) |
ptr++; |
ptr++; |
/* finished variable list */ |
/* End of variable list ? */ |
if (endVar - wrd == 2 && wrd[0] == 'i' && wrd[1] == 'n') |
if (endVar - wrd == 2 && wrd[0] == 'i' && wrd[1] == 'n') |
break; |
break; |
Lst_AtEnd(&arg->vars, interval_dup(wrd, endVar)); |
Lst_AtEnd(&arg->vars, Str_dupi(wrd, endVar)); |
arg->nvars++; |
arg->nvars++; |
} |
} |
if (arg->nvars == 0) { |
if (arg->nvars == 0) { |
|
|
} |
} |
|
|
/* Make a list with the remaining words. */ |
/* Make a list with the remaining words. */ |
sub = Var_Subst(ptr, NULL, FALSE); |
sub = Var_Subst(ptr, NULL, false); |
if (DEBUG(FOR)) { |
if (DEBUG(FOR)) { |
LstNode ln; |
LstNode ln; |
(void)fprintf(stderr, "For: Iterator "); |
(void)fprintf(stderr, "For: Iterator "); |
|
|
} |
} |
|
|
|
|
/*- |
bool |
*----------------------------------------------------------------------- |
|
* 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_Accumulate(arg, line) |
For *arg; |
For *arg; |
const char *line; /* Line to parse */ |
const char *line; /* Line to parse */ |
|
|
(void)fprintf(stderr, "For: end for %lu\n", arg->level); |
(void)fprintf(stderr, "For: end for %lu\n", arg->level); |
/* If matching endfor, don't add line to buffer. */ |
/* If matching endfor, don't add line to buffer. */ |
if (--arg->level == 0) |
if (--arg->level == 0) |
return FALSE; |
return false; |
} |
} |
else if (strncmp(ptr, "for", 3) == 0 && |
else if (strncmp(ptr, "for", 3) == 0 && |
isspace(ptr[3])) { |
isspace(ptr[3])) { |
|
|
} |
} |
Buf_AddString(&arg->buf, line); |
Buf_AddString(&arg->buf, line); |
Buf_AddChar(&arg->buf, '\n'); |
Buf_AddChar(&arg->buf, '\n'); |
return TRUE; |
return true; |
} |
} |
|
|
|
|
#define GUESS_EXPANSION 32 |
#define GUESS_EXPANSION 32 |
/*- |
|
*----------------------------------------------------------------------- |
|
* ForExec -- |
|
* Expand the for loop for this index and push it in the Makefile |
|
*----------------------------------------------------------------------- |
|
*/ |
|
static void |
static void |
ForExec(namep, argp) |
ForExec(valuep, argp) |
void *namep; |
void *valuep; |
void *argp; |
void *argp; |
{ |
{ |
char *name = (char *)namep; |
char *value = (char *)valuep; |
For *arg = (For *)argp; |
For *arg = (For *)argp; |
BUFFER buf; |
BUFFER buf; |
|
|
|
|
if (arg->var == NULL) { |
if (arg->var == NULL) { |
arg->var = Lst_Last(&arg->vars); |
arg->var = Lst_Last(&arg->vars); |
arg->text = Buf_Retrieve(&arg->buf); |
arg->text = Buf_Retrieve(&arg->buf); |
arg->freeold = FALSE; |
arg->freeold = false; |
} |
} |
|
|
if (DEBUG(FOR)) |
if (DEBUG(FOR)) |
(void)fprintf(stderr, "--- %s = %s\n", (char *)Lst_Datum(arg->var), name); |
(void)fprintf(stderr, "--- %s = %s\n", (char *)Lst_Datum(arg->var), |
|
value); |
Buf_Init(&buf, arg->guess); |
Buf_Init(&buf, arg->guess); |
Var_SubstVar(&buf, arg->text, Lst_Datum(arg->var), name); |
Var_SubstVar(&buf, arg->text, Lst_Datum(arg->var), value); |
if (arg->freeold) |
if (arg->freeold) |
free(arg->text); |
free(arg->text); |
arg->text = Buf_Retrieve(&buf); |
arg->text = Buf_Retrieve(&buf); |
arg->freeold = TRUE; |
arg->freeold = true; |
arg->var = Lst_Rev(arg->var); |
arg->var = Lst_Rev(arg->var); |
if (arg->var == NULL) |
if (arg->var == NULL) |
Parse_FromString(arg->text, arg->lineno); |
Parse_FromString(arg->text, arg->lineno); |
} |
} |
|
|
|
|
/*- |
|
*----------------------------------------------------------------------- |
|
* For_Run -- |
|
* Run the for loop, pushing expanded lines for reparse |
|
*----------------------------------------------------------------------- |
|
*/ |
|
|
|
void |
void |
For_Run(arg) |
For_Run(arg) |