From d696707cb5009308baa345ff60c8378512b07edb Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Fri, 25 Oct 2002 22:01:47 +0000 Subject: [PATCH] Fix eval bugs 1516 and 1517. --- ChangeLog | 19 +++++++++++++ expand.c | 25 ++++++++++++++++ function.c | 10 +++++++ read.c | 55 +++++++++++++++++++++++++----------- tests/ChangeLog | 5 ++++ tests/scripts/functions/eval | 31 ++++++++++++++++++++ variable.h | 2 ++ 7 files changed, 130 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 409db2b9..1f4c0586 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,24 @@ 2002-10-25 Paul D. Smith + * expand.c (install_variable_buffer): New function. Install a new + variable_buffer context and return the previous one. + (restore_variable_buffer): New function. Free the current + variable_buffer context and put a previously saved one back. + * variable.h: Prototypes for {install,restore}_variable_buffer. + * function.c (func_eval): Push a new variable_buffer context + before we eval, then restore the old one when we're done. + Fixes Bug #1517. + + * read.c (install_conditionals): New function. Install a new + conditional context and return the previous one. + (restore_conditionals): New function. Free the current + conditional context and put a previously saved one back. + (eval): Use the {install,restore}_conditionals for "include" + handling. + (eval_buffer): Use {install,restore}_conditionals to preserve the + present conditional state before we evaluate the buffer. + Fixes Bug #1516. + * doc/make.texi (Quick Reference): Add references to $(eval ...) and $(value ...). (Recursion): Add a variable index entry for CURDIR. diff --git a/expand.c b/expand.c index 5c2c3e2e..ac4ccda5 100644 --- a/expand.c +++ b/expand.c @@ -545,3 +545,28 @@ allocated_variable_expand_for_file (char *line, struct file *file) return value; } + +/* Install a new variable_buffer context, returning the current one for + safe-keeping. */ + +void +install_variable_buffer (char **bufp, unsigned int *lenp) +{ + *bufp = variable_buffer; + *lenp = variable_buffer_length; + + variable_buffer = 0; + initialize_variable_output (); +} + +/* Restore a previously-saved variable_buffer setting (free the current one). + */ + +void +restore_variable_buffer (char *buf, unsigned int len) +{ + free (variable_buffer); + + variable_buffer = buf; + variable_buffer_length = len; +} diff --git a/function.c b/function.c index 3282cdfc..5a27406b 100644 --- a/function.c +++ b/function.c @@ -1196,8 +1196,18 @@ func_wildcard (char *o, char **argv, const char *funcname) static char * func_eval (char *o, char **argv, const char *funcname) { + char *buf; + unsigned int len; + + /* Eval the buffer. Pop the current variable buffer setting so that the + eval'd code can use its own without conflicting. */ + + install_variable_buffer (&buf, &len); + eval_buffer (argv[0]); + restore_variable_buffer (buf, len); + return o; } diff --git a/read.c b/read.c index 4fb811a4..3e015720 100644 --- a/read.c +++ b/read.c @@ -272,6 +272,34 @@ read_all_makefiles (char **makefiles) return read_makefiles; } +/* Install a new conditional and return the previous one. */ + +static struct conditionals * +install_conditionals (struct conditionals *new) +{ + struct conditionals *save = conditionals; + + bzero ((char *) new, sizeof (*new)); + conditionals = new; + + return save; +} + +/* Free the current conditionals and reinstate a saved one. */ + +static void +restore_conditionals (struct conditionals *saved) +{ + /* Free any space allocated by conditional_line. */ + if (conditionals->ignoring) + free (conditionals->ignoring); + if (conditionals->seen_else) + free (conditionals->seen_else); + + /* Restore state. */ + conditionals = saved; +} + static int eval_makefile (char *filename, int flags) { @@ -388,6 +416,8 @@ int eval_buffer (char *buffer) { struct ebuffer ebuf; + struct conditionals *saved; + struct conditionals new; const struct floc *curfile; int r; @@ -402,8 +432,12 @@ eval_buffer (char *buffer) curfile = reading_file; reading_file = &ebuf.floc; + saved = install_conditionals (&new); + r = eval (&ebuf, 1); + restore_conditionals (saved); + reading_file = curfile; return r; @@ -412,13 +446,8 @@ eval_buffer (char *buffer) /* Read file FILENAME as a makefile and add its contents to the data base. - SET_DEFAULT is true if we are allowed to set the default goal. + SET_DEFAULT is true if we are allowed to set the default goal. */ - FILENAME is added to the `read_makefiles' chain. - - Returns 0 if a file was not found or not read. - Returns 1 if FILENAME was found and read. - Returns 2 if FILENAME was read, and we kept a reference (don't free it). */ static int eval (struct ebuffer *ebuf, int set_default) @@ -782,9 +811,7 @@ eval (struct ebuffer *ebuf, int set_default) /* Save the state of conditionals and start the included makefile with a clean slate. */ - save = conditionals; - bzero ((char *) &new_conditionals, sizeof new_conditionals); - conditionals = &new_conditionals; + save = install_conditionals (&new_conditionals); /* Record the rules that are waiting so they will determine the default goal before those in the included makefile. */ @@ -810,14 +837,8 @@ eval (struct ebuffer *ebuf, int set_default) } } - /* Free any space allocated by conditional_line. */ - if (conditionals->ignoring) - free (conditionals->ignoring); - if (conditionals->seen_else) - free (conditionals->seen_else); - - /* Restore state. */ - conditionals = save; + /* Restore conditional state. */ + restore_conditionals (save); goto rule_complete; } diff --git a/tests/ChangeLog b/tests/ChangeLog index 3c62080f..e91ccc9b 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,8 @@ +2002-10-25 Paul D. Smith + + * scripts/functions/eval: Test using $(eval ...) inside + conditionals (Bug #1516). + 2002-10-13 Paul D. Smith * scripts/features/targetvars: Add a test for exporting diff --git a/tests/scripts/functions/eval b/tests/scripts/functions/eval index 0d5e3b83..174767d7 100644 --- a/tests/scripts/functions/eval +++ b/tests/scripts/functions/eval @@ -57,4 +57,35 @@ $answer = "A = A B = B\n"; &compare_output($answer,&get_logfile(1)); +# Test to make sure eval'ing inside conditionals works properly + +$makefile3 = &get_tmpfile; + +open(MAKEFILE,"> $makefile3"); + +print MAKEFILE <<'EOF'; +FOO = foo + +all:: ; @echo it + +define Y + all:: ; @echo worked +endef + +ifdef BAR +$(eval $(Y)) +endif + +EOF + +close(MAKEFILE); + +&run_make_with_options($makefile3, "", &get_logfile); +$answer = "it\n"; +&compare_output($answer,&get_logfile(1)); + +&run_make_with_options($makefile3, "BAR=1", &get_logfile); +$answer = "it\nworked\n"; +&compare_output($answer,&get_logfile(1)); + 1; diff --git a/variable.h b/variable.h index d9cd7f7c..f96bd625 100644 --- a/variable.h +++ b/variable.h @@ -107,6 +107,8 @@ extern char *allocated_variable_expand_for_file PARAMS ((char *line, struct file extern char *expand_argument PARAMS ((char *str, char *end)); extern char *variable_expand_string PARAMS ((char *line, char *string, long length)); +extern void install_variable_buffer PARAMS ((char **bufp, unsigned int *lenp)); +extern void restore_variable_buffer PARAMS ((char *buf, unsigned int len)); /* function.c */ extern int handle_function PARAMS ((char **op, char **stringp));