diff options
author | Paul Smith <psmith@gnu.org> | 2003-05-02 01:44:59 +0000 |
---|---|---|
committer | Paul Smith <psmith@gnu.org> | 2003-05-02 01:44:59 +0000 |
commit | 1a5beef51f5c32081116e502c1c90a3e32813020 (patch) | |
tree | 5cf133d3615d2674df02234f6d5708d22175a67d | |
parent | 652234e967b825478d0b756a65353f252adf73d3 (diff) | |
download | gunmake-1a5beef51f5c32081116e502c1c90a3e32813020.tar.gz |
- Fix bug #1405: allow multiple pattern-specific variables to match a target.
- Fix some uncleanliness about the implementation of patterns-specific vars.
- Some enhancements to the OS/2 port.
-rw-r--r-- | ChangeLog | 57 | ||||
-rw-r--r-- | Makefile.am | 10 | ||||
-rw-r--r-- | NEWS | 21 | ||||
-rw-r--r-- | README.OS2.template | 159 | ||||
-rw-r--r-- | README.cvs | 3 | ||||
-rw-r--r-- | build.template | 17 | ||||
-rw-r--r-- | config/ChangeLog | 5 | ||||
-rw-r--r-- | config/dospaths.m4 | 21 | ||||
-rw-r--r-- | configure.in | 9 | ||||
-rw-r--r-- | default.c | 4 | ||||
-rw-r--r-- | dir.c | 6 | ||||
-rw-r--r-- | doc/make.texi | 17 | ||||
-rw-r--r-- | function.c | 4 | ||||
-rw-r--r-- | implicit.c | 2 | ||||
-rw-r--r-- | job.c | 13 | ||||
-rw-r--r-- | maintMakefile | 6 | ||||
-rw-r--r-- | read.c | 36 | ||||
-rw-r--r-- | rule.c | 100 | ||||
-rw-r--r-- | rule.h | 11 | ||||
-rw-r--r-- | tests/ChangeLog | 11 | ||||
-rwxr-xr-x | tests/run_make_tests.pl | 6 | ||||
-rw-r--r-- | tests/scripts/features/patspecific_vars | 35 | ||||
-rw-r--r-- | variable.c | 175 | ||||
-rw-r--r-- | variable.h | 28 |
24 files changed, 551 insertions, 205 deletions
@@ -1,3 +1,60 @@ +2003-04-30 Paul D. Smith <psmith@gnu.org> + + * build.template: Make some changes to maybe allow this script to + work on DOS/Windows/OS2 systems. Suggested by Andreas Buening. + + * README.OS2.template: New file for OS/2 support. Original + contributed by Andreas Buening. + * configure.in: Invoke new pds_AC_DOS_PATHS macro to test for + DOS-style paths. + +2003-04-19 Paul D. Smith <psmith@gnu.org> + + Fix bug #1405: allow a target to match multiple pattern-specific + variables. + + * rule.c (create_pattern_var, lookup_pattern_var): Move these to + variable.c, where they've always belonged. + * rule.h: Move the prototypes and struct pattern_var as well. + * variable.c (initialize_file_variables): Invoke + lookup_pattern_var() in a loop, until no more matches are found. + If a match is found, create a new variable set for the target's + pattern variables. Then merge the contents of each matching + pattern variable set into the target's pattern variable set. + (lookup_pattern_var): Change this function to be usable + in a loop. It takes a starting position: if NULL, start at the + beginning; if non-NULL, start with the pattern variable after that + position, and return the next matching pattern. + (create_pattern_var): Create a unique instance of + pattern-specific variables for every definition in the makefile. + Don't combine the same pattern together. This allows us to + process the variable handling properly even when the same pattern + is used multiple times. + (parse_variable_definition): New function: break out the parsing + of a variable definition line from try_variable_definition. + (try_variable_definition): Call parse_variable_definition to + parse. + (print_variable_data_base): Print out pattern-specific variables. + * variable.h (struct variable): Remember when a variable is + conditional. Also remember its flavor. + (struct pattern_var): Instead of keeping a variable set, we just + keep a single variable for each pattern. + * read.c (record_target_var): Each pattern variable contains only a + single variable, not a set, so create it properly. + * doc/make.texi (Pattern-specific): Document the new behavior. + +2003-04-17 Paul D. Smith <psmith@gnu.org> + + * dir.c (file_exists_p) [VMS]: Patch provided with Bug #3018 by + Jean-Pierre Portier <portierjp2@free.fr>. I don't understand the + file/directory naming rules for VMS so I can't tell whether this + is correct or not. + +2003-04-09 Paul D. Smith <psmith@gnu.org> + + * configure.in (HAVE_DOS_PATHS): Define this on systems that need + DOS-style pathnames: backslash separators and drive specifiers. + 2003-03-28 Paul D. Smith <psmith@gnu.org> * file.c (snap_deps): If .SECONDARY with no targets is given, set diff --git a/Makefile.am b/Makefile.am index fea1f4d..06d2df1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -38,12 +38,12 @@ AM_CPPFLAGS = $(GLOBINC) # because often that directory isn't built on the systems used by the # maintainers. -EXTRA_DIST = README build.sh.in $(man_MANS)\ - README.customs\ - SCOPTIONS SMakefile\ - README.Amiga Makefile.ami config.ami make.lnk amiga.c amiga.h\ +EXTRA_DIST = README build.sh.in $(man_MANS) \ + README.customs README.OS2 \ + SCOPTIONS SMakefile \ + README.Amiga Makefile.ami config.ami make.lnk amiga.c amiga.h \ README.DOS Makefile.DOS configure.bat dosbuild.bat configh.dos\ - README.W32 NMakefile config.h.W32 build_w32.bat subproc.bat\ + README.W32 NMakefile config.h.W32 build_w32.bat subproc.bat \ readme.vms makefile.vms makefile.com config.h-vms \ vmsdir.h vmsfunctions.c vmsify.c @@ -1,8 +1,8 @@ GNU make NEWS -*-indented-text-*- History of user-visible changes. - 03 October 2002 + 17 April 2003 -Copyright (C) 2002 Free Software Foundation, Inc. +Copyright (C) 2002,2003 Free Software Foundation, Inc. See the end for copying conditions. All changes mentioned here are more fully described in the GNU make @@ -12,7 +12,22 @@ Please send GNU make bug reports to <bug-make@gnu.org>. See the README file and the GNU make manual for details on sending bug reports. -Version 3.81a1 +Version 3.81a2 + +* GNU make is ported to OS/2. + Port provided by Andreas Buening <andreas.buening@nexgo.de>. + +* All pattern-specific variables that match a given target are now used + (previously only the first match was used). + +* Target-specific variables can be marked as exportable using the + "export" keyword. + +* In a recursive $(call ...) context, any extra arguments from the outer + call are now masked in the context of the inner call. + +* Enhancements for POSIX compatibility: + - Only touch targets (under -t) if they have at least one command. Version 3.80 diff --git a/README.OS2.template b/README.OS2.template new file mode 100644 index 0000000..eff2c0b --- /dev/null +++ b/README.OS2.template @@ -0,0 +1,159 @@ +Port of GNU make to OS/2. + +Features of GNU make that do not work under OS/2: + - remote job execution + - dynamic load balancing + + +Special features of the OS/2 version: + +Due to the fact that some people might want to use sh syntax in +Makefiles while others might want to use OS/2's native shell cmd.exe, +GNU make supports both shell types. The following list defines the order +that is used to determine the shell: + + 1. The shell specified by the environment variable MAKESHELL. + 2. The shell specified by the SHELL variable within a Makefile. As on + Unix, SHELL is NOT taken from the environment. + 3. The shell specified by the COMSPEC environment variable. + 4. The shell specified by the OS2_SHELL environment variable. + 5. If none of the above is defined /bin/sh is used as default. This + happens e.g. in the make testsuite. + +Note: - Points 3 and 4 can be turned off at compile time by adding + -DNO_CMD_DEFAULT to the CPPFLAGS. + - DOS support is not tested for EMX and therefore might not work. + - The UNIXROOT environment variable is supported to find /bin/sh + if it is not on the current drive. + + +COMPILATION OF GNU MAKE FOR OS/2: + +I. ***** SPECIAL OPTIONS ***** + + - At compile time you can turn off that cmd is used as default shell + (but only /bin/sh). Simply set CPPFLAGS="-DNO_CMD_DEFAULT" and make + will not use cmd unless you cause it to do so by setting MAKESHELL to + cmd or by specifying SHELL=cmd in your Makefile. + + - At compile time you can set CPPFLAGS="-DNO_CHDIR2" to turn off that + GNU make prints drive letters. This is necessary if you want to run + the testsuite. + + +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) + 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 + - GNU file utilities (make sure that install.exe from the file utilities + is in front of your PATH before X:\OS2\INSTALL\INSTALL.EXE. I recommend + also to change the filename to ginstall.exe instead of install.exe + to avoid confusion with X:\OS2\INSTALL\INSTALL.EXE) + - GNU shell utilities + - GNU text utilities + - gawk + - grep + - sed + - GNU make 3.79.1 (special OS/2 patched version) + - 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) + + +III. ***** COMPILATION AND INSTALLATION ***** + + a) ** Developers only - Everyone else should skip this section ** + To recreate the configuration files use: + + export EMXSHELL=ksh + aclocal -I config + automake + autoconf + autoheader + + +b) Installation into x:/usr + + Note: Although it is possible to compile make using "./configure", + "make", "make install" this is not recommended. In particular, + you must ALWAYS use LDFLAGS="-Zstack 0x8000" because the default + stack size is far to small and make will not work properly! + +Recommended environment variables and installation options: + + export ac_executable_extensions=".exe" + export CPPFLAGS="-D__ST_MT_ERRNO__" + export CFLAGS="-O2 -Zomf -Zmt" + export LDFLAGS="-Zcrtdll -Zlinker /exepack:2 -Zlinker /pm:vio -Zstack 0x8000" + export RANLIB="echo" + ./configure --prefix=x:/usr --infodir=x:/usr/share/info --mandir=x:/usr/share/man --without-included-gettext + make AR=emxomfar + make install + +Note: If you use gcc 2.9.x or higher I recommend to set also LIBS="-lgcc" + +Note: You can add -DNO_CMD_DEFAULT and -DNO_CHDIR2 to CPPFLAGS. + See section I. for details. + + +IV. ***** NLS support ***** + +GNU make has NLS (National Language Support), with the following +caveats: + + a) It will only work with GNU gettext, and + b) GNU gettext support is not included in the GNU make package. + +Therefore, if you wish to enable the internationalization features of +GNU make you must install GNU gettext on your system before configuring +GNU make. + +You can choose the languages to be installed. To install support for +English, German and French only enter: + + export LINGUAS="en de fr" + +If you don't specify LINGUAS all languages are installed. + +If you don't want NLS support (English only) use the option +--disable-nls for the configure script. Note if GNU gettext is not +installed then NLS will not be enabled regardless of this flag. + + +V. ***** Running the make test suite ***** + +To run the included make test suite you have to set + + CPPFLAGS="-D__ST_MT_ERRNO__ -DNO_CMD_DEFAULT -DNO_CHDIR2" + +before you compile make. This is due to some restrictions of the +testsuite itself. -DNO_CMD_DEFAULT causes make to use /bin/sh as default +shell in every case. Normally you could simply set MAKESHELL="/bin/sh" +to do this but the testsuite ignores the environment. -DNO_CHDIR2 causes +make not to use drive letters for directory names (i.e. _chdir2() and +_getcwd2() are NOT used). The testsuite interpretes the whole output of +make, especially statements like make[1]: Entering directory +`C:/somewhere/make-3.79.1/tests' where the testsuite does not expect the +drive letter. This would be interpreted as an error even if there is +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 RANLIB="echo" + ./configure --prefix=x:/usr --disable-nls + make AR=emxomfar + make checks + +All tests should work fine with the exception of "default_names" which +is because OS/2 file systems are not case sensitive ("makefile" and +"Makefile" specify the same file). @@ -48,6 +48,9 @@ to the point where you can run "make". Use wget to retrieve various other files that GNU make relies on, but does not keep in its own source tree. + NB: You may need GNU make to correctly perform this step; if you use + a platform-local make you may get problems with missing files in doc/. + At this point you have successfully brought your CVS copy of the GNU make source directory up to the point where it can be treated diff --git a/build.template b/build.template index 1cf7cd8..894140e 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 Free Software Foundation, Inc. +# Copyright (C) 1993, 1994, 1997, 2003 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify @@ -29,9 +29,12 @@ CPPFLAGS='@CPPFLAGS@' LDFLAGS='@LDFLAGS@' ALLOCA='@ALLOCA@' LOADLIBES='@LIBS@' -extras='@LIBOBJS@' +eval extras=\'@LIBOBJS@\' REMOTE='@REMOTE@' GLOBLIB='@GLOBLIB@' +PATH_SEPARATOR='@PATH_SEPARATOR@' +OBJEXT='@OBJEXT@' +EXEEXT='@EXEEXT@' # Common prefix for machine-independent installed files. prefix='@prefix@' @@ -43,7 +46,7 @@ libdir=${exec_prefix}/lib includedir=${prefix}/include localedir=${prefix}/share/locale -aliaspath=${localedir}:. +aliaspath=${localedir}${PATH_SEPARATOR}. defines="-DALIASPATH=\"${aliaspath}\" -DLOCALEDIR=\"${localedir}\" -DLIBDIR=\"${libdir}\" -DINCLUDEDIR=\"${includedir}\""' @DEFS@' @@ -51,7 +54,7 @@ defines="-DALIASPATH=\"${aliaspath}\" -DLOCALEDIR=\"${localedir}\" -DLIBDIR=\"${ set -e # These are all the objects we need to link together. -objs="%objs% remote-${REMOTE}.o ${extras} ${ALLOCA}" +objs="%objs% remote-${REMOTE}.${OBJEXT} ${extras} ${ALLOCA}" if [ x"$GLOBLIB" != x ]; then objs="$objs %globobjs%" @@ -59,7 +62,7 @@ if [ x"$GLOBLIB" != x ]; then fi # Compile the source files into those objects. -for file in `echo ${objs} | sed 's/\.o/.c/g'`; do +for file in `echo ${objs} | sed 's/\.'${OBJEXT}'/.c/g'`; do echo compiling ${file}... $CC $defines $CPPFLAGS $CFLAGS \ -c -I. -I${srcdir} ${globinc} ${srcdir}/$file @@ -75,6 +78,6 @@ done # Link all the objects together. echo linking make... -$CC $LDFLAGS $objs $LOADLIBES -o make.new +$CC $LDFLAGS $objs $LOADLIBES -o makenew${EXEEXT} echo done -mv -f make.new make +mv -f makenew${EXEEXT} make${EXEEXT} diff --git a/config/ChangeLog b/config/ChangeLog index 9755ae9..3192177 100644 --- a/config/ChangeLog +++ b/config/ChangeLog @@ -1,3 +1,8 @@ +2003-04-30 Paul D. Smith <psmith@gnu.org> + + * dospaths.m4: New macro to test for DOS-style pathnames, based on + coreutils 5.0 "dos.m4" by Jim Meyering. + 2002-04-21 gettextize <bug-gnu-gettext@gnu.org> * codeset.m4: New file, from gettext-0.11.1. diff --git a/config/dospaths.m4 b/config/dospaths.m4 new file mode 100644 index 0000000..3cadbbf --- /dev/null +++ b/config/dospaths.m4 @@ -0,0 +1,21 @@ +# Test if the system uses DOS-style pathnames (drive specs and backslashes) +# By Paul Smith <psmith@gnu.org>. Based on dos.m4 by Jim Meyering. + +AC_DEFUN([pds_AC_DOS_PATHS], + [ + AC_CACHE_CHECK([whether system uses MSDOS-style paths], [ac_cv_dos_paths], + [ + AC_COMPILE_IFELSE([ +#if !defined _WIN32 && !defined __WIN32__ && !defined __MSDOS__ && !defined __EMX__ +neither MSDOS nor Windows nor OS2 +#endif +], + [ac_cv_dos_paths=yes], + [ac_cv_dos_paths=no]) + ]) + + if test x"$ac_cv_dos_paths" = xyes; then + AC_DEFINE_UNQUOTED([HAVE_DOS_PATHS], 1, + [Define if the system uses DOS-style pathnames.]) + fi + ]) diff --git a/configure.in b/configure.in index c2f065e..ef44f90 100644 --- a/configure.in +++ b/configure.in @@ -103,6 +103,8 @@ if test "$make_cv_file_timestamp_hi_res" = yes; then fi fi +# Check for DOS-style pathnames. +pds_AC_DOS_PATHS # See if we have a standard version of gettimeofday(). Since actual # implementations can differ, just make sure we have the most common @@ -192,6 +194,13 @@ fi AC_MSG_RESULT($make_cv_union_wait) +# If we're building on Windows/DOS/OS/2, add some support for DOS drive specs. +if test "$PATH_SEPARATOR" = ';'; then + AC_DEFINE(HAVE_DOS_PATHS, 1, + [Define this if your system requires backslashes or drive specs in pathnames.]) +fi + + # See if the user wants to use pmake's "customs" distributed build capability AC_SUBST(REMOTE) REMOTE=stub @@ -18,12 +18,12 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "make.h" +#include "filedef.h" +#include "variable.h" #include "rule.h" #include "dep.h" -#include "filedef.h" #include "job.h" #include "commands.h" -#include "variable.h" /* Define GCC_IS_NATIVE if gcc is the native development environment on your system (gcc/bison/flex vs cc/yacc/lex). */ @@ -590,7 +590,8 @@ dir_contents_file_exists_p (struct directory_contents *dir, char *filename) #endif #ifdef __EMX__ - _fnlwr(filename); /* lower case for FAT drives */ + if (filename != 0) + _fnlwr (filename); /* lower case for FAT drives */ #endif #ifdef VMS @@ -736,8 +737,7 @@ file_exists_p (char *name) dirend = strrchr (name, ']'); if (dirend == 0) dirend = strrchr (name, ':'); - dirend++; - if (dirend == (char *)1) + if (dirend == (char *)0) return dir_file_exists_p ("[]", name); #else /* !VMS */ dirend = strrchr (name, '/'); diff --git a/doc/make.texi b/doc/make.texi index 1f491ad..1470adb 100644 --- a/doc/make.texi +++ b/doc/make.texi @@ -5245,13 +5245,16 @@ command scripts that create @file{prog.o}, @file{foo.o}, and @cindex pattern-specific variables @cindex variables, pattern-specific -In addition to target-specific variable values (@pxref{Target-specific, -,Target-specific Variable Values}), GNU @code{make} supports -pattern-specific variable values. In this form, a variable is defined -for any target that matches the pattern specified. Variables defined in -this way are searched after any target-specific variables defined -explicitly for that target, and before target-specific variables defined -for the parent target. +In addition to target-specific variable values +(@pxref{Target-specific, ,Target-specific Variable Values}), GNU +@code{make} supports pattern-specific variable values. In this form, +the variable is defined for any target that matches the pattern +specified. If a target matches more than one pattern, all the +matching pattern-specific variables are interpreted in the order in +which they were defined in the makefile, and collected together into +one set. Variables defined in this way are searched after any +target-specific variables defined explicitly for that target, and +before target-specific variables defined for the parent target. Set a pattern-specific variable value like this: @@ -681,9 +681,9 @@ func_words (char *o, char **argv, const char *funcname) static char * strip_whitespace (const char **begpp, const char **endpp) { - while (isspace ((unsigned char)**begpp) && *begpp <= *endpp) + while (*begpp <= *endpp && isspace ((unsigned char)**begpp)) (*begpp) ++; - while (isspace ((unsigned char)**endpp) && *endpp >= *begpp) + while (*endpp >= *begpp && isspace ((unsigned char)**endpp)) (*endpp) --; return (char *)*begpp; } @@ -18,9 +18,9 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "make.h" +#include "filedef.h" #include "rule.h" #include "dep.h" -#include "filedef.h" #include "debug.h" static int pattern_search PARAMS ((struct file *file, int archive, unsigned int depth, @@ -104,7 +104,7 @@ static int amiga_batch_file; #endif /* WINDOWS32 */ #ifdef __EMX__ -# include <sys/file.h> +# include <process.h> #endif #if defined (HAVE_SYS_WAIT_H) || defined (HAVE_UNION_WAIT) @@ -2507,9 +2507,9 @@ exec_command (char **argv, char **envp) # ifdef __EMX__ /* Do not use $SHELL from the environment */ - shell = lookup_variable ("SHELL", 5); - if (shell) - shell = shell->value; + struct variable *p = lookup_variable ("SHELL", 5); + if (p) + shell = p->value; else shell = 0; # else @@ -2756,11 +2756,9 @@ construct_command_argv_internal (char *line, char **restp, char *shell, DB (DB_BASIC, (_("$SHELL changed (was `%s', now `%s')\n"), default_shell, shell)); unixy_shell = _is_unixy_shell (shell); - default_shell = shell; /* we must allocate a copy of shell: construct_command_argv() will free * shell after this function returns. */ - default_shell = xmalloc (strlen (shell) + 1); - strcpy (default_shell, shell); + default_shell = xstrdup (shell); } if (unixy_shell) { @@ -2778,6 +2776,7 @@ construct_command_argv_internal (char *line, char **restp, char *shell, sh_cmds = sh_cmds_os2; } # endif + } #else /* !__MSDOS__ */ else if (strcmp (shell, default_shell)) goto slow; diff --git a/maintMakefile b/maintMakefile index 1bf49f0..1c93463 100644 --- a/maintMakefile +++ b/maintMakefile @@ -8,7 +8,7 @@ globsrc := $(wildcard glob/*.c) globhdr := $(wildcard glob/*.h) -TEMPLATES = README README.DOS README.W32 \ +TEMPLATES = README README.DOS README.W32 README.OS2 \ config.ami configh.dos config.h.W32 config.h-vms MTEMPLATES = Makefile.DOS SMakefile @@ -54,8 +54,8 @@ NMakefile: NMakefile.template .dep_segment Makefile # build.sh.in: build.template Makefile rm -f $@ - sed -e 's@%objs%@$(filter-out remote-%,$(make_OBJECTS)@g' \ - -e 's@%globobjs%@$(patsubst %.c,%.o,$(globsrc)))@g' \ + sed -e 's@%objs%@$(patsubst %.o,%.$${OBJEXT},$(filter-out remote-%,$(make_OBJECTS)))@g' \ + -e 's@%globobjs%@$(patsubst %.c,%.$${OBJEXT},$(globsrc)))@g' \ $< > $@ chmod a-w+x $@ @@ -1667,9 +1667,9 @@ record_target_var (struct nameseq *filenames, char *defn, int two_colon, { struct variable *v; register char *name = filenames->name; - struct variable_set_list *vlist; char *fname; char *percent; + struct pattern_var *p; nextf = filenames->next; free ((char *) filenames); @@ -1679,11 +1679,13 @@ record_target_var (struct nameseq *filenames, char *defn, int two_colon, percent = find_percent (name); if (percent) { - struct pattern_var *p; - /* Get a reference for this pattern-specific variable struct. */ - p = create_pattern_var(name, percent); - vlist = p->vars; + p = create_pattern_var (name, percent); + p->variable.fileinfo = *flocp; + v = parse_variable_definition (&p->variable, defn); + v->value = xstrdup (v->value); + if (!v) + error (flocp, _("Malformed pattern-specific variable definition")); fname = p->target; } else @@ -1701,15 +1703,17 @@ record_target_var (struct nameseq *filenames, char *defn, int two_colon, f = f->double_colon; initialize_file_variables (f, 1); - vlist = f->variables; fname = f->name; + + current_variable_set_list = f->variables; + v = try_variable_definition (flocp, defn, origin, 1); + if (!v) + error (flocp, _("Malformed target-specific variable definition")); + current_variable_set_list = global; } - /* Make the new variable context current and define the variable. */ - current_variable_set_list = vlist; - v = try_variable_definition (flocp, defn, origin, 1); - if (!v) - error (flocp, _("Malformed per-target variable definition")); + /* Set up the variable to be *-specific. */ + v->origin = origin; v->per_target = 1; if (exported) v->export = v_export; @@ -1721,12 +1725,14 @@ record_target_var (struct nameseq *filenames, char *defn, int two_colon, struct variable *gv; int len = strlen(v->name); - current_variable_set_list = global; gv = lookup_variable (v->name, len); if (gv && (gv->origin == o_env_override || gv->origin == o_command)) { - v = define_variable_in_set (v->name, len, gv->value, gv->origin, - gv->recursive, vlist->set, flocp); + if (v->value != 0) + free (v->value); + v->value = xstrdup (gv->value); + v->origin = gv->origin; + v->recursive = gv->recursive; v->append = 0; } } @@ -1735,8 +1741,6 @@ record_target_var (struct nameseq *filenames, char *defn, int two_colon, if (name != fname && (name < fname || name > fname + strlen (fname))) free (name); } - - current_variable_set_list = global; } /* Record a description line for files FILENAMES, @@ -51,14 +51,6 @@ unsigned int max_pattern_deps; unsigned int max_pattern_dep_length; -/* Chain of all pattern-specific variables. */ - -static struct pattern_var *pattern_vars; - -/* Pointer to last struct in the chain, so we can add onto the end. */ - -static struct pattern_var *last_pattern_var; - /* Pointer to structure for the file .SUFFIXES whose dependencies are the suffixes to be searched. */ @@ -537,76 +529,6 @@ create_pattern_rule (char **targets, char **target_percents, r->terminal = terminal; } -/* Create a new pattern-specific variable struct. */ - -struct pattern_var * -create_pattern_var (char *target, char *suffix) -{ - register struct pattern_var *p = 0; - unsigned int len = strlen(target); - - /* Look to see if this pattern already exists in the list. */ - for (p = pattern_vars; p != NULL; p = p->next) - if (p->len == len && !strcmp(p->target, target)) - break; - - if (p == 0) - { - p = (struct pattern_var *) xmalloc (sizeof (struct pattern_var)); - if (last_pattern_var != 0) - last_pattern_var->next = p; - else - pattern_vars = p; - last_pattern_var = p; - p->next = 0; - p->target = target; - p->len = len; - p->suffix = suffix + 1; - p->vars = create_new_variable_set(); - } - - return p; -} - -/* Look up a target in the pattern-specific variable list. */ - -struct pattern_var * -lookup_pattern_var (char *target) -{ - struct pattern_var *p; - unsigned int targlen = strlen(target); - - for (p = pattern_vars; p != 0; p = p->next) - { - char *stem; - unsigned int stemlen; - - if (p->len > targlen) - /* It can't possibly match. */ - continue; - - /* From the lengths of the filename and the pattern parts, - find the stem: the part of the filename that matches the %. */ - stem = target + (p->suffix - p->target - 1); - stemlen = targlen - p->len + 1; - - /* Compare the text in the pattern before the stem, if any. */ - if (stem > target && !strneq (p->target, target, stem - target)) - continue; - - /* Compare the text in the pattern after the stem, if any. - 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]))) - break; - } - - return p; -} - /* Print the data base of rules. */ static void /* Useful to call from gdb. */ @@ -678,26 +600,4 @@ print_rule_data_base (void) fatal (NILF, _("BUG: num_pattern_rules wrong! %u != %u"), num_pattern_rules, rules); } - - puts (_("\n# Pattern-specific variable values")); - - { - struct pattern_var *p; - - rules = 0; - for (p = pattern_vars; p != 0; p = p->next) - { - ++rules; - - printf ("\n%s :\n", p->target); - print_variable_set (p->vars->set, "# "); - } - - if (rules == 0) - puts (_("\n# No pattern-specific variable values.")); - else - { - printf (_("\n# %u pattern-specific variable values"), rules); - } - } } @@ -31,15 +31,6 @@ struct rule char in_use; /* If in use by a parent pattern_search. */ }; -struct pattern_var - { - struct pattern_var *next; - char *target; - unsigned int len; - char *suffix; - struct variable_set_list *vars; - }; - /* For calling install_pattern_rule. */ struct pspec { @@ -61,8 +52,6 @@ extern unsigned int maxsuffix; extern void install_pattern_rule PARAMS ((struct pspec *p, int terminal)); extern int new_pattern_rule PARAMS ((struct rule *rule, int override)); -extern struct pattern_var *create_pattern_var PARAMS ((char *target, char *suffix)); -extern struct pattern_var *lookup_pattern_var PARAMS ((char *target)); extern void count_implicit_rule_limits PARAMS ((void)); extern void convert_to_pattern PARAMS ((void)); extern void create_pattern_rule PARAMS ((char **targets, diff --git a/tests/ChangeLog b/tests/ChangeLog index b4ba23e..3880e8a 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,14 @@ +2003-04-19 Paul D. Smith <psmith@gnu.org> + + * scripts/features/patspecific_vars: Test multiple patterns + matching the same target--Bug #1405. + +2003-04-09 Paul D. Smith <psmith@gnu.org> + + * run_make_tests.pl (set_more_defaults): A new $port_type of + 'OS/2' for (surprise!) OS/2. Also choose a wait time of 2 seconds + for OS/2. + 2003-03-28 Paul D. Smith <psmith@gnu.org> * scripts/targets/SECONDARY: Test the "global" .SECONDARY (with diff --git a/tests/run_make_tests.pl b/tests/run_make_tests.pl index 0ada574..4389d43 100755 --- a/tests/run_make_tests.pl +++ b/tests/run_make_tests.pl @@ -169,6 +169,10 @@ sub set_more_defaults elsif ($osname =~ /^([^ ]*|[^ ]* [^ ]*)D(OS|os|ev) /) { $port_type = 'DOS'; } + # Check for OS/2 + elsif ($osname =~ m%OS/2%) { + $port_type = 'OS/2'; + } # Everything else, right now, is UNIX. Note that we should integrate # the VOS support into this as well and get rid of $vos; we'll do # that next time. @@ -180,7 +184,7 @@ sub set_more_defaults # timestamps with second granularity (!!). Change the sleep time # needed to force a file to be considered "old". # - $wtime = $port_type eq 'UNIX' ? 1 : 4; + $wtime = $port_type eq 'UNIX' ? 1 : $port_type eq 'OS/2' ? 2 : 4; # Find the full pathname of Make. For DOS systems this is more # complicated, so we ask make itself. diff --git a/tests/scripts/features/patspecific_vars b/tests/scripts/features/patspecific_vars index 7feb687..9ace5c4 100644 --- a/tests/scripts/features/patspecific_vars +++ b/tests/scripts/features/patspecific_vars @@ -13,14 +13,22 @@ all: one.x two.x three.x FOO = foo BAR = bar BAZ = baz -thr% : override BAZ = three -t%.x: BAR = four -%.x: BAR = two -%.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) +%.x: BAR = two +t%.x: BAR = four +thr% : override BAZ = three +one.x two.x three.x: ; @echo $@: $(FOO) $(BAR) $(BAZ) +four.x: baz ; @echo $@: $(FOO) $(BAR) $(BAZ) +baz: ; @echo $@: $(FOO) $(BAR) $(BAZ) + +# test matching multiple patterns +a%: AAA = aaa +%b: BBB = ccc +a%: BBB += ddd +%b: AAA ?= xxx +%b: AAA += bbb +.PHONY: ab +ab: ; @echo $(AAA); echo $(BBB) EOF close(MAKEFILE); @@ -29,21 +37,28 @@ close(MAKEFILE); # TEST #1 -- basics &run_make_with_options($makefile, "", &get_logfile); -$answer = "one two three\nfoo four baz\nfoo bar three\n"; +$answer = "one.x: one two baz\ntwo.x: foo four baz\nthree.x: foo four three\n"; &compare_output($answer,&get_logfile(1)); # TEST #2 -- try the override feature &run_make_with_options($makefile, "BAZ=five", &get_logfile); -$answer = "one two three\nfoo four five\nfoo bar three\n"; +$answer = "one.x: one two five\ntwo.x: foo four five\nthree.x: foo four 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"; +$answer = "baz: foo two baz\nfour.x: foo two baz\n"; +&compare_output($answer,&get_logfile(1)); + + +# TEST #4 -- test multiple patterns matching the same target + +&run_make_with_options($makefile, "ab", &get_logfile); +$answer = "aaa bbb\nccc ddd\n"; &compare_output($answer,&get_logfile(1)); 1; @@ -30,6 +30,75 @@ Boston, MA 02111-1307, USA. */ #endif #include "hash.h" +/* Chain of all pattern-specific variables. */ + +static struct pattern_var *pattern_vars; + +/* Pointer to last struct in the chain, so we can add onto the end. */ + +static struct pattern_var *last_pattern_var; + +/* Create a new pattern-specific variable struct. */ + +struct pattern_var * +create_pattern_var (char *target, char *suffix) +{ + register struct pattern_var *p + = (struct pattern_var *) xmalloc (sizeof (struct pattern_var)); + + if (last_pattern_var != 0) + last_pattern_var->next = p; + else + pattern_vars = p; + last_pattern_var = p; + p->next = 0; + + p->target = target; + p->len = strlen (target); + p->suffix = suffix + 1; + + return p; +} + +/* Look up a target in the pattern-specific variable list. */ + +static struct pattern_var * +lookup_pattern_var (struct pattern_var *start, char *target) +{ + struct pattern_var *p; + unsigned int targlen = strlen(target); + + for (p = start ? start->next : pattern_vars; p != 0; p = p->next) + { + char *stem; + unsigned int stemlen; + + if (p->len > targlen) + /* It can't possibly match. */ + continue; + + /* From the lengths of the filename and the pattern parts, + find the stem: the part of the filename that matches the %. */ + stem = target + (p->suffix - p->target - 1); + stemlen = targlen - p->len + 1; + + /* Compare the text in the pattern before the stem, if any. */ + if (stem > target && !strneq (p->target, target, stem - target)) + continue; + + /* Compare the text in the pattern after the stem, if any. + 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]))) + break; + } + + return p; +} + /* Hash table of all global variable definitions. */ static unsigned long @@ -147,6 +216,7 @@ define_variable_in_set (const char *name, unsigned int length, v->fileinfo.filenm = 0; v->origin = origin; v->recursive = recursive; + v->special = 0; v->expanding = 0; v->exp_count = 0; v->per_target = 0; @@ -405,21 +475,33 @@ initialize_file_variables (struct file *file, int reading) } /* If we're not reading makefiles and we haven't looked yet, see if - we can find a pattern variable. */ + we can find pattern variables for this target. */ if (!reading && !file->pat_searched) { - struct pattern_var *p = lookup_pattern_var (file->name); + struct pattern_var *p; - file->pat_searched = 1; + p = lookup_pattern_var (0, file->name); 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; + struct variable_set_list *global = current_variable_set_list; + + /* We found at least one. Set up a new variable set to accumulate + all the pattern variables that match this target. */ + + file->pat_variables = create_new_variable_set (); + current_variable_set_list = file->pat_variables; + + do + /* We found one, so insert it into the set. */ + do_variable_definition (&p->variable.fileinfo, p->variable.name, + p->variable.value, p->variable.origin, + p->variable.flavor, 1); + while ((p = lookup_pattern_var (p, file->name)) != 0); + + current_variable_set_list = global; } + file->pat_searched = 1; } /* If we have a pattern variable match, set it up. */ @@ -483,7 +565,7 @@ push_new_variable_scope (void) return (current_variable_set_list = create_new_variable_set()); } -/* Merge SET1 into SET0, freeing unused storage in SET1. */ +/* Merge FROM_SET into TO_SET, freeing unused storage in FROM_SET. */ static void merge_variable_sets (struct variable_set *to_set, @@ -834,6 +916,7 @@ do_variable_definition (const struct floc *flocp, const char *varname, char *p, *alloc_value = NULL; struct variable *v; int append = 0; + int conditional = 0; /* Calculate the variable's new value in VALUE. */ @@ -857,6 +940,7 @@ do_variable_definition (const struct floc *flocp, const char *varname, if (v) return v; + conditional = 1; flavor = f_recursive; /* FALLTHROUGH */ case f_recursive: @@ -1034,6 +1118,7 @@ do_variable_definition (const struct floc *flocp, const char *varname, ? current_variable_set_list->set : NULL), flocp); v->append = append; + v->conditional = conditional; if (alloc_value) free (alloc_value); @@ -1055,16 +1140,14 @@ do_variable_definition (const struct floc *flocp, const char *varname, returned. */ struct variable * -try_variable_definition (const struct floc *flocp, char *line, - enum variable_origin origin, int target_var) +parse_variable_definition (struct variable *v, char *line) { register int c; register char *p = line; register char *beg; register char *end; enum variable_flavor flavor = f_bogus; - char *name, *expanded_name; - struct variable *v; + char *name; while (1) { @@ -1128,27 +1211,60 @@ try_variable_definition (const struct floc *flocp, char *line, } } } + v->flavor = flavor; beg = next_token (line); while (end > beg && isblank ((unsigned char)end[-1])) --end; p = next_token (p); + v->value = p; /* Expand the name, so "$(foo)bar = baz" works. */ name = (char *) alloca (end - beg + 1); bcopy (beg, name, end - beg); name[end - beg] = '\0'; - expanded_name = allocated_variable_expand (name); + v->name = allocated_variable_expand (name); + + if (v->name[0] == '\0') + fatal (&v->fileinfo, _("empty variable name")); + + return v; +} + +/* Try to interpret LINE (a null-terminated string) as a variable definition. - if (expanded_name[0] == '\0') - fatal (flocp, _("empty variable name")); + ORIGIN may be o_file, o_override, o_env, o_env_override, + or o_command specifying that the variable definition comes + from a makefile, an override directive, the environment with + or without the -e switch, or the command line. - v = do_variable_definition (flocp, expanded_name, p, - origin, flavor, target_var); + See the comments for parse_variable_definition(). - free (expanded_name); + If LINE was recognized as a variable definition, a pointer to its `struct + variable' is returned. If LINE is not a variable definition, NULL is + returned. */ - return v; +struct variable * +try_variable_definition (const struct floc *flocp, char *line, + enum variable_origin origin, int target_var) +{ + struct variable v; + struct variable *vp; + + if (flocp != 0) + v.fileinfo = *flocp; + else + v.fileinfo.filenm = 0; + + if (!parse_variable_definition (&v, line)) + return 0; + + vp = do_variable_definition (flocp, v.name, v.value, + origin, v.flavor, target_var); + + free (v.name); + + return vp; } /* Print information for variable V, prefixing it with PREFIX. */ @@ -1246,6 +1362,25 @@ print_variable_data_base (void) puts (_("\n# Variables\n")); print_variable_set (&global_variable_set, ""); + + puts (_("\n# Pattern-specific Variable Values")); + + { + struct pattern_var *p; + int rules = 0; + + for (p = pattern_vars; p != 0; p = p->next) + { + ++rules; + printf ("\n%s :\n", p->target); + print_variable (&p->variable, "# "); + } + + if (rules == 0) + puts (_("\n# No pattern-specific variable values.")); + else + printf (_("\n# %u pattern-specific variable values"), rules); + } } @@ -47,7 +47,6 @@ enum variable_flavor chained through `next'. */ #define EXP_COUNT_BITS 15 /* This gets all the bitfields into 32 bits */ - #define EXP_COUNT_MAX ((1<<EXP_COUNT_BITS)-1) struct variable @@ -57,20 +56,21 @@ struct variable char *value; /* Variable value. */ struct floc fileinfo; /* Where the variable was defined. */ unsigned int recursive:1; /* Gets recursively re-evaluated. */ - unsigned int per_target:1; /* Nonzero if a target-specific variable. */ unsigned int append:1; /* Nonzero if an appending target-specific variable. */ + unsigned int conditional:1; /* Nonzero if set with a ?=. */ + unsigned int per_target:1; /* Nonzero if a target-specific variable. */ unsigned int special:1; /* Nonzero if this is a special variable. */ + unsigned int exportable:1; /* Nonzero if the variable _could_ be + exported. */ unsigned int expanding:1; /* Nonzero if currently being expanded. */ unsigned int exp_count:EXP_COUNT_BITS; /* If >1, allow this many self-referential expansions. */ - + enum variable_flavor + flavor ENUM_BITFIELD (3); /* Variable flavor. */ enum variable_origin origin ENUM_BITFIELD (3); /* Variable origin. */ - - unsigned int exportable:1; /* Nonzero if the variable _could_ be - exported. */ enum variable_export { v_export, /* Export this variable. */ @@ -95,6 +95,17 @@ struct variable_set_list struct variable_set *set; /* Variable set. */ }; +/* Structure used for pattern-specific variables. */ + +struct pattern_var + { + struct pattern_var *next; + char *target; + unsigned int len; + char *suffix; + struct variable variable; + }; + extern char *variable_buffer; extern struct variable_set_list *current_variable_set_list; @@ -131,8 +142,9 @@ extern void define_automatic_variables PARAMS ((void)); 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 void merge_variable_set_lists PARAMS ((struct variable_set_list **to_list, struct variable_set_list *from_list)); extern struct variable *do_variable_definition PARAMS ((const struct floc *flocp, const char *name, char *value, enum variable_origin origin, enum variable_flavor flavor, int target_var)); +extern struct variable *parse_variable_definition PARAMS ((struct variable *v, char *line)); extern struct variable *try_variable_definition PARAMS ((const struct floc *flocp, char *line, enum variable_origin origin, int target_var)); extern void init_hash_global_variable_set PARAMS ((void)); extern void hash_init_function_table PARAMS ((void)); @@ -179,6 +191,8 @@ extern struct variable *define_variable_in_set extern char **target_environment PARAMS ((struct file *file)); +extern struct pattern_var *create_pattern_var PARAMS ((char *target, char *suffix)); + extern int export_all_variables; #define MAKELEVEL_NAME "MAKELEVEL" |