bug-make
[Top][All Lists]
Advanced

[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;
 }
 
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]