m4-discuss
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: RFC: m4 2.0 --prepend-include option


From: Eric Blake
Subject: Re: RFC: m4 2.0 --prepend-include option
Date: Fri, 25 Aug 2006 13:22:20 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.5) Gecko/20060719 Thunderbird/1.5.0.5 Mnenhy/0.7.4.666

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

According to Eric Blake on 8/23/2006 9:24 AM:
> 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've cleaned it up some, making -B an unconditional synonym for
- --prepend-include, per Paul's advice, with the caveat that -B1024 will
issue a warning that it is no longer compatible with other command line m4
implementations.  Perhaps I should tune it further to not even warn unless
./1024 is a directory?  I also added some tests to the testsuite.

I also added warnings for -T and -S, as well as for -N/--diversions (which
has been a no-op in 1.4.x), but I left -H/--hashsize as a silent
compatibility option for now (since it had an effect in 1.4.x, and might
make the transition from 1.4.x to 2.0 smoother).  Let me know if I should
change any of these decisions.

There are more things to do in regards to POSIXLY_CORRECT, so this thread
is by no means closed, but I am checking in the following:

2006-08-25  Eric Blake  <address@hidden>

        * tests/options.at (debug-flags): Update to reflect new message.
        (deprecated options, prepend-include, help and version): New
        tests.
        * tests/testsuite.at (AT_CHECK_M4): Avoid hanging testsuite if
        test omits an input file name.
        * src/main.c (long_options, main): Add -B/--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             address@hidden
-----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

iD8DBQFE703s84KuGfSFAYARAkQbAJ9qqflEcz2v7olFsZXY52PtLYGBGQCfRIbX
id3GH9fR8LKYNMB6QRIu/1Y=
=XW+Z
-----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.34
diff -u -p -r1.34 m4.texinfo
--- doc/m4.texinfo      25 Aug 2006 15:34:09 -0000      1.34
+++ doc/m4.texinfo      25 Aug 2006 19:00:14 -0000
@@ -497,8 +497,19 @@ Imports every variable in the environmen
 before @option{-D} and @option{-U}, so they can override the
 enviroment.
 
address@hidden FIXME - need to implement -B/--prepend=DIR, to prepend to the
address@hidden search path prior to `.'.
address@hidden -B @var{DIRECTORY}
address@hidden address@hidden
+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.  Some other
+implementations of @code{m4} use @code{-B @var{number}} to change their
+hard-coded limits, but that is unnecessary in @acronym{GNU} where the
+only limit is your hardware capability.  So although it is unlikely that
+you will want to include a relative directory whose name is purely
+numeric, @acronym{GNU} @code{m4} will warn you about this potential
+compatibility issue; you can avoid the warning by using the long
+spelling, or by using @samp{./@var{number}} if you really meant it.
+
 @item -D @address@hidden@address@hidden
 @itemx address@hidden@address@hidden@r{]}
 This enters @var{NAME} into the symbol table, before any input files are
@@ -586,13 +597,14 @@ problem in general, if not undecidable!
 @itemx address@hidden
 These options are present only for compatibility with previous
 versions of GNU @code{m4}.  They do nothing, because the symbol table
-size and number of diversions are not fixed anymore.
+size and number of diversions are not fixed anymore.  They will
+eventually disappear in future releases.
 
address@hidden -B @var{NUM}
 @itemx -S @var{NUM}
 @itemx -T @var{NUM}
 These options are present for compatibility with System V @code{m4}, but
-do nothing in this implementation.
+do nothing in this implementation.  They may disappear in future
+releases.
 @end table
 
 @acronym{GNU} @code{m4} comes with a feature of freezing internal state
@@ -2184,7 +2196,7 @@ Show the the current input line number i
 
 @item p
 Print a message when a named file is found through the path search
-mecanism (@pxref{Search Path}), giving the actual file name used.
+mechanism (@pxref{Search Path}), giving the actual file name used.
 
 @item i
 Print a message each time the current input file is changed, giving file
@@ -2941,12 +2953,14 @@ 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
address@hidden environment variable is set, it is expected to contain a
-colon-separated list of directories, which will be searched in order.
+If the @option{--prepend-include} or @option{-B} option was provided
+(@pxref{Invoking m4}), those directories are searched first, in reverse
+order that those options were listed on the command line.  Then
address@hidden looks in the current working directory.  Next comes the
+directories specified with the @option{--include} or @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     25 Aug 2006 19:00:14 -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     25 Aug 2006 19:00:14 -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       25 Aug 2006 19:00:14 -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      25 Aug 2006 19:00:14 -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   25 Aug 2006 19:00:14 -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  25 Aug 2006 19:00:14 -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\
+  -B, --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,14 +170,26 @@ 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
+{
+  DIVERSIONS_OPTION = CHAR_MAX + 1,    /* not quite -N, because of message */
+  IMPORT_ENVIRONMENT_OPTION,           /* no short opt */
+  PREPEND_INCLUDE_OPTION,              /* not quite -B, because of message */
+
+  HELP_OPTION,                         /* no short opt */
+  VERSION_OPTION                       /* no short opt */
+};
+
 /* Decode options and launch execution.  */
 static const struct option long_options[] =
 {
   {"arglength", required_argument, NULL, 'l'},
   {"batch", no_argument, NULL, 'b'},
   {"debug", optional_argument, NULL, 'd'},
+  {"define", required_argument, NULL, 'D'},
   {"discard-comments", no_argument, NULL, 'c'},
-  {"diversions", required_argument, NULL, 'N'},
   {"error-output", required_argument, NULL, 'o'},
   {"fatal-warnings", no_argument, NULL, 'E'},
   {"freeze-state", required_argument, NULL, 'F'},
@@ -189,20 +205,19 @@ static const struct option long_options[
   {"reload-state", required_argument, NULL, 'R'},
   {"silent", no_argument, NULL, 'Q'},
   {"synclines", no_argument, NULL, 's'},
+  {"trace", required_argument, NULL, 't'},
   {"traditional", no_argument, NULL, 'G'},
+  {"undefine", required_argument, NULL, 'U'},
   {"word-regexp", required_argument, NULL, 'W'},
 
-  {"import-environment", no_argument, &import_environment, 1},
-
-  {"help", no_argument, &show_help, 1},
-  {"version", no_argument, &show_version, 1},
+  {"diversions", required_argument, NULL, DIVERSIONS_OPTION},
+  {"import-environment", no_argument, NULL, IMPORT_ENVIRONMENT_OPTION},
+  {"prepend-include", required_argument, NULL, PREPEND_INCLUDE_OPTION},
 
-  /* These are somewhat troublesome.  */
-  { "define", required_argument, NULL, 'D' },
-  { "undefine", required_argument, NULL, 'U' },
-  { "trace", required_argument, NULL, 't' },
+  {"help", no_argument, NULL, HELP_OPTION},
+  {"version", no_argument, NULL, VERSION_OPTION},
 
-  { 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 +227,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 +266,33 @@ 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:
+      case 'H':
+       /* -H was supported in 1.4.x.  FIXME - make obsolete after
+            2.0, and remove after 2.1.  For now, keep it silent.  */
        break;
 
-      case 'B':                        /* compatibility junk */
-      case 'H':
       case 'N':
+      case DIVERSIONS_OPTION:
+       /* -N became an obsolete no-op in 1.4.x.  FIXME - remove
+            support for -N after 2.0.  */
+       error (0, 0, _("Warning: `m4 %s' is deprecated"),
+              optchar == 'N' ? "-N" : "--diversions");
+       break;
+
       case 'S':
       case 'T':
+       /* Compatibility junk: options that other implementations
+          support, but which we ignore as no-ops and don't list in
+          --help.  */
+       error (0, 0, _("Warning: `m4 -%c' may be removed in a future release"),
+              optchar);
        break;
 
       case 'D':
@@ -276,19 +302,37 @@ 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;
 
+      case 'B':
+       /* In 1.4.x, -B<num> was a no-op option for compatibility with
+          Solaris m4.  Warn if optarg is all numeric.  FIXME -
+          silence this warning after 2.0.  */
+       if (isdigit ((unsigned char) *optarg))
+         {
+           char *end;
+           errno = 0;
+           strtol (optarg, &end, 10);
+           if (*end == '\0' && errno == 0)
+             error (0, 0, _("Warning: recommend using `m4 -B ./%s' instead"),
+                    optarg);
+         }
+       /* fall through */
+      case PREPEND_INCLUDE_OPTION:
+       m4_add_include_directory (context, optarg, true);
+       break;
+
       case 'E':
        m4_set_fatal_warnings_opt (context, true);
        break;
@@ -303,12 +347,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 +420,23 @@ 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 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 +454,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 +463,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;
 
Index: tests/options.at
===================================================================
RCS file: /sources/m4/m4/tests/options.at,v
retrieving revision 1.4
diff -u -p -r1.4 options.at
--- tests/options.at    23 Aug 2006 11:39:26 -0000      1.4
+++ tests/options.at    25 Aug 2006 19:00:14 -0000
@@ -35,7 +35,7 @@ comment
  --> ends.
 ]])
 
-AT_CHECK_M4([-c in], 0,
+AT_CHECK_M4([-c in], [0],
 [[This is not a comment This should not disappear.
 
 html  ends.
@@ -66,8 +66,8 @@ export ZAPPED
 OVERRIDE='This is an environment variable which we will change'
 export OVERRIDE
 
-AT_CHECK_M4([--import-environment -UZAPPED -DOVERRIDE='It is changed.' in], 0,
-[[TEST=This is an environment variable
+AT_CHECK_M4([--import-environment -UZAPPED -DOVERRIDE='It is changed.' in],
+[0], [[TEST=This is an environment variable
 ZAPPED=ZAPPED
 OVERRIDE=It is changed.
 ]])
@@ -87,15 +87,16 @@ len(`abc')
 ]])
 
 dnl AT_CHECK_M4 starts life with -d.  Make sure it looks like -daeq.
-AT_CHECK_M4([-tlen in], 0, [[0
+AT_CHECK_M4([-tlen in], [0], [[0
 3
 ]], [[m4trace: -1- len(`abc') -> `3'
 ]])
 
 dnl Test all flags.
-AT_CHECK_M4([-dV in], 0, [[0
+AT_CHECK_M4([-dV in], [0], [[0
 3
-]], [[m4debug: input read from in
+]], [[m4debug: path search for `in' found `in'
+m4debug: input read from in
 m4trace:in:1: -1- id 1: divnum ...
 m4trace:in:1: -1- id 1: divnum -> ???
 m4trace:in:1: -1- id 1: divnum -> `0'
@@ -106,10 +107,114 @@ m4debug:in:3: input exhausted
 ]])
 
 dnl Test addition and subtraction of flags.
-AT_CHECK_M4([-d-e -d+xt in], 0, [[0
+AT_CHECK_M4([-d-e -d+xt in], [0], [[0
 3
 ]], [[m4trace: -1- id 1: divnum
 m4trace: -1- id 2: len(`abc')
 ]])
 
 AT_CLEANUP
+
+
+## ---------------- ##
+## obsolete options ##
+## ---------------- ##
+
+AT_SETUP([deprecated options])
+
+dnl -N/--diversions are no-ops since 1.4.x
+AT_CHECK_M4([-N1 --diversions=1], [0], [],
+[[m4: Warning: `m4 -N' is deprecated
+m4: Warning: `m4 --diversions' is deprecated
+]])
+
+dnl -H/--hashsize are no-ops since 2.0, and still silent for now...
+AT_CHECK_M4([-H1 --hashsize=1])
+
+dnl -S/-T are no-ops for compatibility
+AT_CHECK_M4([-S1 -T1], [0], [],
+[[m4: Warning: `m4 -S' may be removed in a future release
+m4: Warning: `m4 -T' may be removed in a future release
+]])
+
+dnl -Bint can be confused with its no-op meaning in 1.4.x, but all other
+dnl uses of -B or its long option are okay
+AT_CHECK_M4([-B1 -B./1 --prepend-include=1], [0], [],
+[[m4: Warning: recommend using `m4 -B ./1' instead
+]])
+
+AT_CLEANUP
+
+
+## --------------- ##
+## prepend-include ##
+## --------------- ##
+
+AT_SETUP([prepend-include])
+
+dnl Lots of data to set up.
+AT_DATA([[in]],
+[[include(`foo')dnl
+include(`bar')dnl
+include(`bad')dnl
+include(`blah')dnl
+]])
+
+AT_CHECK([mkdir pre post])
+
+AT_DATA([[pre/foo]], [[in pre/foo
+]])
+AT_DATA([[foo]], [[in ./foo
+]])
+AT_DATA([[bar]], [[in ./bar
+]])
+AT_DATA([[post/bar]], [[in post/bar
+]])
+AT_DATA([[post/blah]], [[in post/blah
+]])
+
+dnl Make circular links in the subdirectories, to ensure that the error
+dnl message when bad cannot be opened comes from the search in ., regardless
+dnl of what else was searched.
+AT_CHECK([ln -s bad pre/bad])
+AT_CHECK([ln -s bad post/bad])
+
+dnl Finally, see that it all works.
+AT_CHECK_M4([-I post -B pre in], [1],
+[[in pre/foo
+in ./bar
+in post/blah
+]], [[m4:in:3: include: cannot open `bad': No such file or directory
+]])
+
+AT_CLEANUP
+
+
+## ---------------- ##
+## help and version ##
+## ---------------- ##
+
+AT_SETUP([help and version])
+
+AT_CHECK_M4([--help], [0], [stdout])
+AT_CHECK([[sed -n -e 's|Usage:.*\[OPTION\]... \[FILE\]...|success|p' stdout]],
+[0], [success
+])
+
+AT_CHECK_M4([--version], [0], [stdout])
+AT_CHECK([[sed -n -e 's|There is NO WARRANTY.*|success|p' stdout]],
+[0], [success
+])
+
+dnl make sure option specified first takes precedence
+AT_CHECK_M4([--help --version], [0], [stdout])
+AT_CHECK([[sed -n -e 's|Usage:.*\[OPTION\]... \[FILE\]...|success|p' stdout]],
+[0], [success
+])
+
+AT_CHECK_M4([--version --help], [0], [stdout])
+AT_CHECK([[sed -n -e 's|There is NO WARRANTY.*|success|p' stdout]],
+[0], [success
+])
+
+AT_CLEANUP
Index: tests/testsuite.at
===================================================================
RCS file: /sources/m4/m4/tests/testsuite.at,v
retrieving revision 1.19
diff -u -p -r1.19 testsuite.at
--- tests/testsuite.at  22 Aug 2006 16:16:48 -0000      1.19
+++ tests/testsuite.at  25 Aug 2006 19:00:14 -0000
@@ -23,8 +23,10 @@ m4_version_prereq([2.52e])
 
 # AT_CHECK_M4(ARGS, [EXIT-STATUS = 0], [STDOUT = `'], [STDERR = `'])
 # ------------------------------------------------------------------
+# Run m4 with ARGS, and stdin redirected from /dev/null.  Expect EXIT-STATUS,
+# with output matching STDOUT and STDERR as in AT_CHECK.
 m4_define([AT_CHECK_M4],
-[AT_CHECK([m4 -b -d $1], [$2], [$3], [$4])
+[AT_CHECK([m4 -b -d $1 < /dev/null], [$2], [$3], [$4])
 ])
 
 # AT_TEST_M4(TITLE, INPUT, [STDOUT = `'], [STDERR = `'])

reply via email to

[Prev in Thread] Current Thread [Next in Thread]