- Fix some uncleanliness about the implementation of patterns-specific vars.
- Some enhancements to the OS/2 port.
+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
# 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
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
See the README file and the GNU make manual for details on sending bug
reports.
\f
-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.
\f
Version 3.80
--- /dev/null
+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).
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
# 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
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@'
includedir=${prefix}/include
localedir=${prefix}/share/locale
-aliaspath=${localedir}:.
+aliaspath=${localedir}${PATH_SEPARATOR}.
defines="-DALIASPATH=\"${aliaspath}\" -DLOCALEDIR=\"${localedir}\" -DLIBDIR=\"${libdir}\" -DINCLUDEDIR=\"${includedir}\""' @DEFS@'
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%"
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
# 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}
+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.
--- /dev/null
+# 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
+ ])
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
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
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). */
#endif
#ifdef __EMX__
- _fnlwr(filename); /* lower case for FAT drives */
+ if (filename != 0)
+ _fnlwr (filename); /* lower case for FAT drives */
#endif
#ifdef VMS
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, '/');
@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:
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;
}
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,
#endif /* WINDOWS32 */
#ifdef __EMX__
-# include <sys/file.h>
+# include <process.h>
#endif
#if defined (HAVE_SYS_WAIT_H) || defined (HAVE_UNION_WAIT)
# 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
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)
{
sh_cmds = sh_cmds_os2;
}
# endif
+ }
#else /* !__MSDOS__ */
else if (strcmp (shell, default_shell))
goto slow;
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
#
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 $@
{
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);
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
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;
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;
}
}
if (name != fname && (name < fname || name > fname + strlen (fname)))
free (name);
}
-
- current_variable_set_list = global;
}
\f
/* Record a description line for files FILENAMES,
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. */
r->terminal = terminal;
}
\f
-/* 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;
-}
-\f
-/* 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;
-}
-\f
/* Print the data base of rules. */
static void /* Useful to call from gdb. */
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);
- }
- }
}
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
{
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,
+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
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.
# 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.
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);
# 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;
#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;
+}
+\f
/* Hash table of all global variable definitions. */
static unsigned long
v->fileinfo.filenm = 0;
v->origin = origin;
v->recursive = recursive;
+ v->special = 0;
v->expanding = 0;
v->exp_count = 0;
v->per_target = 0;
}
/* 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. */
return (current_variable_set_list = create_new_variable_set());
}
\f
-/* 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,
char *p, *alloc_value = NULL;
struct variable *v;
int append = 0;
+ int conditional = 0;
/* Calculate the variable's new value in VALUE. */
if (v)
return v;
+ conditional = 1;
flavor = f_recursive;
/* FALLTHROUGH */
case f_recursive:
? current_variable_set_list->set : NULL),
flocp);
v->append = append;
+ v->conditional = conditional;
if (alloc_value)
free (alloc_value);
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)
{
}
}
}
+ 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;
+}
+\f
+/* 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;
}
\f
/* Print information for variable V, prefixing it with PREFIX. */
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);
+ }
}
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
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. */
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;
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));
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"