From 7ea029a07c02b9401cb3d88566eac41959b84c11 Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Tue, 10 Sep 2002 07:27:28 +0000 Subject: [PATCH] Add support for broken SA_RESTART on PTX. Fix bug #103: allow ifdef, export, and unexport to expand their arguments. --- ChangeLog | 22 +++++ configure.in | 15 ++++ doc/make.texi | 8 +- make.h | 14 +++ misc.c | 35 ++++++++ read.c | 43 +++++++-- tests/ChangeLog | 8 ++ tests/scripts/features/conditionals | 34 +++++++ tests/scripts/features/export | 173 ++++++++++++++++++++++++++++++++++++ 9 files changed, 345 insertions(+), 7 deletions(-) create mode 100644 tests/scripts/features/export diff --git a/ChangeLog b/ChangeLog index d600686..4891382 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,29 @@ +2002-09-10 Paul D. Smith + + * read.c (eval): Expand variable lists given to export and + unexport, so that "export $(LIST_OF_VARIABLES)" (etc.) works. + (conditional_line): Ditto for "ifdef". Fixes bug #103. + + * doc/make.texi (Variables/Recursion): Document this. + (Conditional Syntax): And here. + 2002-09-09 Paul D. Smith * configure.in: Check for memmove(). +2002-09-07 Paul D. Smith + + * configure.in (HAVE_BROKEN_RESTART): Define this on PTX systems; + Michael Sterrett reports that while it has + SA_RESTART, it does not work properly. + + * misc.c (atomic_stat): If HAVE_BROKEN_RESTART, create a function + that invokes stat() and loops to do it again if it returns EINTR. + (atomic_readdir): Ditto, with readdir(). + + * make.h (stat, readdir): If HAVE_BROKEN_RESTART, alias stat() + and readdir() to atomic_stat() and atomic_readdir(). + 2002-09-04 Paul D. Smith * implicit.c (pattern_search): Daniel diff --git a/configure.in b/configure.in index 5abbad5..c5c8026 100644 --- a/configure.in +++ b/configure.in @@ -291,6 +291,21 @@ make_cv_sys_gnu_glob=no])]) # Tell automake about this, so it can build the right .c files. AM_CONDITIONAL(USE_LOCAL_GLOB, test "$make_cv_sys_gnu_glob" = no) +# PTX systems have a broken implementation of SA_RESTART. I know of +# no way to test for this behavior, so I'll just test for PTX + +case "$host" in + i386-sequent-sysv4) + AC_DEFINE(HAVE_BROKEN_RESTART, 1, [This system has SA_RESTART, but it doesn't work properly.]) + echo "" + echo "WARNING: The SA_RESTART sigaction() flag does not work on PTX." + echo " This causes 'make -j' to fail at random times." + echo " I am installing a workaround, which is mostly but not 100%" + echo " effective. If you see random failures during 'make -j'" + echo " you should either contact the bug list, or not use -j." + echo "" ;; +esac + # Let the makefile know what our build host is AC_DEFINE_UNQUOTED(MAKE_HOST,"$host",[Build host information.]) diff --git a/doc/make.texi b/doc/make.texi index 4ef1107..2389ca0 100644 --- a/doc/make.texi +++ b/doc/make.texi @@ -3747,6 +3747,10 @@ unexport @var{variable} @dots{} @end example @noindent +In both of these forms, the arguments to @code{export} and +@code{unexport} are expanded, and so could be variables or functions +which expand to a (list of) variable names to be (un)exported. + As a convenience, you can define a variable and export it at the same time by doing: @@ -5434,7 +5438,9 @@ effective; otherwise, the @var{text-if-false}, if any, is effective. If the variable @var{variable-name} has a non-empty value, the @var{text-if-true} is effective; otherwise, the @var{text-if-false}, if any, is effective. Variables that have never been defined have an -empty value. +empty value. The variable @var{variable-name} is itself expanded, so +it could be a variable or function that expands to the name of a +variable. Note that @code{ifdef} only tests whether a variable has a value. It does not expand the variable to see if that value is nonempty. diff --git a/make.h b/make.h index 32f233f..2e354c9 100644 --- a/make.h +++ b/make.h @@ -537,3 +537,17 @@ extern int handling_fatal_signal; #ifdef HAVE_DMALLOC_H #include #endif + + +/* If we have broken SA_RESTART support, then wrap stat() and readdir() with + versions that handle EINTR. Note that there are still plenty of system + calls that can fail with EINTR but this, reportedly, gets the vast + majority of failure cases. If you still experience failures you'll need + to either get a system where SA_RESTART works, or you need to avoid -j. */ + +#ifdef HAVE_BROKEN_RESTART + +#define stat(_f,_b) atomic_stat ((_f), (_b)) +#define readdir(_d) atomic_readdir (_d) + +#endif diff --git a/misc.c b/misc.c index 6e2b570..669dabc 100644 --- a/misc.c +++ b/misc.c @@ -856,3 +856,38 @@ get_path_max () return value; } #endif + + +#ifdef HAVE_BROKEN_RESTART + +#undef stat +#undef readdir + +int +atomic_stat(file, buf) + const char *file; + struct stat *buf; +{ + int r; + + while ((r = stat (file, buf)) < 0) + if (errno != EINTR) + break; + + return r; +} + +struct dirent * +atomic_readdir(dir) + DIR *file; +{ + struct dirent *r; + + while ((r = readdir (file, buf)) == NULL) + if (errno != EINTR) + break; + + return r; +} + +#endif /* HAVE_BROKEN_RESTART */ diff --git a/read.c b/read.c index 7dee3e3..dd930f7 100644 --- a/read.c +++ b/read.c @@ -593,7 +593,7 @@ eval (ebuf, set_default) || word1eq ("ifeq") || word1eq ("ifneq") || word1eq ("else") || word1eq ("endif"))) { - int i = conditional_line (p, fstart); + int i = conditional_line (p, fstart); if (i < 0) fatal (fstart, _("invalid syntax in conditional")); @@ -686,11 +686,21 @@ eval (ebuf, set_default) for (p = find_next_token (&p2, &len); p != 0; p = find_next_token (&p2, &len)) { - v = lookup_variable (p, len); + char *var; + int l; + + /* Expand the thing we're looking up, so we can use + indirect and constructed variable names. */ + p[len] = '\0'; + var = allocated_variable_expand (p); + l = strlen (var); + + v = lookup_variable (var, l); if (v == 0) - v = define_variable_loc (p, len, "", o_file, 0, + v = define_variable_loc (var, l, "", o_file, 0, fstart); v->export = v_export; + free (var); } } } @@ -708,10 +718,22 @@ eval (ebuf, set_default) for (p = find_next_token (&p2, &len); p != 0; p = find_next_token (&p2, &len)) { - v = lookup_variable (p, len); + char *var; + int l; + + /* Expand the thing we're looking up, so we can use + indirect and constructed variable names. */ + p[len] = '\0'; + var = allocated_variable_expand (p); + l = strlen (var); + + v = lookup_variable (var, l); if (v == 0) - v = define_variable_loc (p, len, "", o_file, 0, fstart); + v = define_variable_loc (var, l, "", o_file, 0, fstart); + v->export = v_noexport; + + free (var); } } goto rule_complete; @@ -1410,15 +1432,24 @@ conditional_line (line, flocp) if (cmdname[notdef ? 3 : 2] == 'd') { /* "Ifdef" or "ifndef". */ + char *var; struct variable *v; register char *p = end_of_token (line); i = p - line; p = next_token (p); if (*p != '\0') return -1; - v = lookup_variable (line, i); + + /* Expand the thing we're looking up, so we can use indirect and + constructed variable names. */ + line[i] = '\0'; + var = allocated_variable_expand (line); + + v = lookup_variable (var, strlen (var)); conditionals->ignoring[conditionals->if_cmds - 1] = (v != 0 && *v->value != '\0') == notdef; + + free (var); } else { diff --git a/tests/ChangeLog b/tests/ChangeLog index 7336bd3..64a8322 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,11 @@ +2002-09-10 Paul D. Smith + + * scripts/features/export: Created. Add tests for export/unexport + capabilities, including exporting/unexporting expanded variables. + + * scripts/features/conditionals: Add a test for expanded variables + in ifdef conditionals. + 2002-09-04 Paul D. Smith * scripts/features/reinvoke: Change touch/sleep combos to utouch diff --git a/tests/scripts/features/conditionals b/tests/scripts/features/conditionals index 3557fb5..ab3d9d5 100644 --- a/tests/scripts/features/conditionals +++ b/tests/scripts/features/conditionals @@ -63,5 +63,39 @@ arg4 is defined &compare_output($answer,&get_logfile(1)); + +# Test expansion of variables inside ifdef. + +$makefile2 = &get_tmpfile; + +open(MAKEFILE, "> $makefile2"); + +print MAKEFILE <<'EOF'; + +foo = 1 + +FOO = foo +F = f + +DEF = no +DEF2 = no + +ifdef $(FOO) +DEF = yes +endif + +ifdef $(F)oo +DEF2 = yes +endif + +all:; @echo DEF=$(DEF) DEF2=$(DEF2) + +EOF + +&run_make_with_options($makefile2,"",&get_logfile,0); +$answer = "DEF=yes DEF2=yes\n"; +&compare_output($answer,&get_logfile(1)); + + # This tells the test driver that the perl test script executed properly. 1; diff --git a/tests/scripts/features/export b/tests/scripts/features/export new file mode 100644 index 0000000..09aeac2 --- /dev/null +++ b/tests/scripts/features/export @@ -0,0 +1,173 @@ +# -*-perl-*- +$description = "Check GNU make export/unexport commands."; + +$details = ""; + +# The test driver cleans out our environment for us so we don't have to worry +# about that here. + +open(MAKEFILE,"> $makefile"); + +# The Contents of the MAKEFILE ... + +print MAKEFILE <<'EOMAKE'; + +FOO = foo +BAR = bar +BOZ = boz + +export BAZ = baz +export BOZ + +BITZ = bitz +BOTZ = botz + +export BITZ BOTZ +unexport BOTZ + + +ifdef EXPORT_ALL +export +endif + +ifdef UNEXPORT_ALL +unexport +endif + +ifdef EXPORT_ALL_PSEUDO +.EXPORT_ALL_VARIABLES: +endif + +all: + @echo "FOO=$(FOO) BAR=$(BAR) BAZ=$(BAZ) BOZ=$(BOZ) BITZ=$(BITZ) BOTZ=$(BOTZ)" + @echo "FOO=$$FOO BAR=$$BAR BAZ=$$BAZ BOZ=$$BOZ BITZ=$$BITZ BOTZ=$$BOTZ" + +EOMAKE + +close(MAKEFILE); + +# TEST 0: basics + +&run_make_with_options($makefile,"",&get_logfile,0); + +$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz +FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"; + +&compare_output($answer,&get_logfile(1)); + +# TEST 1: make sure vars inherited from the parent are exported + +$ENV{FOO} = 1; + +&run_make_with_options($makefile,"",&get_logfile,0); + +$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz +FOO=foo BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"; + +&compare_output($answer,&get_logfile(1)); + +delete $ENV{FOO}; + +# TEST 2: global export. Explicit unexport takes precedence. + +&run_make_with_options($makefile,"EXPORT_ALL=1",&get_logfile,0); + +$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz +FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"; + +&compare_output($answer,&get_logfile(1)); + +# TEST 3: global unexport. Explicit export takes precedence. + +&run_make_with_options($makefile,"UNEXPORT_ALL=1",&get_logfile,0); + +$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz +FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"; + +&compare_output($answer,&get_logfile(1)); + +# TEST 4: both: in the above makefile the unexport comes last so that rules. + +&run_make_with_options($makefile,"EXPORT_ALL=1 UNEXPORT_ALL=1",&get_logfile,0); + +$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz +FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"; + +&compare_output($answer,&get_logfile(1)); + +# TEST 5: test the pseudo target. + +&run_make_with_options($makefile,"EXPORT_ALL_PSEUDO=1",&get_logfile,0); + +$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz +FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"; + +&compare_output($answer,&get_logfile(1)); + + +# TEST 6: Test the expansion of variables inside export + +$makefile2 = &get_tmpfile; + +open(MAKEFILE, "> $makefile2"); + +print MAKEFILE <<'EOF'; + +foo = f-ok +bar = b-ok + +FOO = foo +F = f + +BAR = bar +B = b + +export $(FOO) +export $(B)ar + +all: + @echo foo=$(foo) bar=$(bar) + @echo foo=$$foo bar=$$bar + +EOF + +&run_make_with_options($makefile2,"",&get_logfile,0); +$answer = "foo=f-ok bar=b-ok\nfoo=f-ok bar=b-ok\n"; +&compare_output($answer,&get_logfile(1)); + + +# TEST 7: Test the expansion of variables inside unexport + +$makefile3 = &get_tmpfile; + +open(MAKEFILE, "> $makefile3"); + +print MAKEFILE <<'EOF'; + +foo = f-ok +bar = b-ok + +FOO = foo +F = f + +BAR = bar +B = b + +export foo bar + +unexport $(FOO) +unexport $(B)ar + +all: + @echo foo=$(foo) bar=$(bar) + @echo foo=$$foo bar=$$bar + +EOF + +&run_make_with_options($makefile3,"",&get_logfile,0); +$answer = "foo=f-ok bar=b-ok\nfoo= bar=\n"; +&compare_output($answer,&get_logfile(1)); + + +# This tells the test driver that the perl test script executed properly. +1; -- 2.7.4