summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2002-10-25 22:01:47 +0000
committerPaul Smith <psmith@gnu.org>2002-10-25 22:01:47 +0000
commitd696707cb5009308baa345ff60c8378512b07edb (patch)
tree480e6f04e132649d7346adc8eb92d090f85aabde
parentbd108cf45cca0a37cb82aca0f3f3516e593d638b (diff)
downloadgunmake-d696707cb5009308baa345ff60c8378512b07edb.tar.gz
Fix eval bugs 1516 and 1517.
-rw-r--r--ChangeLog19
-rw-r--r--expand.c25
-rw-r--r--function.c10
-rw-r--r--read.c55
-rw-r--r--tests/ChangeLog5
-rw-r--r--tests/scripts/functions/eval31
-rw-r--r--variable.h2
7 files changed, 130 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index 409db2b..1f4c058 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,24 @@
2002-10-25 Paul D. Smith <psmith@gnu.org>
+ * 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 5c2c3e2..ac4ccda 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 3282cdf..5a27406 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 4fb811a..3e01572 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.
-
- FILENAME is added to the `read_makefiles' chain.
+ SET_DEFAULT is true if we are allowed to set the default goal. */
- 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 3c62080..e91ccc9 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,8 @@
+2002-10-25 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/functions/eval: Test using $(eval ...) inside
+ conditionals (Bug #1516).
+
2002-10-13 Paul D. Smith <psmith@gnu.org>
* scripts/features/targetvars: Add a test for exporting
diff --git a/tests/scripts/functions/eval b/tests/scripts/functions/eval
index 0d5e3b8..174767d 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 d9cd7f7..f96bd62 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));