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.
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;
+}
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;
}
return read_makefiles;
}
\f
+/* 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;
+}
+\f
static int
eval_makefile (char *filename, int flags)
{
eval_buffer (char *buffer)
{
struct ebuffer ebuf;
+ struct conditionals *saved;
+ struct conditionals new;
const struct floc *curfile;
int r;
curfile = reading_file;
reading_file = &ebuf.floc;
+ saved = install_conditionals (&new);
+
r = eval (&ebuf, 1);
+ restore_conditionals (saved);
+
reading_file = curfile;
return r;
\f
/* 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)
/* 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. */
}
}
- /* 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;
}
+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
&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;
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));