diff --git a/ChangeLog b/ChangeLog index 4d5e0f44..30f13b9c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,54 @@ +2004-03-20 Paul D. Smith + + * variable.c (do_variable_definition): Don't append from the + global set if a previous non-appending target-specific variable + definition exists. Reported by Oliver Schmidt + (with fix). + + * expand.c (reference_variable): Don't give up on variables with + no value that have the target-specific append flag set: they might + have a value after all. Reported by Oliver Schmidt + (with fix) and also by Maksim A. Nikulin + . + + * rule.c (count_implicit_rule_limits): Don't delete patterns which + refer to absolute pathnames in directories that don't exist: some + portion of the makefile could create those directories before we + match the pattern. Fixes bugs #775 and #108. + + Fixes from Jonathan R. Grant : + + * main.c (main): Free makefile_mtimes if we have any. + * README.W32.template: Update documentation for the current status + of the MS-Windows port. + * NMakefile.template (MAKE): Add "MAKE = nmake". A conflicting + environment variable is sometimes already defined which causes the + build to fail. + * main.c (debug_signal_handler): Only define this function if + SIGUSR1 is available. + + Fixes for OS/2 from Andreas Beuning : + + * configure.in [OS/2]: Relocate setting of HAVE_SA_RESTART for OS/2. + * README.OS2.template: Documentation updates. + * build.template: Add LIBINTL into LOADLIBES. Add $CFLAGS to the + link line for safety. + * maintMakefile (build.sh.in): Remove an extraneous ")". + * job.c (child_execute_job): Close saved FDs. + * job.c (exec_command) [OS/2]: exec_command(): If the command + can't be exec'ed and if the shell is not Unix-sh, then try again + with argv = { "cmd", "/c", ... }. Normally, this code is never + reached for the cmd shell unless the command really doesn't exist. + (construct_command_argv_internal) [OS/2]: The code for cmd + handling now uses new_argv = { "cmd", "/c", "original line", NULL}. + The CMD builtin commands are case insensitive so use strcasecmp(). + +2004-03-19 Paul D. Smith + + * read.c (do_define): Re-order line counter increment so the count + is accurate (we were losing one line per define). Reported by + Dave Yost . + 2004-03-06 Paul D. Smith * configure.in (HAVE_ANSI_COMPILER): Define if we have an ANSI/ISO diff --git a/NMakefile.template b/NMakefile.template index 6fe52766..df964c04 100644 --- a/NMakefile.template +++ b/NMakefile.template @@ -25,6 +25,7 @@ LINK = link CC = cl +MAKE = nmake OUTDIR=. MAKEFILE=NMakefile diff --git a/README.OS2.template b/README.OS2.template index eff2c0bc..bb0a60f0 100644 --- a/README.OS2.template +++ b/README.OS2.template @@ -46,7 +46,7 @@ II. ***** REQUIREMENTS FOR THE COMPILATION ***** A standard Unix like build environment: - sh compatible shell (ksh, bash, ash, but tested only with pdksh 5.2.14 - (release 2) + release 2) If you use pdksh it is recommended to update to 5.2.14 release 2. Older versions may not work! You can get this version at http://www.math.ohio-state.edu/~ilya/software/os2/pdksh-5.2.14-bin-2.zip @@ -59,12 +59,12 @@ A standard Unix like build environment: - gawk - grep - sed - - GNU make 3.79.1 (special OS/2 patched version) + - GNU make 3.79.1 (special OS/2 patched version) or higher - perl 5.005 or higher - GNU texinfo (you can use 3.1 (gnuinfo.zip), but I recommend 4.0) If you want to recreate the configuration files (developers only!) -you need also: GNU m4 1.4, autoconf 2.57, automake 1.7.2 (or compatible) +you need also: GNU m4 1.4, autoconf 2.59, automake 1.8.2 (or compatible) III. ***** COMPILATION AND INSTALLATION ***** @@ -147,12 +147,12 @@ none. To run the testsuite do the following: export CPPFLAGS="-D__ST_MT_ERRNO__ -DNO_CMD_DEFAULT -DNO_CHDIR2" - export CFLAGS="-Zomf -O2 -s -Zmt" - export LDFLAGS="-Zcrtdll -Zmt -s -Zlinker /exepack:2 -Zlinker /pm:vio -Zstack 0x8000" + export CFLAGS="-Zomf -O2 -Zmt" + export LDFLAGS="-Zcrtdll -s -Zlinker /exepack:2 -Zlinker /pm:vio -Zstack 0x8000" export RANLIB="echo" ./configure --prefix=x:/usr --disable-nls make AR=emxomfar - make checks + make check All tests should work fine with the exception of "default_names" which is because OS/2 file systems are not case sensitive ("makefile" and diff --git a/README.W32.template b/README.W32.template index 2b7b63c1..bb89d20f 100644 --- a/README.W32.template +++ b/README.W32.template @@ -5,7 +5,7 @@ Should also build fine with MSVC 5.x and 6.x (though not confirmed). This Windows 32-bit port of GNU make is maintained primarily by Rob Tulloh, who is also the author of this README. -To build with nmake on Windows NT, Windows 95, or Windows 98: +To build with nmake on MS-Windows: 1. Make sure cl.exe is in your %Path%. Example: @@ -63,10 +63,10 @@ GNU make and sh.exe: There are very few true ports of Bourne shell for NT right now. There is a version of GNU bash available from Cygnus "Cygwin" - porting effort (http://sourceware.cygnus.com/cygwin). + porting effort (http://www.cygwin.com/). Other possibilities are the MKS version of sh.exe, or building your own with a package like NutCracker (DataFocus) or Portage - (Consensys). + (Consensys). Also MinGW includes sh (http://mingw.org/). GNU make and brain-dead shells (BATCH_MODE_ONLY_SHELL): @@ -131,7 +131,8 @@ GNU make handling of drive letters in pathnames (PATH, vpath, VPATH): Please note that you are free to mix colon and semi-colon in the specification of paths. Make is able to figure out the intended result and convert the paths internally to the format needed - when interacting with the operating system. + when interacting with the operating system, providing the path + is not within quotes, e.g. "x:/test/test.c". You are encouraged to use colon as the separator character. This should ease the pain of deciding how to handle various path @@ -167,15 +168,17 @@ Building GNU make on Windows NT and Windows 95/98 with Microsoft Visual C: Pathnames and white space: Unlike Unix, Windows 95/NT systems encourage pathnames which - contain white space (e.g. C:\Program Files\). These sorts of pathnames - are legal under Unix too, but are never encouraged. There is - at least one place in make (VPATH/vpath handling) where paths - containing white space will simply not work. There may be others - too. I chose to not try and port make in such a way so that - these sorts of paths could be handled. I offer these suggestions - as workarounds: + contain white space (e.g. C:\Program Files\). These sorts of + pathnames are legal under Unix too, but are never encouraged. + There is at least one place in make (VPATH/vpath handling) where + paths containing white space will simply not work. There may be + others too. I chose to not try and port make in such a way so + that these sorts of paths could be handled. I offer these + suggestions as workarounds: - 1. Use 8.3 notation + 1. Use 8.3 notation. i.e. "x:/long~1/", which is actually + "x:\longpathtest". Type "dir /x" to view these filenames + within the cmd.exe shell. 2. Rename the directory so it does not contain white space. If you are unhappy with this choice, this is free software diff --git a/build.template b/build.template index 894140e2..3ba94ae3 100644 --- a/build.template +++ b/build.template @@ -2,7 +2,7 @@ # Shell script to build GNU Make in the absence of any `make' program. # @configure_input@ -# Copyright (C) 1993, 1994, 1997, 2003 Free Software Foundation, Inc. +# Copyright (C) 1993, 1994, 1997, 2003, 2004 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify @@ -28,7 +28,7 @@ CFLAGS='@CFLAGS@' CPPFLAGS='@CPPFLAGS@' LDFLAGS='@LDFLAGS@' ALLOCA='@ALLOCA@' -LOADLIBES='@LIBS@' +LOADLIBES='@LIBS@ @LIBINTL@' eval extras=\'@LIBOBJS@\' REMOTE='@REMOTE@' GLOBLIB='@GLOBLIB@' @@ -78,6 +78,6 @@ done # Link all the objects together. echo linking make... -$CC $LDFLAGS $objs $LOADLIBES -o makenew${EXEEXT} +$CC $CFLAGS $LDFLAGS $objs $LOADLIBES -o makenew${EXEEXT} echo done mv -f makenew${EXEEXT} make${EXEEXT} diff --git a/configure.in b/configure.in index 967a8edf..b28c3fb0 100644 --- a/configure.in +++ b/configure.in @@ -254,16 +254,16 @@ AC_CACHE_CHECK(for SA_RESTART, make_cv_sa_restart, [ [make_cv_sa_restart=yes], [make_cv_sa_restart=no])]) -# enable make_cv_sa_restart for OS/2 -case "$host_os" in - os2*) make_cv_sa_restart=yes ;; -esac - if test "$make_cv_sa_restart" != no; then AC_DEFINE(HAVE_SA_RESTART, 1, [Define if defines the SA_RESTART constant.]) fi +# enable make_cv_sa_restart for OS/2 +case "$host_os" in + os2*) make_cv_sa_restart=yes ;; +esac + case "$ac_cv_func_pipe/$ac_cv_func_sigaction/$make_cv_sa_restart/$has_wait_nohang/$make_cv_job_server" in yes/yes/yes/yes/yes) AC_DEFINE(MAKE_JOBSERVER, 1, diff --git a/expand.c b/expand.c index 8f9f4b1f..2c8b4b69 100644 --- a/expand.c +++ b/expand.c @@ -153,7 +153,8 @@ reference_variable (char *o, char *name, unsigned int length) if (v == 0) warn_undefined (name, length); - if (v == 0 || *v->value == '\0') + /* If there's no variable by that name or it has no value, stop now. */ + if (v == 0 || (*v->value == '\0' && !v->append)) return o; value = (v->recursive ? recursively_expand (v) : v->value); diff --git a/job.c b/job.c index 681fdcf9..01539950 100644 --- a/job.c +++ b/job.c @@ -469,7 +469,7 @@ reap_children (int block, int err) && (block || REAP_MORE)) { int remote = 0; - register int pid; + pid_t pid; int exit_code, exit_sig, coredump; register struct child *lastc, *c; int child_failed; @@ -611,29 +611,34 @@ reap_children (int block, int err) { HANDLE hPID; int err; + exit_code = 0; + exit_sig = 0; + coredump = 0; /* wait for anything to finish */ - if (hPID = process_wait_for_any()) { + hPID = process_wait_for_any(); + if (hPID) + { - /* was an error found on this process? */ - err = process_last_err(hPID); + /* was an error found on this process? */ + err = process_last_err(hPID); - /* get exit data */ - exit_code = process_exit_code(hPID); + /* get exit data */ + exit_code = process_exit_code(hPID); - if (err) - fprintf(stderr, "make (e=%d): %s", - exit_code, map_windows32_error_to_string(exit_code)); + if (err) + fprintf(stderr, "make (e=%d): %s", + exit_code, map_windows32_error_to_string(exit_code)); - /* signal */ - exit_sig = process_signal(hPID); + /* signal */ + exit_sig = process_signal(hPID); - /* cleanup process */ - process_cleanup(hPID); + /* cleanup process */ + process_cleanup(hPID); - coredump = 0; - } - pid = (int) hPID; + coredump = 0; + } + pid = (pid_t) hPID; } #endif /* WINDOWS32 */ } @@ -2400,11 +2405,22 @@ child_execute_job (int stdin_fd, int stdout_fd, char **argv, char **envp) /* Run the command. */ pid = exec_command (argv, envp); - /* Restore stdout/stdin of the parent process. */ - if (stdin_fd != 0 && dup2 (save_stdin, 0) != 0) - fatal (NILF, _("restoring of stdin failed\n")); - if (stdout_fd != 1 && dup2 (save_stdout, 1) != 1) - fatal (NILF, _("restoring of stdout failed\n")); + /* Restore stdout/stdin of the parent and close temporary FDs. */ + if (stdin_fd != 0) + { + if (dup2 (save_stdin, 0) != 0) + fatal (NILF, _("Could not restore stdin\n")); + else + close (save_stdin); + } + + if (stdout_fd != 1) + { + if (dup2 (save_stdout, 1) != 1) + fatal (NILF, _("Could not restore stdout\n")); + else + close (save_stdout); + } return pid; } @@ -2482,7 +2498,8 @@ exec_command (char **argv, char **envp) } /* wait and reap last child */ - while (hWaitPID = process_wait_for_any()) + hWaitPID = process_wait_for_any(); + while (hWaitPID) { /* was an error found on this process? */ err = process_last_err(hWaitPID); @@ -2550,6 +2567,7 @@ exec_command (char **argv, char **envp) char *shell; char **new_argv; int argc; + int i=1; # ifdef __EMX__ /* Do not use $SHELL from the environment */ @@ -2568,12 +2586,27 @@ exec_command (char **argv, char **envp) while (argv[argc] != 0) ++argc; +# ifdef __EMX__ + if (!unixy_shell) + ++argc; +# endif + new_argv = (char **) alloca ((1 + argc + 1) * sizeof (char *)); new_argv[0] = shell; - new_argv[1] = argv[0]; + +# ifdef __EMX__ + if (!unixy_shell) + { + new_argv[1] = "/c"; + ++i; + --argc; + } +# endif + + new_argv[i] = argv[0]; while (argc > 0) { - new_argv[1 + argc] = argv[argc]; + new_argv[i + argc] = argv[argc]; --argc; } @@ -3010,8 +3043,16 @@ construct_command_argv_internal (char *line, char **restp, char *shell, { register int j; for (j = 0; sh_cmds[j] != 0; ++j) - if (streq (sh_cmds[j], new_argv[0])) - goto slow; + { + if (streq (sh_cmds[j], new_argv[0])) + goto slow; +# ifdef __EMX__ + /* Non-Unix shells are case insensitive. */ + if (!unixy_shell + && strcasecmp (sh_cmds[j], new_argv[0]) == 0) + goto slow; +# endif + } } /* Ignore multiple whitespace chars. */ @@ -3247,103 +3288,59 @@ construct_command_argv_internal (char *line, char **restp, char *shell, new_argv = construct_command_argv_internal (new_line, (char **) NULL, (char *) 0, (char *) 0, (char **) 0); -# ifdef __EMX__ +#ifdef __EMX__ else if (!unixy_shell) { - /* new_line is local, must not be freed therefore */ - char *p, *q; - int quote; - size_t index; - size_t len; + /* new_line is local, must not be freed therefore + We use line here instead of new_line because we run the shell + manually. */ + size_t line_len = strlen (line); + memcpy (new_line, line, line_len + 1); - /* handle quotes - We have to remove all double quotes and to split the line - into distinct arguments because of the strange handling - of builtin commands by cmd: 'echo "bla"' prints "bla" - (with quotes) while 'c:\bin\echo.exe "bla"' prints bla - (without quotes). Some programs like autoconf rely - on the second behaviour. */ +# ifndef NO_CMD_DEFAULT + if (strnicmp (new_line, "echo", 4) == 0 + && (new_line[4] == ' ' || new_line[4] == '\t')) + { + /* the builtin echo command: handle it separately */ + size_t echo_len = line_len - 5; + char *echo_line = new_line + 5; - len = strlen (new_line) + 1; + /* special case: echo 'x="y"' + cmd works this way: a string is printed as is, i.e., no quotes + are removed. But autoconf uses a command like echo 'x="y"' to + determine whether make works. autoconf expects the output x="y" + so we will do exactly that. + Note: if we do not allow cmd to be the default shell + we do not need this kind of voodoo */ + if (echo_line[0] == '\'' + && echo_line[echo_len - 1] == '\'' + && strncmp (echo_line + 1, "ac_maketemp=", + strlen ("ac_maketemp=")) == 0) + { + /* remove the enclosing quotes */ + memmove (echo_line, echo_line + 1, echo_len - 2); + echo_line[echo_len - 2] = '\0'; + } + } +# endif - /* More than 1 arg per character is impossible. */ - new_argv = (char **) xmalloc (len * sizeof (char *)); + { + /* Let the shell decide what to do. Put the command line into the + 2nd command line argument and hope for the best ;-) */ + size_t sh_len = strlen (shell); - /* All the args can fit in a buffer as big as new_line is. */ - new_argv[0] = (char *) xmalloc (len); - - index = 0; - quote = 0; - q = new_line; - p = new_argv[index]; - while(*q != '\0') - { - /* searching for closing quote */ - if (quote) - { - if (*q == quote) - { - /* remove the quote */ - q++; - quote = 0; - } - else /* normal character: copy it */ - *p++ = *q++; - } - - /* searching for opening quote */ - else if (*q == '\"' -# ifndef NO_CMD_DEFAULT - || *q == '\'' -# endif - ) - { - /* remove opening quote */ - quote = *q; - q++; - } - - /* spaces outside of a quoted string: remove them - and start a new argument */ - else if (*q == ' ' || *q == '\t') - { - *p++ = '\0'; /* trailing '\0' for last argument */ - - /* remove all successive spaces */ - do - { - q++; - } - while(*q == ' ' || *q == '\t'); - - /* start new argument */ - index++; - new_argv[index] = p; - } - - /* normal character (no space) outside a quoted string*/ - else - *p++ = *q++; - } /* end while() */ - - *p = '\0'; /* trailing '\0' for the last argument */ - new_argv[index + 1] = NULL; - -# ifndef NO_CMD_DEFAULT - /* special case: echo x="y" - (e.g. autoconf uses this to determine whether make works) - this is pure idioty but cmd works this way: - if 'echo' and 'x="y"' are two different arguments cmd - will print '"x="y""' but if they are only one argument - cmd will print 'bla="blurb"' as it should be - note: if we do not allow cmd to be the default shell - we do not need this kind of voodoo */ - if (index == 3 && strcasecmp(new_argv[2], "echo") == 0) - { - new_argv[2][4] = ' '; - new_argv[3] = NULL; - } -# endif + /* exactly 3 arguments + NULL */ + new_argv = (char **) xmalloc (4 * sizeof (char *)); + /* Exactly strlen(shell) + strlen("/c") + strlen(line) + 3 times + the trailing '\0' */ + new_argv[0] = (char *) malloc (sh_len + line_len + 5); + memcpy (new_argv[0], shell, sh_len + 1); + new_argv[1] = new_argv[0] + sh_len + 1; + memcpy (new_argv[1], "/c", 3); + new_argv[2] = new_argv[1] + 3; + memcpy (new_argv[2], new_line, line_len); + new_argv[3] = NULL; + } } #elif defined(__MSDOS__) else diff --git a/main.c b/main.c index 0c29af6a..d17e576d 100644 --- a/main.c +++ b/main.c @@ -35,6 +35,7 @@ MA 02111-1307, USA. */ #endif #ifdef WINDOWS32 #include +#include #include "pathstuff.h" #endif #ifdef __EMX__ @@ -544,11 +545,13 @@ enter_command_line_file (char *name) /* Toggle -d on receipt of SIGUSR1. */ +#ifdef SIGUSR1 static RETSIGTYPE debug_signal_handler (int sig UNUSED) { db_level = db_level ? DB_NONE : DB_BASIC; } +#endif static void decode_debug_flags (void) @@ -1917,14 +1920,14 @@ main (int argc, char **argv, char **envp) termination. */ int pid; int status; - pid = child_execute_job(0, 1, nargv, environ); + pid = child_execute_job (0, 1, nargv, environ); /* is this loop really necessary? */ do { - pid = wait(&status); - } while(pid <= 0); + pid = wait (&status); + } while (pid <= 0); /* use the exit code of the child process */ - exit(WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE); + exit (WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE); } #else exec_command (nargv, environ); @@ -1938,6 +1941,10 @@ main (int argc, char **argv, char **envp) } db_level = orig_db_level; + + /* Free the makefile mtimes (if we allocated any). */ + if (makefile_mtimes) + free ((char *) makefile_mtimes); } /* Set up `MAKEFLAGS' again for the normal targets. */ diff --git a/maintMakefile b/maintMakefile index 49b3a96c..c3208fe7 100644 --- a/maintMakefile +++ b/maintMakefile @@ -56,7 +56,7 @@ NMakefile: NMakefile.template .dep_segment Makefile build.sh.in: build.template Makefile rm -f $@ sed -e 's@%objs%@$(patsubst %.o,%.$${OBJEXT},$(filter-out remote-%,$(make_OBJECTS)))@g' \ - -e 's@%globobjs%@$(patsubst %.c,%.$${OBJEXT},$(globsrc)))@g' \ + -e 's@%globobjs%@$(patsubst %.c,%.$${OBJEXT},$(globsrc))@g' \ $< > $@ chmod a-w+x $@ @@ -246,8 +246,10 @@ po-check: ## ------------------------- ## # This target creates the upload artifacts. +# Sign it with my key. GPG = gpg +GPGFLAGS = -u 6338B6D4 DIST_ARCHIVES_SIG = $(addsuffix .sig,$(DIST_ARCHIVES)) DIST_ARCHIVES_DIRECTIVE = $(addsuffix .directive.asc,$(DIST_ARCHIVES)) @@ -260,12 +262,12 @@ $(DIST_ARCHIVES_DIRECTIVE): .directive.asc %.sig : % @echo "Signing file '$<':" - $(GPG) -o $@ -b $< + $(GPG) $(GPGFLAGS) -o $@ -b $< .directive.asc: @echo "Creating directive file '$@':" @echo 'directory: make' > .directive - $(GPG) -o $@ --clearsign .directive + $(GPG) $(GPGFLAGS) -o $@ --clearsign .directive @rm -f .directive # Upload the artifacts diff --git a/read.c b/read.c index 3469806f..1da2eacd 100644 --- a/read.c +++ b/read.c @@ -1277,8 +1277,8 @@ do_define (char *name, unsigned int namelen, unsigned int len; char *line; - ebuf->floc.lineno += nlines; nlines = readline (ebuf); + ebuf->floc.lineno += nlines; /* If there is nothing left to eval, we're done. */ if (nlines < 0) diff --git a/rule.c b/rule.c index 322ed23d..dd0ebcb6 100644 --- a/rule.c +++ b/rule.c @@ -135,20 +135,6 @@ count_implicit_rule_limits (void) nonexistent subdirectory. */ dep->changed = !dir_file_exists_p (name, ""); -#ifdef VMS - if (dep->changed && strchr (name, ':') != 0) -#else - if (dep->changed && *name == '/') -#endif - { - /* The name is absolute and the directory does not exist. - This rule can never possibly match, since this dependency - can never possibly exist. So just remove the rule from - the list. */ - freerule (rule, lastrule); - --num_pattern_rules; - goto end_main_loop; - } } else /* This dependency does not reside in a subdirectory. */ @@ -159,7 +145,6 @@ count_implicit_rule_limits (void) max_pattern_deps = ndeps; lastrule = rule; - end_main_loop: rule = next; } diff --git a/tests/ChangeLog b/tests/ChangeLog index 9f31f4e2..0e84c6b0 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,9 @@ +2004-03-22 Paul D. Smith + + * test_driver.pl (run_each_test, toplevel, compare_output): Change + to track both the testing categories _AND_ the number of + individual tests, and report both sets of numbers. + 2004-02-21 Paul D. Smith * scripts/functions/origin: Set our own environment variable diff --git a/tests/scripts/variables/flavors b/tests/scripts/variables/flavors index 7c98afd2..c9025b2e 100644 --- a/tests/scripts/variables/flavors +++ b/tests/scripts/variables/flavors @@ -71,7 +71,7 @@ $answer = "later foo bar\n"; # ------- &run_make_with_options($makefile, "BOGUS=true", &get_logfile, 512); -$answer = "$makefile:23: *** empty variable name. Stop.\n"; +$answer = "$makefile:24: *** empty variable name. Stop.\n"; &compare_output($answer, &get_logfile(1)); # TEST #4 diff --git a/tests/test_driver.pl b/tests/test_driver.pl index 0130605a..0ddb8842 100644 --- a/tests/test_driver.pl +++ b/tests/test_driver.pl @@ -1,4 +1,4 @@ -#!/usr/local/bin/perl +#!/usr/bin/perl # -*-perl-*- # Modification history: @@ -12,6 +12,22 @@ # this routine controls the whole mess; each test suite sets up a few # variables and then calls &toplevel, which does all the real work. +# $Id$ + + +# The number of test categories we've run +$categories_run = 0; +# The number of test categroies that have passed +$categories_passed = 0; +# The total number of individual tests that have been run +$total_tests_run = 0; +# The total number of individual tests that have passed +$total_tests_passed = 0; +# The number of tests in this category that have been run +$tests_run = 0; +# The number of tests in this category that have passed +$tests_passed = 0; + sub toplevel { # Get a clean environment @@ -150,17 +166,24 @@ sub toplevel $| = 1; - if ($num_failed) + $categories_failed = $categories_run - $categories_passed; + $total_tests_failed = $total_tests_run - $total_tests_passed; + + if ($total_tests_failed) { - print "\n$num_failed Test"; - print "s" unless $num_failed == 1; + print "\n$total_tests_failed Test"; + print "s" unless $total_tests_failed == 1; + print " in $categories_failed Categor"; + print ($categories_failed == 1 ? "y" : "ies"); print " Failed (See .$diffext files in $workdir dir for details) :-(\n\n"; return 0; } else { - print "\n$counter Test"; - print "s" unless $counter == 1; + print "\n$total_tests_passed Test"; + print "s" unless $total_tests_passed == 1; + print " in $categories_passed Categor"; + print ($categories_passed == 1 ? "y" : "ies"); print " Complete ... No Failures :-)\n\n"; return 1; } @@ -348,12 +371,12 @@ sub print_banner sub run_each_test { - $counter = 0; + $categories_run = 0; foreach $testname (sort @TESTS) { - $counter++; - $test_passed = 1; # reset by test on failure + ++$categories_run; + $passed = 1; # reset by test on failure $num_of_logfiles = 0; $num_of_tmpfiles = 0; $description = ""; @@ -390,11 +413,17 @@ sub run_each_test print $output; # Run the actual test! - # + $tests_run = 0; + $tests_passed = 0; $code = do $perl_testname; + + $total_tests_run += $tests_run; + $total_tests_passed += $tests_passed; + + # How did it go? if (!defined($code)) { - $test_passed = 0; + $passed = 0; if (length ($@)) { warn "\n*** Test died ($testname): $@\n"; @@ -405,15 +434,16 @@ sub run_each_test } } elsif ($code == -1) { - $test_passed = 0; + $passed = 0; } elsif ($code != 1 && $code != -1) { - $test_passed = 0; + $passed = 0; warn "\n*** Test returned $code\n"; } - if ($test_passed) { - $status = "ok"; + if ($passed) { + ++$categories_passed; + $status = "ok ($tests_passed passed)"; for ($i = $num_of_tmpfiles; $i; $i--) { &delete ($tmp_filename . &num_suffix ($i) ); @@ -426,12 +456,11 @@ sub run_each_test } } elsif ($code > 0) { - $status = "FAILED"; - $num_failed++; + $status = "FAILED ($tests_passed/$tests_run passed)"; } elsif ($code < 0) { $status = "N/A"; - --$counter; + --$categories_run; } # If the verbose option has been specified, then a short description @@ -591,12 +620,15 @@ sub compare_output $slurp =~ s/^.*modification time .*in the future.*\n//gm; $slurp =~ s/^.*Clock skew detected.*\n//gm; + ++$tests_run; + if ($slurp eq $answer) { if ($debug) { print "ok\n"; } + ++$tests_passed; return 1; } else @@ -605,7 +637,7 @@ sub compare_output { print "DIFFERENT OUTPUT\n"; } - $test_passed = 0; + $passed = 0; &create_file (&get_basefile, $answer); if ($debug) diff --git a/variable.c b/variable.c index d74672b3..7b9d0d8d 100644 --- a/variable.c +++ b/variable.c @@ -957,6 +957,11 @@ do_variable_definition (const struct floc *flocp, const char *varname, append = 1; v = lookup_variable_in_set (varname, strlen (varname), current_variable_set_list->set); + + /* Don't append from the global set if a previous non-appending + target-specific variable definition exists. */ + if (v && !v->append) + append = 0; } else v = lookup_variable (varname, strlen (varname));