diff options
author | Paul Smith <psmith@gnu.org> | 2002-08-08 00:11:19 +0000 |
---|---|---|
committer | Paul Smith <psmith@gnu.org> | 2002-08-08 00:11:19 +0000 |
commit | f2ceb0d68aa780e57641e50d972fac3b6e70bd58 (patch) | |
tree | 73853f27fe9a08b2ba2938057f1f3ccc51597d06 | |
parent | bccb277dda1a4dcc6729824a7c9d544086f147c3 (diff) | |
download | gunmake-f2ceb0d68aa780e57641e50d972fac3b6e70bd58.tar.gz |
Incorporate some VMS fixes.
Add -B option docs.
Add .VARIABLES variable.
Add a few new tests.
Add a new translation: Swedish
-rw-r--r-- | ChangeLog | 36 | ||||
-rw-r--r-- | NEWS | 11 | ||||
-rw-r--r-- | config.h-vms.template | 17 | ||||
-rw-r--r-- | dir.c | 2 | ||||
-rw-r--r-- | doc/make.texi | 60 | ||||
-rw-r--r-- | hash.h | 4 | ||||
-rw-r--r-- | main.c | 12 | ||||
-rw-r--r-- | make.h | 4 | ||||
-rw-r--r-- | makefile.com | 2 | ||||
-rw-r--r-- | po/ChangeLog | 16 | ||||
-rw-r--r-- | po/LINGUAS | 2 | ||||
-rw-r--r-- | read.c | 11 | ||||
-rw-r--r-- | remake.c | 21 | ||||
-rw-r--r-- | tests/ChangeLog | 13 | ||||
-rw-r--r-- | tests/scripts/misc/general3 | 19 | ||||
-rw-r--r-- | tests/scripts/options/dash-B | 43 | ||||
-rw-r--r-- | tests/scripts/variables/special | 68 | ||||
-rw-r--r-- | variable.c | 51 | ||||
-rw-r--r-- | variable.h | 1 |
19 files changed, 317 insertions, 76 deletions
@@ -1,6 +1,26 @@ +2002-08-02 Paul D. Smith <psmith@gnu.org> + + * NEWS: Remove the mention of .TARGETS; we aren't going to publish + this one because it's too hard to get right. We'll look at it for + a future release. + 2002-08-01 Paul D. Smith <psmith@gnu.org> - Add new introspection variables .VARIABLES and .TARGETS. + * main.c (switches): Add a new option, -B (--always-make). If + specified, make will rebuild all targets that it encounters even + if they don't appear to be out of date. + (always_make_flag): New flag. + * make.h: Extern always_make_flag. + * remake.c (update_file_1): Check always_make_flag; if it's set we + will always rebuild any target we can, even if none of its + prerequisites are newer. + * NEWS: Mention it. + + * doc/make.texi (Shell Function): Make it clear that make + variables marked as "export" are not passed to instances of the + shell function. + + Add new introspection variable .VARIABLES and .TARGETS. * variable.c (handle_special_var): New function. If the variable reference passed in is "special" (.VARIABLES or .TARGETS), @@ -23,6 +43,20 @@ (target_environment): Use the "exportable" flag instead of re-checking the name here... an efficiency improvement. +2002-07-31 Paul D. Smith <psmith@gnu.org> + + * config.h-vms.template: Updates to build on VMS. Thanks to + Brian_Benning@aksteel.com for helping verify the build. + * makefile.com: Build the new hash.c file. + * hash.h: Use strcpmi(), not stricmp(), in the + HAVE_CASE_INSENSITIVE_FS case. + +2002-07-30 Paul D. Smith <psmith@gnu.org> + + * hash.h (ISTRING_COMPARE, return_ISTRING_COMPARE): Add missing + backslashes to the HAVE_CASE_INSENSITIVE_FS case. + Reported by <Brian_Benning@aksteel.com>. + 2002-07-10 Paul D. Smith <psmith@gnu.org> * variable.c (pop_variable_scope): Remove variable made unused by @@ -44,10 +44,13 @@ Version 3.80 list when a makefile is just being read (before any includes) is the name of the current makefile. -* GNU make now supports some simple introspection capability: two new - built-in variables are defined: $(.VARIABLES) and $(.TARGETS). These - expand to a complete list of variables and targets, respectively, - defined by all makefiles at the time the variables are expanded. +* A new built-in variable is defined: $(.VARIABLES). When it is + expanded it returns a complete list of variable names defined by all + makefiles at that moment. + +* A new command-line option is defined, -B or --always-make. If + specified GNU make will consider all targets out-of-date even if they + would otherwise not be. * The arguments to $(call ...) functions were being stored in $1, $2, etc. as recursive variables, even though they are fully expanded diff --git a/config.h-vms.template b/config.h-vms.template index 1dbf04c..7d7d9b0 100644 --- a/config.h-vms.template +++ b/config.h-vms.template @@ -9,13 +9,6 @@ /* #undef _ALL_SOURCE */ #endif -/* Define if using alloca.c. */ -/* #undef C_ALLOCA */ -/* maybe this should be placed into make.h */ -#if defined(__VAX) && defined(__DECC) -#define alloca(n) __ALLOCA(n) -#endif - /* Define to 1 if NLS is requested. */ /* #undef ENABLE_NLS */ @@ -345,6 +338,9 @@ /* Define if you have the sun library (-lsun). */ /* #undef HAVE_LIBSUN */ +/* Use high resolution file timestamps if nonzero. */ +#define FILE_TIMESTAMP_HI_RES 0 + /* Define for case insensitve filenames */ #define HAVE_CASE_INSENSITIVE_FS 1 @@ -396,5 +392,12 @@ #define PARAMS(protos) () #endif /* C++ or ANSI C. */ +/* Define if using alloca.c. */ +/* #undef C_ALLOCA */ +/* maybe this should be placed into make.h */ +#if defined(__VAX) && defined(__DECC) +#define alloca(n) __ALLOCA(n) +#endif + /* Build host information. */ #define MAKE_HOST "VMS" @@ -546,7 +546,7 @@ find_directory (name) if (dc->dirstream == 0) /* Couldn't open the directory. Mark this by setting the `files' member to a nil pointer. */ - hash_free (&dc->dirfiles, 0); + dc->dirfiles.ht_vec = 0; else { hash_init (&dc->dirfiles, DIRFILE_BUCKETS, diff --git a/doc/make.texi b/doc/make.texi index 291a294..b36383a 100644 --- a/doc/make.texi +++ b/doc/make.texi @@ -68,14 +68,21 @@ Published by the Free Software Foundation @* Boston, MA 02111-1307 USA @* ISBN @value{ISBN} @* -Maintenance and updates since Version 3.76 by Paul D. Smith. - Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or -any later version published by the Free Software Foundation; with no -Invariant Sections, with no Front-Cover Texts, and with no Back-Cover -Texts. A copy of the license is included in the section entitled +any later version published by the Free Software Foundation; with the +Invariant Sections being ``GNU General Public License'', the Front-Cover +Texts being ``A GNU Manual'', and with the Back-Cover Texts being as in +(a) below. A copy of the license is included in the section entitled ``GNU Free Documentation License''. + +(a) The FSF's Back-Cover Text is: + +@quotation + You have freedom to copy and modify this GNU Manual, like GNU + software. Copies published by the Free Software Foundation raise + funds for GNU development. +@end quotation @sp 2 Cover art by Etienne Suvasa. @end titlepage @@ -1240,9 +1247,9 @@ variable definitions. @cindex makefiles, and special variables @cindex special variables -GNU @code{make} also supports two other special variables. Note that -any value you assign to these variables will be ignored; they will -always return their special value. +GNU @code{make} also supports a special variable. Note that any value +you assign to this variable will be ignored; it will always return its +special value. @vindex $(.VARIABLES) @vindex .VARIABLES @r{(list of variables)} @@ -1254,15 +1261,15 @@ variables which have empty values, as well as built-in variables does not include any variables which are only defined in a target-specific context. -@vindex $(.TARGETS) -@vindex .TARGETS @r{(list of targets)} -The second special variable is @code{.TARGETS}. When expanded, the -value consists of a list of all targets defined in all makefiles read -up until that point. Note it's not enough for a file to be simply -mentioned in the makefile to be listed in this variable, even if it -would match an implicit rule and become an ``implicit target''. The -file must appear as a target, on the left-hand side of a ``:'', to be -considered a target for the purposes of this variable. +@c @vindex $(.TARGETS) +@c @vindex .TARGETS @r{(list of targets)} +@c The second special variable is @code{.TARGETS}. When expanded, the +@c value consists of a list of all targets defined in all makefiles read +@c up until that point. Note it's not enough for a file to be simply +@c mentioned in the makefile to be listed in this variable, even if it +@c would match an implicit rule and become an ``implicit target''. The +@c file must appear as a target, on the left-hand side of a ``:'', to be +@c considered a target for the purposes of this variable. @node Remaking Makefiles, Overriding Makefiles, Special Variables, Makefiles @section How Makefiles Are Remade @@ -6542,10 +6549,12 @@ removes the trailing (carriage-return and) newline, if it's the last thing in the result.@refill The commands run by calls to the @code{shell} function are run when the -function calls are expanded. In most cases, this is when the makefile is -read in. The exception is that function calls in the commands of the rules -are expanded when the commands are run, and this applies to @code{shell} -function calls like all others. +function calls are expanded (@pxref{Reading Makefiles, , How +@code{make} Reads a Makefile}). Because this function involves +spawning a new shell, you should carefully consider the performance +implications of using the @code{shell} function within recursively +expanded variables vs. simply expanded variables (@pxref{Flavors, ,The +Two Flavors of Variables}). Here are some examples of the use of the @code{shell} function: @@ -7093,6 +7102,15 @@ Here is a table of all the options @code{make} understands: @cindex @code{-m} These options are ignored for compatibility with other versions of @code{make}. +@item -B +@cindex @code{-B} +@itemx --always-make +@cindex @code{--always-make} +Consider all targets out-of-date. GNU @code{make} proceeds to +consider targets and their prerequisites using the normal algorithms; +however, all these targets are remade, regardless of the status of +their prerequisites. + @item -C @var{dir} @cindex @code{-C} @itemx --directory=@var{dir} @@ -173,10 +173,10 @@ extern void *hash_deleted_item; } while (0) #define ISTRING_COMPARE(X, Y, RESULT) do { \ - _RESULT_ = stricmp ((X), (Y)); + _RESULT_ = strcmpi ((X), (Y)); \ } while (0) #define return_ISTRING_COMPARE(X, Y) do { \ - return stricmp ((X), (Y)); + return strcmpi ((X), (Y)); \ } while (0) #else @@ -252,6 +252,11 @@ static int print_usage_flag = 0; for each reference to an undefined variable. */ int warn_undefined_variables_flag; + +/* If nonzero, always build all targets, regardless of whether + they appear out of date or not. */ + +int always_make_flag = 0; /* The table of command switches. */ @@ -260,6 +265,9 @@ static const struct command_switch switches[] = { 'b', ignore, 0, 0, 0, 0, 0, 0, 0, 0, N_("Ignored for compatibility") }, + { 'B', flag, (char *) &always_make_flag, 1, 1, 0, 0, 0, + "always-make", 0, + N_("Unconditionally make all targets") }, { 'C', string, (char *) &directories, 0, 0, 0, 0, 0, "directory", N_("DIRECTORY"), N_("Change to DIRECTORY before doing anything") }, @@ -989,8 +997,8 @@ int main (int argc, char ** argv) #endif /* Initialize the special variables. */ - define_variable (".VARIABLES", 10, "", o_default, 0); - define_variable (".TARGETS", 8, "", o_default, 0); + define_variable (".VARIABLES", 10, "", o_default, 0)->special = 1; + /* define_variable (".TARGETS", 8, "", o_default, 0); */ /* Read in variables from the environment. It is important that this be done before $(MAKE) is figured out so its definitions will not be @@ -194,6 +194,8 @@ extern unsigned int get_path_max PARAMS ((void)); # include <unixlib.h> # include <unixio.h> # include <perror.h> +/* Needed to use alloca on VMS. */ +# include <builtins.h> #endif #ifndef __attribute__ @@ -485,7 +487,7 @@ extern const struct floc *reading_file; extern char **environ; extern int just_print_flag, silent_flag, ignore_errors_flag, keep_going_flag; -extern int print_data_base_flag, question_flag, touch_flag; +extern int print_data_base_flag, question_flag, touch_flag, always_make_flag; extern int env_overrides, no_builtin_rules_flag, no_builtin_variables_flag; extern int print_version_flag, print_directory_flag; extern int warn_undefined_variables_flag, posix_pedantic, not_parallel; diff --git a/makefile.com b/makefile.com index 5a0f884..4d55923 100644 --- a/makefile.com +++ b/makefile.com @@ -49,7 +49,7 @@ $ lopt = "/debug" $ else $ lopt = "" $ endif -$ filelist = "alloca ar arscan commands default dir expand file function implicit job main misc read remake remote-stub rule signame variable version vmsfunctions vmsify vpath [.glob]glob [.glob]fnmatch getopt1 getopt" +$ filelist = "alloca ar arscan commands default dir expand file function hash implicit job main misc read remake remote-stub rule signame variable version vmsfunctions vmsify vpath [.glob]glob [.glob]fnmatch getopt1 getopt" $ copy config.h-vms config.h $ n=0 $ open/write optf make.opt diff --git a/po/ChangeLog b/po/ChangeLog index 6c53a00..6c5321a 100644 --- a/po/ChangeLog +++ b/po/ChangeLog @@ -1,3 +1,7 @@ +2002-08-02 Paul D. Smith <psmith@gnu.org> + + * LINGUAS: Add a new translation for Swedish (sv). + 2002-04-21 Paul D. Smith <psmith@gnu.org> * LINGUAS, hr.po: Added new translation: Croatian. @@ -7,15 +11,3 @@ * .cvsignore: Moved from i18n to here. * POTFILES.in, LINGUAS, Makevars: Created. - -2002-04-21 gettextize <bug-gnu-gettext@gnu.org> - - * Makefile.in.in: New file, from gettext-0.11.1. - * Rules-quot: New file, from gettext-0.11.1. - * boldquot.sed: New file, from gettext-0.11.1. - * en@boldquot.header: New file, from gettext-0.11.1. - * en@quot.header: New file, from gettext-0.11.1. - * insert-header.sin: New file, from gettext-0.11.1. - * quot.sed: New file, from gettext-0.11.1. - * remove-potcdate.sin: New file, from gettext-0.11.1. - @@ -1,5 +1,5 @@ # Set of available languages: 14 languages -da de es fr gl he hr ja ko nl pl pt_BR ru tr +da de es fr gl he hr ja ko nl pl pt_BR sv ru tr # Can't seem to get en@quot and en@boldquot to build properly? @@ -380,7 +380,9 @@ eval_makefile (filename, flags) reading_file = curfile; - free(ebuf.bufstart); + fclose (ebuf.fp); + + free (ebuf.bufstart); return r; } @@ -2564,7 +2566,12 @@ readline (ebuf) if (ferror (ebuf->fp)) pfatal_with_name (ebuf->floc.filenm); - return nlines ? nlines : -1; + /* If we found some lines, return how many. + If we didn't, but we did find _something_, that indicates we read the last + line of a file with no final newline; return 1. + If we read nothing, we're at EOF; return -1. */ + + return nlines ? nlines : p == ebuf->bufstart ? -1 : 1; } /* Parse the next "makefile word" from the input buffer, and return info @@ -350,7 +350,6 @@ update_file_1 (file, depth) int dep_status = 0; register struct dep *d, *lastd; int running = 0; - int maybe_make; DBF (DB_VERBOSE, _("Considering target file `%s'.\n")); @@ -437,6 +436,7 @@ update_file_1 (file, depth) while (d != 0) { FILE_TIMESTAMP mtime; + int maybe_make; check_renamed (d->file); @@ -492,7 +492,7 @@ update_file_1 (file, depth) /* Now we know whether this target needs updating. If it does, update all the intermediate files we depend on. */ - if (must_make) + if (must_make || always_make_flag) { for (d = file->deps; d != 0; d = d->next) if (d->file->intermediate) @@ -544,7 +544,7 @@ update_file_1 (file, depth) file->update_status = dep_status; notice_finished_file (file); - depth--; + --depth; DBF (DB_VERBOSE, _("Giving up on target file `%s'.\n")); @@ -567,7 +567,7 @@ update_file_1 (file, depth) file's bookkeeping (updated, but not_started is bogus state). */ set_command_state (file, cs_not_started); - /* Now record which dependencies are more + /* Now record which prerequisites are more recent than this file, so we can define $?. */ deps_changed = 0; @@ -636,12 +636,18 @@ update_file_1 (file, depth) DBF (DB_BASIC, _("Target `%s' is double-colon and has no prerequisites.\n")); } - else if (!noexist && file->is_target && !deps_changed && file->cmds == 0) + else if (!noexist && file->is_target && !deps_changed && file->cmds == 0 + && !always_make_flag) { must_make = 0; DBF (DB_VERBOSE, _("No commands for `%s' and no prerequisites actually changed.\n")); } + else if (!must_make && file->cmds != 0 && always_make_flag) + { + must_make = 1; + DBF (DB_VERBOSE, _("Making `%s' due to always-make flag.\n")); + } if (!must_make) { @@ -839,7 +845,6 @@ check_dep (file, depth, this_mtime, must_make_ptr) { struct dep *d; int dep_status = 0; - int maybe_make; ++depth; start_updating (file); @@ -888,12 +893,14 @@ check_dep (file, depth, this_mtime, must_make_ptr) recent than the file on whose behalf we are checking. */ else { - register struct dep *lastd; + struct dep *lastd; lastd = 0; d = file->deps; while (d != 0) { + int maybe_make; + if (is_updating (d->file)) { error (NILF, _("Circular %s <- %s dependency dropped."), diff --git a/tests/ChangeLog b/tests/ChangeLog index 2dc997f..387c08f 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,16 @@ +2002-08-07 Paul D. Smith <psmith@gnu.org> + + * scripts/misc/general3: Add a test for makefiles that don't end + in newlines. + + * scripts/variables/special: Create tests for the special + variables (.VARIABLES and .TARGETS). Comment out .TARGETS test + for now as it's not yet supported. + +2002-08-01 Paul D. Smith <psmith@gnu.org> + + * scripts/options/dash-B: Add a test for the new -B option. + 2002-07-11 Paul D. Smith <psmith@gnu.org> * run_make_tests.pl (valid_option): Add support for Valgrind diff --git a/tests/scripts/misc/general3 b/tests/scripts/misc/general3 index a265f71..2421ed4 100644 --- a/tests/scripts/misc/general3 +++ b/tests/scripts/misc/general3 @@ -5,12 +5,14 @@ This tests random features of the parser that need to be supported, and which have either broken at some point in the past or seem likely to break."; +$makefile2 = &get_tmpfile; + open(MAKEFILE,"> $makefile"); # The contents of the Makefile ... print MAKEFILE <<EOF; -\# We want to allow both empty commands _and_ commands that resolve to empty. +# We want to allow both empty commands _and_ commands that resolve to empty. EMPTY = .PHONY: all a1 a2 a3 a4 @@ -36,10 +38,21 @@ EOF close(MAKEFILE); &run_make_with_options($makefile,"",&get_logfile); - -# Create the answer to what should be produced by this Makefile $answer = "$make_name: Nothing to be done for `all'.\n"; +&compare_output($answer,&get_logfile(1)); + + +# TEST 2 +# Make sure files without trailing newlines are handled properly. + +open(MAKEFILE, "> $makefile2"); +print MAKEFILE "all:;\@echo FOO = \$(FOO)\nFOO = foo"; +close(MAKEFILE); + +&run_make_with_options($makefile2,"",&get_logfile); +$answer = "FOO = foo\n"; &compare_output($answer,&get_logfile(1)); + 1; diff --git a/tests/scripts/options/dash-B b/tests/scripts/options/dash-B new file mode 100644 index 0000000..94932e5 --- /dev/null +++ b/tests/scripts/options/dash-B @@ -0,0 +1,43 @@ +# -*-perl-*- + +$description = "Test make -B (always remake) option.\n"; + +$details = "\ +Construct a simple makefile that builds a target. +Invoke make once, so it builds everything. Invoke it again and verify +that nothing is built. Then invoke it with -B and verify that everything +is built again."; + +open(MAKEFILE,"> $makefile"); + +print MAKEFILE <<'EOF'; +.SUFFIXES: + +.PHONY: all +all: foo + +foo: bar.x + @echo cp $< $@ + @touch $@ +EOF + +close(MAKEFILE); + + +&touch('bar.x'); + +&run_make_with_options($makefile, '', &get_logfile); +$answer = "cp bar.x foo\n"; +&compare_output($answer, &get_logfile(1)); + +&run_make_with_options($makefile, '', &get_logfile); +$answer = "$make_name: Nothing to be done for `all'.\n"; +&compare_output($answer, &get_logfile(1)); + +&run_make_with_options($makefile, '-B', &get_logfile); +$answer = "cp bar.x foo\n"; +&compare_output($answer, &get_logfile(1)); + +unlink('bar.x', 'foo') unless $keep; + +1; diff --git a/tests/scripts/variables/special b/tests/scripts/variables/special new file mode 100644 index 0000000..58c8655 --- /dev/null +++ b/tests/scripts/variables/special @@ -0,0 +1,68 @@ +# -*-perl-*- + +$description = "Test special GNU make variables."; + +$details = ""; + +$makefile2 = &get_tmpfile; + + +open(MAKEFILE, "> $makefile"); + +print MAKEFILE <<'EOF'; + +X1 := $(sort $(filter FOO BAR,$(.VARIABLES))) + +FOO := foo + +X2 := $(sort $(filter FOO BAR,$(.VARIABLES))) + +BAR := bar + +all: + @echo X1 = $(X1) + @echo X2 = $(X2) + @echo LAST = $(sort $(filter FOO BAR,$(.VARIABLES))) + +EOF + +close(MAKEFILE); + +# TEST #1 +# ------- + +&run_make_with_options($makefile, "", &get_logfile); +$answer = "X1 =\nX2 = FOO\nLAST = BAR FOO\n"; +&compare_output($answer, &get_logfile(1)); + + + + +# open(MAKEFILE, "> $makefile2"); + +# print MAKEFILE <<'EOF'; + +# X1 := $(sort $(.TARGETS)) + +# all: foo +# @echo X1 = $(X1) +# @echo X2 = $(X2) +# @echo LAST = $(sort $(.TARGETS)) + +# X2 := $(sort $(.TARGETS)) + +# foo: + +# EOF + +# close(MAKEFILE); + +# # TEST #2 +# # ------- + +# &run_make_with_options($makefile2, "", &get_logfile); +# $answer = "X1 =\nX2 = all\nLAST = all foo\n"; +# &compare_output($answer, &get_logfile(1)); + + +1; @@ -177,9 +177,9 @@ define_variable_in_set (name, length, value, origin, recursive, set, flocp) /* If the variable passed in is "special", handle its special nature. Currently there are two such variables, both used for introspection: - .MAKE_VARS expands to a list of all the variables defined in this instance + .VARIABLES expands to a list of all the variables defined in this instance of make. - .MAKE_TARGETS expands to a list of all the targets defined in this + .TARGETS expands to a list of all the targets defined in this instance of make. Returns the variable reference passed in. */ @@ -192,10 +192,33 @@ handle_special_var (var) static unsigned long last_var_count = 0; - if (streq (var->name, ".MAKE_TARGETS")) + /* This one actually turns out to be very hard, due to the way the parser + records targets. The way it works is that target information is collected + internally until make knows the target is completely specified. It unitl + it sees that some new construct (a new target or variable) is defined that + it knows the previous one is done. In short, this means that if you do + this: + + all: + + TARGS := $(.TARGETS) + + then $(TARGS) won't contain "all", because it's not until after the + variable is created that the previous target is completed. + + Changing this would be a major pain. I think a less complex way to do it + would be to pre-define the target files as soon as the first line is + parsed, then come back and do the rest of the definition as now. That + would allow $(.TARGETS) to be correct without a major change to the way + the parser works. + + if (streq (var->name, ".TARGETS")) var->value = build_target_list (var->value); - else if (streq (var->name, ".MAKE_VARS") + else + */ + + if (streq (var->name, ".VARIABLES") && global_variable_set.table.ht_fill != last_var_count) { unsigned long max = EXPANSION_INCREMENT (strlen (var->value)); @@ -207,6 +230,7 @@ handle_special_var (var) /* Make sure we have at least MAX bytes in the allocated buffer. */ var->value = xrealloc (var->value, max); + /* Walk through the hash of variables, constructing a list of names. */ p = var->value; len = 0; for (; vp < end; ++vp) @@ -231,6 +255,10 @@ handle_special_var (var) } *(p-1) = '\0'; + /* Remember how many variables are in our current count. Since we never + remove variables from the list, this is a reliable way to know whether + the list is up to date or needs to be recomputed. */ + last_var_count = global_variable_set.table.ht_fill; } @@ -262,7 +290,7 @@ lookup_variable (name, length) v = (struct variable *) hash_find_item ((struct hash_table *) &set->table, &var_key); if (v) - return handle_special_var (v); + return v->special ? handle_special_var (v) : v; } #ifdef VMS @@ -814,9 +842,10 @@ do_variable_definition (flocp, varname, value, origin, flavor, target_var) { /* Paste the old and new values together in VALUE. */ - unsigned int oldlen, newlen; + unsigned int oldlen, vallen; + char *val; - p = value; + val = value; if (v->recursive) /* The previous definition of the variable was recursive. The new value is the unexpanded old and new values. */ @@ -827,14 +856,14 @@ do_variable_definition (flocp, varname, value, origin, flavor, target_var) when it was set; and from the expanded new value. Allocate memory for the expansion as we may still need the rest of the buffer if we're looking at a target-specific variable. */ - p = alloc_value = allocated_variable_expand (p); + val = alloc_value = allocated_variable_expand (val); oldlen = strlen (v->value); - newlen = strlen (p); - p = (char *) alloca (oldlen + 1 + newlen + 1); + vallen = strlen (val); + p = (char *) alloca (oldlen + 1 + vallen + 1); bcopy (v->value, p, oldlen); p[oldlen] = ' '; - bcopy (value, &p[oldlen + 1], newlen + 1); + bcopy (val, &p[oldlen + 1], vallen + 1); } } } @@ -60,6 +60,7 @@ struct variable unsigned int per_target:1; /* Nonzero if a target-specific variable. */ unsigned int append:1; /* Nonzero if an appending target-specific variable. */ + unsigned int special:1; /* Nonzero if this is a special variable. */ unsigned int expanding:1; /* Nonzero if currently being expanded. */ unsigned int exp_count:EXP_COUNT_BITS; /* If >1, allow this many self-referential |