From 9b0a3d91ea594ff1afe7b8ec83ff41ba828d243b Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Sat, 5 Feb 2000 07:37:40 +0000 Subject: [PATCH] * Fix PR/1407. * Keep filename/lineno information for variables, for debugging. --- ChangeLog | 29 ++++++ NEWS | 17 ++-- commands.c | 4 +- expand.c | 15 +-- filedef.h | 8 +- read.c | 11 ++- rule.c | 4 +- tests/ChangeLog | 4 + tests/scripts/features/patspecific_vars | 9 ++ variable.c | 117 ++++++++++++++---------- variable.h | 32 +++++-- 11 files changed, 159 insertions(+), 91 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7ed88a7f..8fdd6d70 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +2000-02-04 Paul D. Smith + + * variable.c (print_variable): Write out filename/linenumber + information for the variable definition if present. + (define_variable_in_set): Store filename information if provided. + (define_variable, define_variable_for_file): Removed. + (try_variable_definition): Use define_variable_loc() to keep + variable definition location information. + * read.c (read_makefile): Keep variable definition location info. + (do_define): Ditto. + (record_target_var): Ditto. + * variable.h (define_variable_in_set): New fileinfo argument. + (define_variable, define_variable_loc, define_variable_for_file): + Declare new macros. + + Fix PR/1407: + + * filedef.h (struct file): Rename patvar to pat_variables and make + it just a variable_set_list; we need our own copy of the pattern + variable's variable set list here to avoid overwriting the global + one. + * variable.c (initialize_file_variables): Move the instantiation + of the pat_variables pointer here. Only do the search after we're + done reading the makefiles so we don't search too early. If + there's a pat_variables value, set up the variables next ptr. + * expand.c (variable_expand_for_file): Remove the setup of the + pat_variables info; it's done earlier now to ensure the parent's + pattern variables are set up correctly as well. + 2000-01-25 Paul D. Smith Change gettext support to use the simplified version in libit 0.7. diff --git a/NEWS b/NEWS index 0dfc96d8..9fe1e020 100644 --- a/NEWS +++ b/NEWS @@ -23,8 +23,8 @@ Version 3.79 be used within make build scripts. However, using them there is not proper behavior: they are meant to be passed to subshells via the environment. Unfortunately the values were not quoted properly to be - passed through the environment. This meant that some invocations of - make didn't properly pass values to submakes. + passed through the environment. This meant that make didn't properly + pass some types of command line values to submakes. With this version we change that behavior: now these variables are quoted properly for passing through the environment, which is the @@ -32,9 +32,9 @@ Version 3.79 explicitly within a make rule you may need to re-examine your use for correctness given this change. -* A new psuedo-target, .NOTPARALLEL, is defined. If set the current - makefile is always run serially regardless of the value of -j. Any - submakes will still be run in parallel if -j was specified. +* A new psuedo-target .NOTPARALLEL is available. If defined, the + current makefile is run serially regardless of the value of -j. + However, submakes are still eligible for parallel execution. * The $(call ...) function doesn't expand its arguments automatically anymore. This allows you to put builtin functions like "if" and @@ -48,8 +48,11 @@ Version 3.79 "normal" targets (not makefiles) were deemed out of date and in need of being rebuilt. - Note that the -d option behaves as before: all debugging information - is generated. + Note that the -d option behaves as before: it takes no arguments and + all debugging information is generated. + +* The `-p' (print database) output now includes filename and linenumber + information for variable definitions, to help debugging. * Hartmut Becker provided many updates for the VMS port of GNU make. See the readme.vms file for more details. diff --git a/commands.c b/commands.c index 8a8d227f..75b33993 100644 --- a/commands.c +++ b/commands.c @@ -108,7 +108,7 @@ set_file_variables (file) less = at; #define DEFINE_VARIABLE(name, len, value) \ - (void) define_variable_for_file (name, len, value, o_automatic, 0, file) + (void) define_variable_for_file (name,len,value,o_automatic,0,file) /* Define the variables. */ @@ -354,7 +354,7 @@ execute_file_commands (file) /* First set the automatic variables according to this file. */ - initialize_file_variables (file); + initialize_file_variables (file, 0); set_file_variables (file); diff --git a/expand.c b/expand.c index a7cfcdbf..f15da026 100644 --- a/expand.c +++ b/expand.c @@ -445,7 +445,7 @@ variable_expand_for_file (line, file) register struct file *file; { char *result; - struct variable_set_list *save, *fnext; + struct variable_set_list *save; if (file == 0) return variable_expand (line); @@ -456,22 +456,9 @@ variable_expand_for_file (line, file) reading_file = &file->cmds->fileinfo; else reading_file = 0; - fnext = file->variables->next; - /* See if there's a pattern-specific variable struct for this target. */ - if (!file->pat_searched) - { - file->patvar = lookup_pattern_var(file->name); - file->pat_searched = 1; - } - if (file->patvar != 0) - { - file->patvar->vars->next = fnext; - file->variables->next = file->patvar->vars; - } result = variable_expand (line); current_variable_set_list = save; reading_file = 0; - file->variables->next = fnext; return result; } diff --git a/filedef.h b/filedef.h index f39b82a3..8712e986 100644 --- a/filedef.h +++ b/filedef.h @@ -48,6 +48,10 @@ struct file /* List of variable sets used for this file. */ struct variable_set_list *variables; + /* Pattern-specific variable reference for this target, or null if there + isn't one. Also see the pat_searched flag, below. */ + struct variable_set_list *pat_variables; + /* Immediate dependent that caused this target to be remade, or nil if there isn't one. */ struct file *parent; @@ -56,10 +60,6 @@ struct file the same file. Otherwise this is null. */ struct file *double_colon; - /* Pattern-specific variable reference for this target, or null if there - isn't one. Also see the pat_searched flag, below. */ - struct pattern_var *patvar; - short int update_status; /* Status of the last attempt to update, or -1 if none has been made. */ diff --git a/read.c b/read.c index 67d78d05..67b2a2dd 100644 --- a/read.c +++ b/read.c @@ -609,7 +609,7 @@ read_makefile (filename, flags) { v = lookup_variable (p, len); if (v == 0) - v = define_variable (p, len, "", o_file, 0); + v = define_variable_loc (p, len, "", o_file, 0, &fileinfo); v->export = v_export; } } @@ -626,7 +626,7 @@ read_makefile (filename, flags) { v = lookup_variable (p, len); if (v == 0) - v = define_variable (p, len, "", o_file, 0); + v = define_variable_loc (p, len, "", o_file, 0, &fileinfo); v->export = v_noexport; } } @@ -1116,7 +1116,8 @@ do_define (name, namelen, origin, infile, flocp) definition[0] = '\0'; else definition[idx - 1] = '\0'; - (void) define_variable (var, strlen (var), definition, origin, 1); + (void) define_variable_loc (var, strlen (var), definition, origin, + 1, flocp); free (definition); freebuffer (&lb); return; @@ -1454,7 +1455,7 @@ record_target_var (filenames, defn, two_colon, origin, flocp) /* Get a file reference for this file, and initialize it. */ f = enter_file (name); - initialize_file_variables (f); + initialize_file_variables (f, 1); vlist = f->variables; fname = f->name; } @@ -1477,7 +1478,7 @@ record_target_var (filenames, defn, two_colon, origin, flocp) gv = lookup_variable (v->name, len); if (gv && (gv->origin == o_env_override || gv->origin == o_command)) define_variable_in_set (v->name, len, gv->value, gv->origin, - gv->recursive, vlist->set); + gv->recursive, vlist->set, flocp); } /* Free name if not needed further. */ diff --git a/rule.c b/rule.c index 5933777a..2b4456e5 100644 --- a/rule.c +++ b/rule.c @@ -607,12 +607,12 @@ lookup_pattern_var (target) continue; /* Compare the text in the pattern after the stem, if any. - We could test simply use streq, but this way we compare the + We could test simply using streq, but this way we compare the first two characters immediately. This saves time in the very common case where the first character matches because it is a period. */ if (*p->suffix == stem[stemlen] - && (*p->suffix == '\0'|| streq (&p->suffix[1], &stem[stemlen+1]))) + && (*p->suffix == '\0' || streq (&p->suffix[1], &stem[stemlen+1]))) break; } diff --git a/tests/ChangeLog b/tests/ChangeLog index 68825fa5..368a30cb 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,7 @@ +2000-02-04 Paul D. Smith + + * scripts/features/patspecific_vars: Add a test for PR/1407. + 2000-01-23 Paul D. Smith * scripts/features/include: Remove a check; the fix caused more diff --git a/tests/scripts/features/patspecific_vars b/tests/scripts/features/patspecific_vars index 0684a80f..7feb6876 100644 --- a/tests/scripts/features/patspecific_vars +++ b/tests/scripts/features/patspecific_vars @@ -19,6 +19,8 @@ t%.x: BAR = four %.x: override BAZ = three one.x: override FOO = one one.x two.x three.x: ; @echo $(FOO) $(BAR) $(BAZ) +four.x: baz ; @echo $(FOO) $(BAR) $(BAZ) +baz: ; @echo $(FOO) $(BAR) $(BAZ) EOF close(MAKEFILE); @@ -37,4 +39,11 @@ $answer = "one two three\nfoo four baz\nfoo bar three\n"; $answer = "one two three\nfoo four five\nfoo bar three\n"; &compare_output($answer,&get_logfile(1)); + +# TEST #3 -- make sure patterns are inherited properly + +&run_make_with_options($makefile, "four.x", &get_logfile); +$answer = "foo two three\nfoo two three\n"; +&compare_output($answer,&get_logfile(1)); + 1; diff --git a/variable.c b/variable.c index 6d105b29..58af1219 100644 --- a/variable.c +++ b/variable.c @@ -23,6 +23,7 @@ Boston, MA 02111-1307, USA. */ #include "job.h" #include "commands.h" #include "variable.h" +#include "rule.h" #ifdef WINDOWS32 #include "pathstuff.h" #endif @@ -58,13 +59,14 @@ static struct variable *lookup_variable_in_set PARAMS ((char *name, that it should be recursively re-expanded. */ struct variable * -define_variable_in_set (name, length, value, origin, recursive, set) +define_variable_in_set (name, length, value, origin, recursive, set, flocp) char *name; unsigned int length; char *value; enum variable_origin origin; int recursive; struct variable_set *set; + const struct floc *flocp; { register unsigned int i; register unsigned int hashval; @@ -99,6 +101,10 @@ define_variable_in_set (name, length, value, origin, recursive, set) if (v->value != 0) free (v->value); v->value = xstrdup (value); + if (flocp != 0) + v->fileinfo = *flocp; + else + v->fileinfo.filenm = 0; v->origin = origin; v->recursive = recursive; } @@ -110,6 +116,10 @@ define_variable_in_set (name, length, value, origin, recursive, set) v = (struct variable *) xmalloc (sizeof (struct variable)); v->name = savestring (name, length); v->value = xstrdup (value); + if (flocp != 0) + v->fileinfo = *flocp; + else + v->fileinfo.filenm = 0; v->origin = origin; v->recursive = recursive; v->expanding = 0; @@ -120,35 +130,6 @@ define_variable_in_set (name, length, value, origin, recursive, set) set->table[hashval] = v; return v; } - -/* Define a variable in the current variable set. */ - -struct variable * -define_variable (name, length, value, origin, recursive) - char *name; - unsigned int length; - char *value; - enum variable_origin origin; - int recursive; -{ - return define_variable_in_set (name, length, value, origin, recursive, - current_variable_set_list->set); -} - -/* Define a variable in FILE's variable set. */ - -struct variable * -define_variable_for_file (name, length, value, origin, recursive, file) - char *name; - unsigned int length; - char *value; - enum variable_origin origin; - int recursive; - struct file *file; -{ - return define_variable_in_set (name, length, value, origin, recursive, - file->variables->set); -} /* Lookup a variable whose name is a string starting at NAME and with LENGTH chars. NAME need not be null-terminated. @@ -272,13 +253,17 @@ lookup_variable_in_set (name, length, set) /* Initialize FILE's variable set list. If FILE already has a variable set list, the topmost variable set is left intact, but the the rest of the - chain is replaced with FILE->parent's setlist. */ + chain is replaced with FILE->parent's setlist. If we're READing a + makefile, don't do the pattern variable search now, since the pattern + variable might not have been defined yet. */ void -initialize_file_variables (file) +initialize_file_variables (file, reading) struct file *file; + int reading; { register struct variable_set_list *l = file->variables; + if (l == 0) { l = (struct variable_set_list *) @@ -296,9 +281,35 @@ initialize_file_variables (file) l->next = &global_setlist; else { - initialize_file_variables (file->parent); + initialize_file_variables (file->parent, reading); l->next = file->parent->variables; } + + /* If we're not reading makefiles and we haven't looked yet, see if + we can find a pattern variable. */ + + if (!reading && !file->pat_searched) + { + struct pattern_var *p = lookup_pattern_var (file->name); + + file->pat_searched = 1; + if (p != 0) + { + /* If we found one, insert it between the current target's + variables and the next set, whatever it is. */ + file->pat_variables = (struct variable_set_list *) + xmalloc (sizeof (struct variable_set_list)); + file->pat_variables->set = p->vars->set; + } + } + + /* If we have a pattern variable match, set it up. */ + + if (file->pat_variables != 0) + { + file->pat_variables->next = l->next; + l->next = file->pat_variables; + } } /* Pop the top set off the current variable set list, @@ -947,8 +958,9 @@ try_variable_definition (flocp, line, origin, target_var) if (*p == '\\') *p = '/'; } - v = define_variable (expanded_name, strlen (expanded_name), - shellpath, origin, flavor == f_recursive); + v = define_variable_loc (expanded_name, strlen (expanded_name), + shellpath, origin, flavor == f_recursive, + flocp); } else { @@ -987,8 +999,9 @@ try_variable_definition (flocp, line, origin, target_var) if (*p == '\\') *p = '/'; } - v = define_variable (expanded_name, strlen (expanded_name), - shellpath, origin, flavor == f_recursive); + v = define_variable_loc (expanded_name, strlen (expanded_name), + shellpath, origin, + flavor == f_recursive, flocp); } else v = lookup_variable (expanded_name, strlen (expanded_name)); @@ -1009,15 +1022,16 @@ try_variable_definition (flocp, line, origin, target_var) * set new value for SHELL variable. */ if (find_and_set_default_shell(value)) { - v = define_variable (expanded_name, strlen (expanded_name), - default_shell, origin, flavor == f_recursive); + v = define_variable_loc (expanded_name, strlen (expanded_name), + default_shell, origin, flavor == f_recursive, + flocp); no_default_sh_exe = 0; } } else #endif - v = define_variable (expanded_name, strlen (expanded_name), - value, origin, flavor == f_recursive); + v = define_variable_loc (expanded_name, strlen (expanded_name), value, + origin, flavor == f_recursive, flocp); v->append = append; @@ -1040,32 +1054,35 @@ print_variable (v, prefix) switch (v->origin) { case o_default: - origin = "default"; + origin = _("default"); break; case o_env: - origin = "environment"; + origin = _("environment"); break; case o_file: - origin = "makefile"; + origin = _("makefile"); break; case o_env_override: - origin = "environment under -e"; + origin = _("environment under -e"); break; case o_command: - origin = "command line"; + origin = _("command line"); break; case o_override: - origin = "`override' directive"; + origin = _("`override' directive"); break; case o_automatic: - origin = "automatic"; + origin = _("automatic"); break; case o_invalid: default: abort (); } - printf ("# %s\n", origin); - + fputs ("# ", stdout); + fputs (origin, stdout); + if (v->fileinfo.filenm) + printf (" (from `%s', line %lu)", v->fileinfo.filenm, v->fileinfo.lineno); + putchar ('\n'); fputs (prefix, stdout); /* Is this a `define'? */ diff --git a/variable.h b/variable.h index 19ec31e8..d449ef82 100644 --- a/variable.h +++ b/variable.h @@ -40,6 +40,7 @@ struct variable struct variable *next; /* Link in the chain. */ char *name; /* Variable name. */ char *value; /* Variable value. */ + struct floc fileinfo; /* Where the variable was defined. */ enum variable_origin origin ENUM_BITFIELD (3); /* Variable origin. */ unsigned int recursive:1; /* Gets recursively re-evaluated. */ @@ -101,19 +102,36 @@ extern struct variable_set_list *create_new_variable_set PARAMS ((void)); extern struct variable_set_list *push_new_variable_scope PARAMS ((void)); extern void pop_variable_scope PARAMS ((void)); extern void define_automatic_variables PARAMS ((void)); -extern void initialize_file_variables PARAMS ((struct file *file)); +extern void initialize_file_variables PARAMS ((struct file *file, int read)); extern void print_file_variables PARAMS ((struct file *file)); extern void print_variable_set PARAMS ((struct variable_set *set, char *prefix)); extern void merge_variable_set_lists PARAMS ((struct variable_set_list **setlist0, struct variable_set_list *setlist1)); extern struct variable *try_variable_definition PARAMS ((const struct floc *flocp, char *line, enum variable_origin origin, int target_var)); extern struct variable *lookup_variable PARAMS ((char *name, unsigned int length)); -extern struct variable *define_variable PARAMS ((char *name, unsigned int length, char *value, - enum variable_origin origin, int recursive)); -extern struct variable *define_variable_in_set PARAMS ((char *name, unsigned int length, - char *value, enum variable_origin origin, int recursive, struct variable_set *set)); -extern struct variable *define_variable_for_file PARAMS ((char *name, unsigned int length, - char *value, enum variable_origin origin, int recursive, struct file *file)); + +extern struct variable *define_variable_in_set + PARAMS ((char *name, unsigned int length, char *value, + enum variable_origin origin, int recursive, + struct variable_set *set, const struct floc *flocp)); + +/* Define a variable in the current variable set. */ + +#define define_variable(n,l,v,o,r) \ + define_variable_in_set((n),(l),(v),(o),(r),\ + current_variable_set_list->set,NILF) + +/* Define a variable with a location in the current variable set. */ + +#define define_variable_loc(n,l,v,o,r,f) \ + define_variable_in_set((n),(l),(v),(o),(r),\ + current_variable_set_list->set,(f)) + +/* Define a variable in FILE's variable set. */ + +#define define_variable_for_file(n,l,v,o,r,f) \ + define_variable_in_set((n),(l),(v),(o),(r),(f)->variables->set,NILF) + extern char **target_environment PARAMS ((struct file *file)); extern int export_all_variables;