-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Digging through the archives of m4 wish list items: http://lists.gnu.org/archive/html/m4-patches/2003-09/msg00027.html Here is my proposal for adding a --prepend-include option to m4 2.0, so that once autom4te requires 2.0, it can search for files outside of the current working directory first. I do have a question, though. Some implementations of m4 (such as Solaris) have a -B<num> option, which changes the size of the rescan buffer from its default of 4096 bytes. Obviously, this is an arbitrary limit, so GNU m4 doesn't need this option, but m4 1.4.x silently accepts and ignores the -B option for compatibility. If I make -B a synonym for --prepend-include, then a user doing 'm4 - -B1024' and expecting traditional Solaris semantics would have subtly different behavior if they happened to have a ./1024/ directory. But since POSIX does not specify -B, a user can't expect it to be portable anyways. So should I go ahead and make -B a short option synonym? One other thing to think of. Right now, CVS m4 has different behavior depending on whether POSIXLY_CORRECT vs. -G was specified, although both of those disable various GNU extensions incompatible with POSIX and/or traditional implementations. This is a maintenance nightmare, and I would rather see POSIXLY_CORRECT imply -G, add an option -g (--gnu) to override it (and some BSD versions already have -g to turn on GNU compatibility), and then base all compatibility decisions solely on whether -G is in effect. And currently, -G disables path searches for including files. So by that proposal, a user could then do 'POSIXLY_CORRECT=1 m4 -B1024' to get the same behavior with GNU or Solaris m4, regardless of the presence of ./1024, because path searches would be disabled in the GNU version thanks to the implicit -G. This patch also fixes 'm4 --help --version' to display help, consistent with coreutils, rather than its current behavior of showing the version. 2006-08-23 Eric Blake <ebb9@xxxxxxx> * src/main.c (long_options, main): Add --prepend-include. (usage): Document it. (main): `m4 --help --version' now displays help, not version. * ltdl/m4/gnulib-cache.m4: Augment with gnulib-tool --import dirname filenamecat. * m4/m4module.h (m4_add_include_directory): Add parameter. * m4/m4private.h (m4__include_init): New prototype. * m4/m4.c (m4_create): Put `.' on path before options are collected. * m4/path.c (includes): Assume C89. Use gnulib for file name management. (m4__include_init): New function. (search_path_add): Allow prepending. (m4_add_include_directory, search_path_env_init): Adjust callers. (m4_path_search): Relative names now invoke path search, since `.' might not be first. * doc/m4.texinfo (Invoking m4, Search Path): Document new option. - -- Life is short - so eat dessert first! Eric Blake ebb9@xxxxxxx -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.2.1 (Cygwin) Comment: Public key at home.comcast.net/~ericblake/eblake.gpg Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFE7HMe84KuGfSFAYARAmo9AKCDAFEHpIgo43f38UakVzpI5HwWiwCgx8+v hnAJnWEQ11yZCC9DIaXpyzk= =/4dj -----END PGP SIGNATURE-----
? ltdl/m4/dirname.m4 ? ltdl/m4/dos.m4 ? ltdl/m4/double-slash-root.m4 ? ltdl/m4/filenamecat.m4 Index: doc/m4.texinfo =================================================================== RCS file: /sources/m4/m4/doc/m4.texinfo,v retrieving revision 1.32 diff -u -p -r1.32 m4.texinfo --- doc/m4.texinfo 23 Aug 2006 11:39:26 -0000 1.32 +++ doc/m4.texinfo 23 Aug 2006 15:02:40 -0000 @@ -261,7 +261,7 @@ Fast loading of frozen state Compatibility with other versions of @code{m4} -* Extensions:: Extensions in @acronym{GNU} m4 +* Extensions:: Extensions in @acronym{GNU} M4 * Incompatibilities:: Other incompatibilities Copying This Manual @@ -497,8 +497,16 @@ Imports every variable in the environmen before @option{-D} and @option{-U}, so they can override the enviroment. -@comment FIXME - need to implement -B/--prepend=DIR, to prepend to the -@comment search path prior to `.'. +@comment FIXME - should we make -B a synonym for --prepend-include? The +@comment only drawback is that -B1024 is currently ignored for +@comment compatibility, but if the user actually had a directory ./1024, +@comment it would subtly change the semantics. But POSIX doesn't +@comment specify -B, so we are free to define it how we want. +@item --prepend-include=@var{DIRECTORY} +Make @code{m4} search @var{DIRECTORY} for included files, prior to +searching the current working directory. @xref{Search Path}, for more +details. This option may be given more than once. + @item -D @var{NAME}@r{[}=@var{VALUE}@r{]} @itemx --define=@var{NAME}@r{[}=@var{VALUE}@r{]} This enters @var{NAME} into the symbol table, before any input files are @@ -2803,12 +2811,13 @@ In GNU @code{m4}, an alternative method GNU @code{m4} allows included files to be found in other directories than the current working directory. -If a file is not found in the current working directory, and the file -name is not absolute, the file will be looked for in a specified search -path. First, the directories specified with the @samp{-I} option will -be searched, in the order found on the command line. Second, if the -@samp{M4PATH} environment variable is set, it is expected to contain a -colon-separated list of directories, which will be searched in order. +If the @option{-B} option was provided (@pxref{Invoking m4}), those +directories are searched first, in the order found on the command line. +Then @code{m4} looks in the current working directory. Next comes the +directories specified with the @option{-I} option will be searched, in +the order found on the command line. Finally, if the @env{M4PATH} +environment variable is set, it is expected to contain a colon-separated +list of directories, which will be searched in order. If the automatic search for include-files causes trouble, the @samp{p} debug flag (@pxref{Debug Levels}) can help isolate the problem. Index: ltdl/m4/gnulib-cache.m4 =================================================================== RCS file: /sources/m4/m4/ltdl/m4/gnulib-cache.m4,v retrieving revision 1.8 diff -u -p -r1.8 gnulib-cache.m4 --- ltdl/m4/gnulib-cache.m4 22 Aug 2006 22:36:28 -0000 1.8 +++ ltdl/m4/gnulib-cache.m4 23 Aug 2006 15:02:40 -0000 @@ -15,10 +15,10 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --lib=libgnu --source-base=gnu --m4-base=ltdl/m4 --doc-base=doc --aux-dir=ltdl/config --libtool --macro-prefix=M4 assert binary-io cloexec close-stream error exit fdl fopen-safer free gendocs getopt gettext gnupload mkstemp obstack progname regex regexprops-generic stdbool stdlib-safer strtol unlocked-io verror xalloc xalloc-die xstrndup xvasprintf +# gnulib-tool --import --dir=. --lib=libgnu --source-base=gnu --m4-base=ltdl/m4 --doc-base=doc --aux-dir=ltdl/config --libtool --macro-prefix=M4 assert binary-io cloexec close-stream dirname error exit fdl filenamecat fopen-safer free gendocs getopt gettext gnupload mkstemp obstack progname regex regexprops-generic stdbool stdlib-safer strtol unlocked-io verror xalloc xalloc-die xstrndup xvasprintf # Specification in the form of a few gnulib-tool.m4 macro invocations: -gl_MODULES([assert binary-io cloexec close-stream error exit fdl fopen-safer free gendocs getopt gettext gnupload mkstemp obstack progname regex regexprops-generic stdbool stdlib-safer strtol unlocked-io verror xalloc xalloc-die xstrndup xvasprintf]) +gl_MODULES([assert binary-io cloexec close-stream dirname error exit fdl filenamecat fopen-safer free gendocs getopt gettext gnupload mkstemp obstack progname regex regexprops-generic stdbool stdlib-safer strtol unlocked-io verror xalloc xalloc-die xstrndup xvasprintf]) gl_AVOID([]) gl_SOURCE_BASE([gnu]) gl_M4_BASE([ltdl/m4]) Index: m4/m4.c =================================================================== RCS file: /sources/m4/m4/m4/m4.c,v retrieving revision 1.16 diff -u -p -r1.16 m4.c --- m4/m4.c 27 Jul 2006 22:34:55 -0000 1.16 +++ m4/m4.c 23 Aug 2006 15:02:40 -0000 @@ -37,6 +37,7 @@ m4_create (void) context->nesting_limit = DEFAULT_NESTING_LIMIT; context->search_path = xzalloc (sizeof context->search_path); + m4__include_init (context); return context; } Index: m4/m4module.h =================================================================== RCS file: /sources/m4/m4/m4/m4module.h,v retrieving revision 1.78 diff -u -p -r1.78 m4module.h --- m4/m4module.h 23 Aug 2006 11:39:26 -0000 1.78 +++ m4/m4module.h 23 Aug 2006 15:02:40 -0000 @@ -386,7 +386,7 @@ extern void m4_undivert_all (m4 *); /* --- PATH MANAGEMENT --- */ extern void m4_include_env_init (m4 *); -extern void m4_add_include_directory (m4 *, const char *); +extern void m4_add_include_directory (m4 *, const char *, bool); extern FILE * m4_path_search (m4 *, const char *, char **); Index: m4/m4private.h =================================================================== RCS file: /sources/m4/m4/m4/m4private.h,v retrieving revision 1.54 diff -u -p -r1.54 m4private.h --- m4/m4private.h 22 Aug 2006 22:36:28 -0000 1.54 +++ m4/m4private.h 23 Aug 2006 15:02:40 -0000 @@ -323,6 +323,7 @@ struct m4__search_path_info { int max_length; /* length of longest directory name */ }; +extern void m4__include_init (m4 *); /* Debugging the memory allocator. */ Index: m4/path.c =================================================================== RCS file: /sources/m4/m4/m4/path.c,v retrieving revision 1.18 diff -u -p -r1.18 path.c --- m4/path.c 22 Aug 2006 22:36:28 -0000 1.18 +++ m4/path.c 23 Aug 2006 15:02:40 -0000 @@ -26,25 +26,19 @@ # include <config.h> #endif -#if HAVE_STDLIB_H -# include <stdlib.h> -#endif - -#if HAVE_STRING_H -# include <string.h> -#else -# if HAVE_STRINGS_H -# include <strings.h> -# endif -#endif +#include <stdlib.h> +#include <string.h> #include "m4module.h" #include "m4private.h" +#include "dirname.h" +#include "filenamecat.h" + /* Define this to see runtime debug info. Implied by DEBUG. */ /*#define DEBUG_INCL */ -static void search_path_add (m4__search_path_info *, const char *); +static void search_path_add (m4__search_path_info *, const char *, bool); static void search_path_env_init (m4__search_path_info *, char *, bool); @@ -53,25 +47,33 @@ static void search_path_env_init (m4__se */ static void -search_path_add (m4__search_path_info *info, const char *dir) +search_path_add (m4__search_path_info *info, const char *dir, bool prepend) { m4__search_path *path = xmalloc (sizeof *path); - if (*dir == '\0') - dir = "."; - - path->next = NULL; path->len = strlen (dir); path->dir = xstrdup (dir); if (path->len > info->max_length) /* remember len of longest directory */ info->max_length = path->len; - if (info->list_end == NULL) - info->list = path; + if (prepend) + { + path->next = info->list; + info->list = path; + if (info->list_end == NULL) + info->list_end = path; + } else - info->list_end->next = path; - info->list_end = path; + { + path->next = NULL; + + if (info->list_end == NULL) + info->list = path; + else + info->list_end->next = path; + info->list_end = path; + } } static void @@ -88,7 +90,7 @@ search_path_env_init (m4__search_path_in if (path_end) *path_end = '\0'; if (!isabs || *path == '/') - search_path_add (info, path); + search_path_add (info, path, false); path = path_end + 1; } while (path_end); @@ -108,25 +110,33 @@ m4_include_env_init (m4 *context) } void -m4_add_include_directory (m4 *context, const char *dir) +m4_add_include_directory (m4 *context, const char *dir, bool prepend) { if (m4_get_no_gnu_extensions_opt (context)) return; - search_path_add (m4__get_search_path (context), dir); + search_path_add (m4__get_search_path (context), dir, prepend); #ifdef DEBUG_INCL - fprintf (stderr, "add_include_directory (%s);\n", dir); + fprintf (stderr, "add_include_directory (%s) %s;\n", dir, + prepend ? "prepend" : "append"); #endif } +/* Search for FILE according to -B options, `.', -I options, then + M4PATH environment. If successful, return the open file, and if + RESULT is not NULL, set *RESULT to a malloc'd string that + represents the file found with respect to the current working + directory. Otherwise, return NULL, and errno reflects the failure + from searching `.' (regardless of what else was searched). */ + FILE * m4_path_search (m4 *context, const char *file, char **expanded_name) { FILE *fp; m4__search_path *incl; char *name; /* buffer for constructed name */ - int e; + int e = 0; if (expanded_name != NULL) *expanded_name = NULL; @@ -138,32 +148,27 @@ m4_path_search (m4 *context, const char return NULL; } - /* Look in current working directory first. */ - fp = fopen (file, "r"); - if (fp != NULL) - { - if (set_cloexec_flag (fileno (fp), true) != 0) - m4_error (context, 0, errno, - _("cannot protect input file across forks")); - if (expanded_name != NULL) - *expanded_name = xstrdup (file); - return fp; - } - - /* If file not found, and filename absolute, fail. */ - if (*file == '/' || m4_get_no_gnu_extensions_opt (context)) - return NULL; - e = errno; - - name = (char *) xmalloc (m4__get_search_path (context)->max_length - + 1 + strlen (file) + 1); + /* If file is absolute, or if we are not searching a path, a single + lookup will do the trick. */ + if (IS_ABSOLUTE_FILE_NAME (file) || m4_get_no_gnu_extensions_opt (context)) + { + fp = fopen (file, "r"); + if (fp != NULL) + { + if (set_cloexec_flag (fileno (fp), true) != 0) + m4_error (context, 0, errno, + _("cannot protect input file across forks")); + if (expanded_name != NULL) + *expanded_name = xstrdup (file); + return fp; + } + return NULL; + } for (incl = m4__get_search_path (context)->list; incl != NULL; incl = incl->next) { - strncpy (name, incl->dir, incl->len); - name[incl->len] = '/'; - strcpy (name + incl->len + 1, file); + name = file_name_concat (incl->dir, file, NULL); #ifdef DEBUG_INCL fprintf (stderr, "path_search (%s) -- trying %s\n", file, name); @@ -183,26 +188,38 @@ m4_path_search (m4 *context, const char *expanded_name = name; else free (name); - errno = e; return fp; } + else if (!incl->len) + /* Capture errno only when searching `.'. */ + e = errno; + free (name); } - free (name); - errno = e; - return fp; + return NULL; +} + +void +m4__include_init (m4 *context) +{ + m4__search_path_info *info = m4__get_search_path (context); + + assert (info); + search_path_add (info, "", false); } + #ifdef DEBUG_INCL -static void +static void M4_GNUC_UNUSED include_dump (m4 *context) { m4__search_path *incl; fprintf (stderr, "include_dump:\n"); - for (incl = m4__get_search_path (context)->list; incl != NULL; incl = incl->next) + for (incl = m4__get_search_path (context)->list; + incl != NULL; incl = incl->next) fprintf (stderr, "\t%s\n", incl->dir); } Index: src/main.c =================================================================== RCS file: /sources/m4/m4/src/main.c,v retrieving revision 1.76 diff -u -p -r1.76 main.c --- src/main.c 23 Aug 2006 11:39:26 -0000 1.76 +++ src/main.c 23 Aug 2006 15:02:40 -0000 @@ -25,6 +25,8 @@ #include "version-etc.h" #include "gnu/progname.h" +#include <limits.h> + #define AUTHORS _("Rene' Seindal"), "Gary V. Vaughan" @@ -34,14 +36,8 @@ const char *frozen_file_to_read = NULL; /* Name of frozen file to produce near completion. */ const char *frozen_file_to_write = NULL; -/* If nonzero, display usage information and exit. */ -static int show_help = 0; - -/* If nonzero, print the version on standard output and exit. */ -static int show_version = 0; - /* If nonzero, import the environment as macros. */ -static int import_environment = 0; +static bool import_environment = false; typedef struct macro_definition { @@ -109,15 +105,16 @@ SPEC is any one of:\n\ printf (_("\ \n\ Dynamic loading features:\n\ - -M, --module-directory=DIRECTORY add DIRECTORY to the module search path\n\ - -m, --load-module=MODULE load dynamic MODULE from %s\n\ + -M, --module-directory=DIR add DIR to the module search path\n\ + -m, --load-module=MODULE load dynamic MODULE from %s\n\ "), USER_MODULE_PATH_ENV); fputs (_("\ \n\ Preprocessor features:\n\ --import-environment import all environment variables as macros\n\ + --prepend-include=DIR add DIR to include path before `.'\n\ -D, --define=NAME[=VALUE] define NAME has having VALUE, or empty\n\ - -I, --include=DIRECTORY append DIRECTORY to include path\n\ + -I, --include=DIR add DIR to include path after `.'\n\ -s, --synclines generate `#line NUM \"FILE\"' lines\n\ -U, --undefine=NAME undefine NAME\n\ "), stdout); @@ -158,6 +155,13 @@ FLAGS is any of:\n\ "), stdout); fputs (_("\ \n\ +If defined, the environment variable `M4PATH' is a colon-separated list\n\ +of directories included after any specified by `-I', and the variable\n\ +`M4MODPATH' is a colon-separated list of directories searched after any\n\ +specified by `-M'.\n\ +"), stdout); + fputs (_("\ +\n\ Exit status is 0 for success, 1 for failure, 63 for frozen file version\n\ mismatch, or whatever value was passed to the m4exit macro.\n\ "), stdout); @@ -166,6 +170,17 @@ mismatch, or whatever value was passed t exit (status); } +/* For long options that have no equivalent short option, use a + non-character as a pseudo short option, starting with CHAR_MAX + 1. */ +enum +{ + IMPORT_ENVIRONMENT_OPTION = CHAR_MAX + 1, + PREPEND_INCLUDE_OPTION, + + HELP_OPTION, + VERSION_OPTION +}; + /* Decode options and launch execution. */ static const struct option long_options[] = { @@ -192,17 +207,18 @@ static const struct option long_options[ {"traditional", no_argument, NULL, 'G'}, {"word-regexp", required_argument, NULL, 'W'}, - {"import-environment", no_argument, &import_environment, 1}, + {"import-environment", no_argument, NULL, IMPORT_ENVIRONMENT_OPTION}, + {"prepend-include", required_argument, NULL, PREPEND_INCLUDE_OPTION}, - {"help", no_argument, &show_help, 1}, - {"version", no_argument, &show_version, 1}, + {"help", no_argument, NULL, HELP_OPTION}, + {"version", no_argument, NULL, VERSION_OPTION}, /* These are somewhat troublesome. */ { "define", required_argument, NULL, 'D' }, { "undefine", required_argument, NULL, 'U' }, { "trace", required_argument, NULL, 't' }, - { 0, 0, 0, 0 }, + { NULL, 0, NULL, 0 }, }; #define OPTSTRING "B:D:EF:GH:I:L:M:N:PQR:S:T:U:bcd::el:m:o:r:st:" @@ -212,7 +228,7 @@ main (int argc, char *const *argv, char { macro_definition *head; /* head of deferred argument list */ macro_definition *tail; - macro_definition *new; + macro_definition *defn; int optchar; /* option character */ macro_definition *defines; @@ -251,22 +267,21 @@ main (int argc, char *const *argv, char head = tail = NULL; - while (optchar = getopt_long (argc, (char **) argv, OPTSTRING, - long_options, NULL), - optchar != EOF) + while ((optchar = getopt_long (argc, (char **) argv, OPTSTRING, + long_options, NULL)) != -1) switch (optchar) { default: usage (EXIT_FAILURE); - case 0: - break; - - case 'B': /* compatibility junk */ + case 'B': /* FIXME - should -B be a synonym of --prepend-include? */ case 'H': case 'N': case 'S': case 'T': + /* Compatibility junk: options that other implementations + support, but which we ignore as no-ops and don't list in + --help. */ break; case 'D': @@ -276,16 +291,16 @@ main (int argc, char *const *argv, char case 'r': /* Arguments that cannot be handled until later are accumulated. */ - new = xmalloc (sizeof *new); - new->code = optchar; - new->macro = optarg; - new->next = NULL; + defn = xmalloc (sizeof *defn); + defn->code = optchar; + defn->macro = optarg; + defn->next = NULL; if (head == NULL) - head = new; + head = defn; else - tail->next = new; - tail = new; + tail->next = defn; + tail = defn; break; @@ -303,12 +318,13 @@ main (int argc, char *const *argv, char break; case 'I': - m4_add_include_directory (context, optarg); + m4_add_include_directory (context, optarg, false); break; case 'L': m4_set_nesting_limit_opt (context, atoi (optarg)); break; + case 'M': if (lt_dlinsertsearchdir (lt_dlgetsearchpath(), optarg) != 0) { @@ -375,19 +391,27 @@ main (int argc, char *const *argv, char case 's': m4_set_sync_output_opt (context, true); break; - } - if (show_version) - { - version_etc (stdout, PACKAGE, PACKAGE_NAME TIMESTAMP, - VERSION, AUTHORS, NULL); - exit (EXIT_SUCCESS); - } + case IMPORT_ENVIRONMENT_OPTION: + import_environment = true; + break; - if (show_help) - usage (EXIT_SUCCESS); + case PREPEND_INCLUDE_OPTION: + m4_add_include_directory (context, optarg, true); + break; + + case VERSION_OPTION: + version_etc (stdout, PACKAGE, PACKAGE_NAME TIMESTAMP, + VERSION, AUTHORS, NULL); + exit (EXIT_SUCCESS); + break; + + case HELP_OPTION: + usage (EXIT_SUCCESS); + break; + } - /* Do the basic initialisations. */ + /* Do the basic initializations. */ m4_input_init (context); m4_output_init (); @@ -405,7 +429,7 @@ main (int argc, char *const *argv, char } /* Import environment variables as macros. The definition are - preprended to the macro definition list, so -U can override + prepended to the macro definition list, so -U can override environment variables. */ if (import_environment) @@ -414,16 +438,16 @@ main (int argc, char *const *argv, char for (env = envp; *env != NULL; env++) { - new = xmalloc (sizeof *new); - new->code = 'D'; - new->macro = *env; - new->next = head; - head = new; + defn = xmalloc (sizeof *defn); + defn->code = 'D'; + defn->macro = *env; + defn->next = head; + head = defn; } } /* Handle deferred command line macro definitions. Must come after - initialisation of the symbol table. */ + initialization of the symbol table. */ { defines = head;
_______________________________________________ Autoconf mailing list Autoconf@xxxxxxx http://lists.gnu.org/mailman/listinfo/autoconf