[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
make-3.80: `eval' bug
From: |
Toomas Rosin |
Subject: |
make-3.80: `eval' bug |
Date: |
Fri, 25 Oct 2002 01:03:51 +0300 (EEST) |
Hello!
Given this input:
f0 = $(foreach s,foobar,$(firstword $s:))
e0 = $(foreach s,foobar,$(eval $s:))
f1 = $(foreach s,foobar, $(firstword $s:))
e1 = $(foreach s,foobar, $(eval $s:))
f2 = $(foreach s,foobar, $(firstword $s:))
e2 = $(foreach s,foobar, $(eval $s:))
all:
@echo f0 == $(f1)
@echo f1 == $(f1)
@echo f2 == $(f2)
@echo e0 == $(e0)
@echo e1 == $(e1)
@echo e2 == $(e2)
`make all' responds with the following:
f0 == foobar:
f1 == foobar:
f2 == foobar:
e0 ==
e1 == f
e2 == fo
I certainly did not expect this!
All built-in functions *except* `eval' work, when used inside the body
of `foreach', as one would expect. The reason is that all the other
`func_*' functions in functions.c pass its `o' pointer to
variable_buffer_output, but func_eval() does not and, in eval(), a new
`variable_buffer' is created which knows nothing about the incremented
offset of the original `o' wrt the previous `variable_buffer'.
I think that this is a bug, and tried to fix it. I hope my changes do
not break anything, although I had to change the syntax of important
functions. My new `make' has already successfully built emacs-21.2
and make-3.80.
A demonstration of the power of `eval' after this fix:
address@hidden:~ $ cat Makefile
What = $(what)
$(foreach s,$(what), \
$(eval prev = $(this)) \
$(eval this = $s) \
$(eval What = $(wordlist 2,$(words $(What)),$(What))) \
$(eval $(this): $(prev)))
$(what):
@echo making $@ from $^
address@hidden:~ $ make.orig what="a b c d e" e
Makefile:2: *** target pattern contains no `%'. Stop.
address@hidden:~ $ make what="a b c d e" e
making a from
making b from a
making c from b
making d from c
making e from d
address@hidden:~ $
This is precisely the kind of thing I dreamed of being able to do with
the many-rumoured `eval' when 3.80 was not released yet!
The changed read_makefile() no longer checks the value returned by
eval(), but this should be ok, because when eval() returned at all, it
always returned 1 anyway.
Thanks for the wonderful program!
Toomas.
--- ./dep.h.orig Thu Oct 24 22:34:42 2002
+++ ./dep.h Thu Oct 24 22:31:58 2002
@@ -73,6 +73,6 @@
extern struct dep *copy_dep_chain PARAMS ((struct dep *d));
extern struct dep *read_all_makefiles PARAMS ((char **makefiles));
-extern int eval_buffer PARAMS ((char *buffer));
+extern char *eval_buffer PARAMS ((char *o, char *buffer));
extern int update_goal_chain PARAMS ((struct dep *goals, int makefiles));
extern void uniquize_deps PARAMS ((struct dep *));
--- ./function.c.orig Thu Oct 24 22:34:52 2002
+++ ./function.c Thu Oct 24 22:32:01 2002
@@ -1281,9 +1281,7 @@
char **argv;
const char *funcname;
{
- eval_buffer (argv[0]);
-
- return o;
+ return eval_buffer (o, argv[0]);
}
--- ./read.c.orig Thu Oct 24 22:34:48 2002
+++ ./read.c Thu Oct 24 22:32:04 2002
@@ -124,7 +124,7 @@
static struct dep *read_makefiles = 0;
static int eval_makefile PARAMS ((char *filename, int flags));
-static int eval PARAMS ((struct ebuffer *buffer, int flags));
+static char *eval PARAMS ((char *o, struct ebuffer *buffer, int flags));
static long readline PARAMS ((struct ebuffer *ebuf));
static void do_define PARAMS ((char *name, unsigned int namelen,
@@ -281,7 +281,6 @@
struct ebuffer ebuf;
const struct floc *curfile;
int makefile_errno;
- int r;
ebuf.floc.filenm = filename;
ebuf.floc.lineno = 1;
@@ -376,23 +375,23 @@
curfile = reading_file;
reading_file = &ebuf.floc;
- r = eval (&ebuf, !(flags & RM_NO_DEFAULT_GOAL));
+ eval (0, &ebuf, !(flags & RM_NO_DEFAULT_GOAL));
reading_file = curfile;
fclose (ebuf.fp);
free (ebuf.bufstart);
- return r;
+ return 1;
}
-int
-eval_buffer (buffer)
+char *
+eval_buffer (o, buffer)
+ char *o;
char *buffer;
{
struct ebuffer ebuf;
const struct floc *curfile;
- int r;
/* Evaluate the buffer */
@@ -405,11 +404,11 @@
curfile = reading_file;
reading_file = &ebuf.floc;
- r = eval (&ebuf, 1);
+ o = eval (o, &ebuf, 1);
reading_file = curfile;
- return r;
+ return o;
}
@@ -423,8 +422,9 @@
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 (ebuf, set_default)
+static char *
+eval (o, ebuf, set_default)
+ char *o;
struct ebuffer *ebuf;
int set_default;
{
@@ -910,7 +910,7 @@
break;
}
- p2 = variable_expand_string(NULL, lb_next, len);
+ p2 = variable_expand_string(o, lb_next, len);
while (1)
{
lb_next += len;
@@ -1211,7 +1211,7 @@
free ((char *) commands);
- return 1;
+ return o;
}
- make-3.80: `eval' bug,
Toomas Rosin <=