m4-patches
[Top][All Lists]
Advanced

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

frozen files format V2


From: Eric Blake
Subject: frozen files format V2
Date: Sat, 20 Jan 2007 21:08:35 -0700
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.9) Gecko/20061207 Thunderbird/1.5.0.9 Mnenhy/0.7.4.666

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

I did some sweeping improvements on src/freeze.c.  It has bugged me that
we claimed that frozen files were editable, but that a user macro with
8-bit or control characters didn't escape those characters except for the
changesyntax S directive, causing problems in some editors.  So I fixed it
- - all strings that can come from arbitrary sources are now fully
escape-encoded in version 2 format files.  It also bugged me that we were
dumping 256 syntax S directives, even when using the default syntax; so
the dump now only produces output for non-default setup.  This fix is also
one step closer to allowing NUL to be handled transparently, since
changesyntax settings for NUL could now be represented (I have that as a
goal for 2.0, although it is a huge, multi-step task to reach it).  It is
also one step closer to adding new changesyntax categories of { and } (for
implementing ${11}).

The documentation still needs an overhaul (including merging the frozen
files section with the improvements on the branch), and I have some
testsuite improvements to add, but this patch was getting big enough that
I wanted to checkpoint things.

NOTE: This is an incompatible change for reloading any frozen files
created with m4 1.4q that used \ in macro names or values.  Fortunately,
1.4o only used version 1 frozen files and was the last widely released m4
version; to my knowledge, 1.4q was never released on any gnu.org sites.  I
don't think many users will be impacted, and the difference between 1.4q
and 1.9a (or 2.0) is reasonable, and early adopters of 1.4q should know
they were using a beta version subject to change.

2007-01-20  Eric Blake  <address@hidden>

        * src/freeze.c (produce_char_dump): Delete.  Replace with...
        (produce_mem_dump): ...this new function, to encode more strings.
        Also make the coding easier to read and slightly more compact.
        (produce_syntax_dump): Only dump non-default syntax codes.
        (produce_module_dump, dump_symbol_CB, produce_frozen_state):
        Encode non-ASCII characters in user-supplied strings.
        (GET_STRING): Accept escape sequences in version 2.
        * NEWS: Document this change.
        * TODO: Update.

- --
Don't work too hard, make some time for fun as well!

Eric Blake             address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFFsudC84KuGfSFAYARAlmyAKCM3tEB7DPaBlw+3RF5bjT48IA4PQCeJ35f
mI63DIPk5fiGWRwDMzXsfoo=
=3ycf
-----END PGP SIGNATURE-----
Index: NEWS
===================================================================
RCS file: /sources/m4/m4/NEWS,v
retrieving revision 1.36
diff -u -p -r1.36 NEWS
--- NEWS        15 Jan 2007 14:04:26 -0000      1.36
+++ NEWS        21 Jan 2007 03:51:24 -0000
@@ -192,10 +192,14 @@ promoted to 2.0.
 ** Other changes
 
 *** The syntax of frozen files format V2 has been improved to save
-    additional state.
-  - FIXME: format 2 still needs to be tweaked to allow complete ASCII
-  representation and to catch any more missing state; once 2.0 is released,
-  any further changes would introduce format 3.
+    additional state.  This includes the 'R' directive for default regular
+    expression syntax.  Also, a V2 file can now be represented completely
+    in ASCII, thanks to escape sequences.  Unfortunately, files frozen by
+    M4 1.4q that contain \ in macros cannot be read by 1.9b, but since 1.4q
+    was not widely distributed, this is not expected to be much of an
+    issue, and comes with the territory of using a beta release.
+  - FIXME: format 2 still needs to catch more missing state; once 2.0 is
+    released, any further changes would introduce format 3.
 
 FIXME: include the (long) list of changes in 1.4.x that were not already
   in earlier betas.
Index: TODO
===================================================================
RCS file: /sources/m4/m4/TODO,v
retrieving revision 1.20
diff -u -p -r1.20 TODO
--- TODO        5 Sep 2006 13:25:24 -0000       1.20
+++ TODO        21 Jan 2007 03:51:24 -0000
@@ -1,5 +1,5 @@
 GNU m4 TODO - Tasks that need implementing.            -*- outline -*-
-Copyright (C) 2000, 2001, 2006 Free Software Foundation, Inc.
+Copyright (C) 2000, 2001, 2006, 2007 Free Software Foundation, Inc.
 
 Tell the maintainers at <address@hidden> if you feel like volunteering
 for any of these ideas or if you have others to add.
@@ -66,10 +66,6 @@ for any of these ideas or if you have ot
   + Make m4 show include dependencies like gcc so Makefile targets are
     updated when their (included) input files are updated (Erick B).
 
-  + Sort out all the weird forms of interaction between changesyntax,
-    changecom and changequote.  What happens if you install a quote with
-    changequote and removes it with changesyntax and vice versa.
-
   + Add support for wide character sets.
 
 
Index: src/freeze.c
===================================================================
RCS file: /sources/m4/m4/src/freeze.c,v
retrieving revision 1.58
diff -u -p -r1.58 freeze.c
--- src/freeze.c        13 Jan 2007 13:55:37 -0000      1.58
+++ src/freeze.c        21 Jan 2007 03:51:24 -0000
@@ -23,57 +23,52 @@
 #include "m4/system.h"
 #include "m4.h"
 #include "m4private.h"
+#include "binary-io.h"
 
-static int   decode_char           (FILE *);
-static void  issue_expect_message  (m4 *, int);
-static int   produce_char_dump     (char *, int);
-static void  produce_resyntax_dump (m4 *, FILE *);
-static void  produce_syntax_dump   (FILE *, m4_syntax_table *, char);
-static void  produce_module_dump   (FILE *, lt_dlhandle);
-static void  produce_symbol_dump   (m4 *, FILE *, m4_symbol_table *);
-static void *dump_symbol_CB        (m4_symbol_table *, const char *,
-                                    m4_symbol *, void *);
+static void  produce_mem_dump          (FILE *, const char *, size_t);
+static void  produce_resyntax_dump     (m4 *, FILE *);
+static void  produce_syntax_dump       (FILE *, m4_syntax_table *, char);
+static void  produce_module_dump       (FILE *, lt_dlhandle);
+static void  produce_symbol_dump       (m4 *, FILE *, m4_symbol_table *);
+static void *dump_symbol_CB            (m4_symbol_table *, const char *,
+                                        m4_symbol *, void *);
+static void  issue_expect_message      (m4 *, int);
+static int   decode_char               (FILE *);
 
 
-/* Produce a frozen state to the given file NAME. */
-
-static int
-produce_char_dump (char *buf, int ch)
+/* Dump an ASCII-encoded representation of LEN bytes at MEM to FILE.
+   MEM may contain embedded NUL characters.  */
+static void
+produce_mem_dump (FILE *file, const char *mem, size_t len)
 {
-  char *p = buf;
-  int digit;
-
-  if (ch > 127 || ch < 32)
-    {
-      *p++  = '\\';
-
-      digit = ch / 64;
-      ch    = ch - (64 * digit);
-      *p++  = digit + '0';
-
-      digit = ch / 8;
-      ch    = ch - (8 * digit);
-      *p++  = digit + '0';
-
-      *p++  = ch + '0';
-    }
-  else
+  while (len--)
     {
+      int ch = to_uchar (*mem++);
       switch (ch)
        {
-       case '\\':
-         *p++ = '\\';
-         *p++ = '\\';
-         break;
-
+       case '\a': putc ('\\', file); putc ('a', file); break;
+       case '\b': putc ('\\', file); putc ('b', file); break;
+       case '\f': putc ('\\', file); putc ('f', file); break;
+       case '\n': putc ('\\', file); putc ('n', file); break;
+       case '\r': putc ('\\', file); putc ('r', file); break;
+       case '\t': putc ('\\', file); putc ('t', file); break;
+       case '\v': putc ('\\', file); putc ('v', file); break;
+       case '\\': putc ('\\', file); putc ('\\', file); break;
        default:
-         *p++ = ch;
+         if (ch >= 0x7f || ch < 0x20)
+           {
+             int digit = ch / 16;
+             ch %= 16;
+             digit += digit > 9 ? 'a' - 10 : '0';
+             ch += ch > 9 ? 'a' - 10 : '0';
+             putc ('\\', file);
+             putc ('x', file);
+             putc (digit, file);
+           }
+         putc (ch, file);
          break;
        }
     }
-  *p = '\0';
-
-  return strlen (buf);
 }
 
 
@@ -87,7 +82,7 @@ produce_char_dump (char *buf, int ch)
 static void
 produce_resyntax_dump (m4 *context, FILE *file)
 {
-  int code  = m4_get_regexp_syntax_opt (context);
+  int code = m4_get_regexp_syntax_opt (context);
 
   /* Don't dump default syntax code (`0' for GNU_EMACS).  */
   if (code)
@@ -98,59 +93,67 @@ produce_resyntax_dump (m4 *context, FILE
        m4_error (context, EXIT_FAILURE, 0,
                  _("invalid regexp syntax code `%d'"), code);
 
+      /* No need to use produce_mem_dump, since we know all resyntax
+        names are already ASCII-encoded.  */
       fprintf (file, "R%d\n%s\n", strlen (resyntax), resyntax);
     }
 }
 
-#define MAX_CHAR_LENGTH 4      /* '\377' -> 4 characters */
-
 static void
 produce_syntax_dump (FILE *file, m4_syntax_table *syntax, char ch)
 {
-  char buf[1+ MAX_CHAR_LENGTH * sizeof (m4_syntax_table)];
+  char buf[256];
   int code = m4_syntax_code (ch);
   int count = 0;
-  int offset = 0;
   int i;
 
-  /* FIXME:  Can't set the syntax of '\000' since that character marks
-            the end of a string, and when passed to `m4_set_syntax', tells
-            it to set the syntax of every table entry. */
+  for (i = 0; i < 256; ++i)
+    if (m4_has_syntax (syntax, i, code) && code != syntax->orig[i])
+      buf[count++] = i;
+
+  /* If code falls in M4_SYNTAX_MASKS, then we must treat it
+     specially, since it will not be found in syntax->orig.  */
+  if (count == 1
+      && ((code == M4_SYNTAX_RQUOTE && *buf == *DEF_RQUOTE)
+         || (code == M4_SYNTAX_ECOMM && *buf == *DEF_ECOMM)))
+    return;
 
-  for (i = 1; i < 256; ++i)
+  if (count || (code & M4_SYNTAX_MASKS))
     {
-      if (m4_has_syntax (syntax, i, code))
-       {
-         offset += produce_char_dump (buf + offset, i);
-         ++count;
-       }
+      fprintf (file, "S%c%d\n", ch, count);
+      produce_mem_dump (file, buf, count);
+      fputc ('\n', file);
     }
-
-  if (offset)
-      fprintf (file, "S%c%d\n%s\n", ch, count, buf);
 }
 
 /* The modules must be dumped in the order in which they will be
    reloaded from the frozen file.  libltdl stores handles in a push
    down stack, so we need to dump them in the reverse order to that.  */
-void
+static void
 produce_module_dump (FILE *file, lt_dlhandle handle)
 {
   const char *name = m4_get_module_name (handle);
+  size_t len = strlen (name);
 
   handle = m4__module_next (handle);
   if (handle)
     produce_module_dump (file, handle);
 
-  fprintf (file, "M%lu\n", (unsigned long int) strlen (name));
-  fputs (name, file);
+  /* GNU assumption: Although POSIX allows size_t to be just 16 bits,
+     independently of int, GNU assumes is at least as big as int.
+     Likewise, although POSIX allows size_t to be bigger than unsigned
+     long in some compilation environments, GNU assumes that size_t
+     always fits in unsigned long.  Unfortunately, GNU does not assume
+     that %zu is portable, yet.  */
+  fprintf (file, "M%lu\n", (unsigned long int) len);
+  produce_mem_dump (file, name, len);
   fputc ('\n', file);
 }
 
 /* Process all entries in one bucket, from the last to the first.
    This order ensures that, at reload time, pushdef's will be
    executed with the oldest definitions first.  */
-void
+static void
 produce_symbol_dump (m4 *context, FILE *file, m4_symbol_table *symtab)
 {
   if (m4_symtab_apply (symtab, dump_symbol_CB, file))
@@ -164,43 +167,43 @@ dump_symbol_CB (m4_symbol_table *symtab,
   lt_dlhandle   handle         = SYMBOL_HANDLE (symbol);
   const char   *module_name    = handle ? m4_get_module_name (handle) : NULL;
   FILE *       file            = (FILE *) userdata;
+  size_t       symbol_len      = strlen (symbol_name);
+  size_t       module_len      = module_name ? strlen (module_name) : 0;
 
   if (m4_is_symbol_text (symbol))
     {
-      fprintf (file, "T%lu,%lu",
-              (unsigned long int) strlen (symbol_name),
-              (unsigned long int) strlen (m4_get_symbol_text (symbol)));
+      const char *text = m4_get_symbol_text (symbol);
+      size_t text_len = strlen (text);
+      fprintf (file, "T%lu,%lu", (unsigned long int) symbol_len,
+              (unsigned long int) text_len);
       if (handle)
-       fprintf (file, ",%lu", (unsigned long int) strlen (module_name));
+       fprintf (file, ",%lu", (unsigned long int) module_len);
       fputc ('\n', file);
 
-      fputs (symbol_name, file);
-      fputs (m4_get_symbol_text (symbol), file);
+      produce_mem_dump (file, symbol_name, symbol_len);
+      produce_mem_dump (file, text, text_len);
       if (handle)
-       fputs (module_name, file);
+       produce_mem_dump (file, module_name, module_len);
       fputc ('\n', file);
     }
   else if (m4_is_symbol_func (symbol))
     {
-      const m4_builtin *bp = m4_builtin_find_by_func (SYMBOL_HANDLE (symbol),
-                                               m4_get_symbol_func (symbol));
-
+      const m4_builtin *bp = m4_get_symbol_builtin (symbol);
+      size_t bp_len;
       if (bp == NULL)
        assert (!"INTERNAL ERROR: builtin not found in builtin table!");
+      bp_len = strlen (bp->name);
 
-      fprintf (file, "F%lu,%lu",
-              (unsigned long int) strlen (symbol_name),
-              (unsigned long int) strlen (bp->name));
-
+      fprintf (file, "F%lu,%lu", (unsigned long int) symbol_len,
+              (unsigned long int) bp_len);
       if (handle)
-       fprintf (file, ",%lu",
-                (unsigned long int) strlen (module_name));
+       fprintf (file, ",%lu", (unsigned long int) module_len);
       fputc ('\n', file);
 
-      fputs (symbol_name, file);
-      fputs (bp->name, file);
+      produce_mem_dump (file, symbol_name, symbol_len);
+      produce_mem_dump (file, bp->name, bp_len);
       if (handle)
-       fputs (module_name, file);
+       produce_mem_dump (file, module_name, module_len);
       fputc ('\n', file);
     }
   else if (m4_is_symbol_placeholder (symbol))
@@ -211,18 +214,13 @@ dump_symbol_CB (m4_symbol_table *symtab,
   return NULL;
 }
 
+/* Produce a frozen state to the given file NAME. */
 void
 produce_frozen_state (m4 *context, const char *name)
 {
-  FILE *file;
-
-#ifdef WIN32
-# define FROZEN_WRITE "wb"
-#else
-# define FROZEN_WRITE "w"
-#endif
+  FILE *file = fopen (name, O_BINARY ? "wb" : "w");
+  const char *str;
 
-  file = fopen (name, FROZEN_WRITE);
   if (!file)
     {
       m4_error (context, 0, errno, _("cannot open `%s'"), name);
@@ -243,8 +241,10 @@ produce_frozen_state (m4 *context, const
       fprintf (file, "Q%lu,%lu\n",
               (unsigned long int) context->syntax->lquote.length,
               (unsigned long int) context->syntax->rquote.length);
-      fputs (context->syntax->lquote.string, file);
-      fputs (context->syntax->rquote.string, file);
+      produce_mem_dump (file, context->syntax->lquote.string,
+                       context->syntax->lquote.length);
+      produce_mem_dump (file, context->syntax->rquote.string,
+                       context->syntax->rquote.length);
       fputc ('\n', file);
     }
 
@@ -256,8 +256,10 @@ produce_frozen_state (m4 *context, const
       fprintf (file, "C%lu,%lu\n",
               (unsigned long int) context->syntax->bcomm.length,
               (unsigned long int) context->syntax->ecomm.length);
-      fputs (context->syntax->bcomm.string, file);
-      fputs (context->syntax->ecomm.string, file);
+      produce_mem_dump (file, context->syntax->bcomm.string,
+                       context->syntax->bcomm.length);
+      produce_mem_dump (file, context->syntax->ecomm.string,
+                       context->syntax->ecomm.length);
       fputc ('\n', file);
     }
 
@@ -267,23 +269,9 @@ produce_frozen_state (m4 *context, const
 
   /* Dump syntax table. */
 
-  produce_syntax_dump (file, M4SYNTAX, 'I');
-  produce_syntax_dump (file, M4SYNTAX, 'S');
-  produce_syntax_dump (file, M4SYNTAX, '(');
-  produce_syntax_dump (file, M4SYNTAX, ')');
-  produce_syntax_dump (file, M4SYNTAX, ',');
-  produce_syntax_dump (file, M4SYNTAX, '$');
-  produce_syntax_dump (file, M4SYNTAX, 'A');
-  produce_syntax_dump (file, M4SYNTAX, '@');
-  produce_syntax_dump (file, M4SYNTAX, 'O');
-
-  produce_syntax_dump (file, M4SYNTAX, 'W');
-  produce_syntax_dump (file, M4SYNTAX, 'D');
-
-  produce_syntax_dump (file, M4SYNTAX, 'L');
-  produce_syntax_dump (file, M4SYNTAX, 'R');
-  produce_syntax_dump (file, M4SYNTAX, 'B');
-  produce_syntax_dump (file, M4SYNTAX, 'E');
+  str = "IS(),address@hidden";
+  while (*str)
+    produce_syntax_dump (file, M4SYNTAX, *str++);
 
   /* Dump all loaded modules.  */
   produce_module_dump (file, m4__module_next (0));
@@ -313,40 +301,78 @@ issue_expect_message (m4 *context, int e
              _("expecting character `%c' in frozen file"), expected);
 }
 
-/* Reload a frozen state from the given file NAME. */
+
+/* Reload frozen state.  */
 
-/* Read the next character from the IN stream.  Octal characters of the
-   form ``\nnn'' are converted, and returned.  EOF is returned if the end
-   of file is reached whilst reading the character.  */
+/* Read the next character from the IN stream.  Various escape
+   sequences are converted, and returned.  EOF is returned if the end
+   of file is reached whilst reading the character, or on an
+   unrecognized escape sequence.  */
 
 static int
 decode_char (FILE *in)
 {
-  int ch = fgetc (in);
+  int ch = getc (in);
+  int next;
+  int value = 0;
 
   if (ch == '\\')
     {
-      ch = fgetc (in);
-      if ((ch != EOF) && (ch != '\\'))
+      ch = getc (in);
+      switch (ch)
        {
-         int next;
-
-         /* first octal digit */
-         ch = (ch - '0') * 64;
-
-         /* second octal digit */
-         next = fgetc (in);
-         if (next == EOF)
-           ch = EOF;
+       case 'a': return '\a';
+       case 'b': return '\b';
+       case 'f': return '\f';
+       case 'n': return '\n';
+       case 'r': return '\r';
+       case 't': return '\t';
+       case 'v': return '\v';
+       case '\\': return '\\';
+
+       case 'x': case 'X':
+         next = getc (in);
+         if (next >= '0' && next <= '9')
+           ch = (next - '0') * 16;
+         else if (next >= 'a' && next <= 'f')
+           ch = (next - 'a' + 10) * 16;
+         else if (next >= 'A' && next <= 'F')
+           ch = (next - 'A' + 10) * 16;
          else
-           ch += 8 * (next - '0');
-
-         /* third octal digit */
-         next = fgetc (in);
-         if (next == EOF)
-           ch = EOF;
+           return EOF;
+         next = getc (in);
+         if (next >= '0' && next <= '9')
+           ch += next - '0';
+         else if (next >= 'a' && next <= 'f')
+           ch += next - 'a' + 10;
+         else if (next >= 'A' && next <= 'F')
+           ch += next - 'A' + 10;
+         else
+           return EOF;
+         return ch;
+       case '0': case '1': case '2': case '3':
+         value = ch - '0';
+         ch = getc (in);
+         /* fall through */
+       case '4': case '5': case '6': case '7':
+         if (ch >= '0' && ch <= '7')
+           {
+             value = value * 8 + ch - '0';
+             ch = getc (in);
+           }
          else
-           ch += (next - '0');
+           {
+             ungetc (ch, in);
+             return value;
+           }
+         if (ch >= '0' && ch <= '7')
+           value = value * 8 + ch - '0';
+         else
+           ungetc (ch, in);
+         return value;
+
+       default:
+         return EOF;
        }
     }
 
@@ -354,7 +380,8 @@ decode_char (FILE *in)
 }
 
 
-/* We are seeking speed, here.  */
+/*  Reload state from the given file NAME.  We are seeking speed,
+    here.  */
 
 void
 reload_frozen_state (m4 *context, const char *name)
@@ -365,7 +392,7 @@ reload_frozen_state (m4 *context, const 
   int operation;
   char syntax;
   char *string[3];
-  int allocated[3];
+  size_t allocated[3];
   int number[3] = {0};
 
 #define GET_CHARACTER                                          \
@@ -386,12 +413,19 @@ reload_frozen_state (m4 *context, const 
 #define GET_STRING(File, Buf, BufSize, StrLen)                 \
   do                                                           \
     {                                                          \
-      CHECK_ALLOCATION ((Buf), (BufSize), (StrLen));           \
-      if ((StrLen) > 0)                                                \
-       if (!fread ((Buf), (size_t) (StrLen), 1, (File)))       \
-         m4_error (context, EXIT_FAILURE, 0,                   \
-                   _("premature end of frozen file"));         \
-      (Buf)[(StrLen)] = '\0';                                  \
+      size_t len = (StrLen);                                   \
+      char *p = (Buf);                                         \
+      CHECK_ALLOCATION (p, (BufSize), len);                    \
+      while (len-- > 0)                                                \
+       {                                                       \
+         int ch = (version > 1 ? decode_char (File)            \
+                   : getc (File));                             \
+         if (ch == EOF)                                        \
+           m4_error (context, EXIT_FAILURE, 0,                 \
+                     _("premature end of frozen file"));       \
+         *p++ = ch;                                            \
+       }                                                       \
+      *p = '\0';                                               \
     }                                                          \
   while (0)
 
@@ -410,7 +444,7 @@ reload_frozen_state (m4 *context, const 
        {                                                       \
          free (Where);                                         \
          (Allocated) = (Needed) + 1;                           \
-         (Where) = xmalloc ((size_t) (Allocated));             \
+         (Where) = xmalloc (Allocated);                        \
        }                                                       \
     }                                                          \
   while (0)
@@ -436,11 +470,11 @@ reload_frozen_state (m4 *context, const 
     m4_error (context, EXIT_FAILURE, errno, _("cannot open `%s'"), name);
 
   allocated[0] = 100;
-  string[0] = xmalloc ((size_t) allocated[0]);
+  string[0] = xmalloc (allocated[0]);
   allocated[1] = 100;
-  string[1] = xmalloc ((size_t) allocated[1]);
+  string[1] = xmalloc (allocated[1]);
   allocated[2] = 100;
-  string[2] = xmalloc ((size_t) allocated[2]);
+  string[2] = xmalloc (allocated[2]);
 
   /* Validate format version.  Accept both `1' (m4 1.3 and 1.4.x) and
      `2' (m4 2.0).  */
@@ -451,22 +485,13 @@ reload_frozen_state (m4 *context, const 
   switch (version)
     {
     case 2:
-      {
-       int ch;
-
-       /* Take care not to mix frozen state with startup state.  */
-       for (ch = 256; --ch > 0;)
-         context->syntax->table[ch] = 0;
-      }
       break;
     case 1:
-      {
-       m4__module_open (context, "m4", NULL);
-       if (m4_get_posixly_correct_opt (context))
-         m4__module_open (context, "traditional", NULL);
-       else
-         m4__module_open (context, "gnu", NULL);
-      }
+      m4__module_open (context, "m4", NULL);
+      if (m4_get_posixly_correct_opt (context))
+       m4__module_open (context, "traditional", NULL);
+      else
+       m4__module_open (context, "gnu", NULL);
       break;
     default:
       if (version > 2)
@@ -613,26 +638,13 @@ ill-formed frozen file, version 2 direct
          GET_CHARACTER;
          GET_NUMBER (number[0]);
          VALIDATE ('\n');
+         GET_STRING (file, string[0], allocated[0], number[0]);
 
-         CHECK_ALLOCATION (string[0], allocated[0], number[0]);
-         if (number[0] > 0)
-           {
-             int i;
-
-             for (i = 0; i < number[0]; ++i)
-               {
-                 int ch = decode_char (file);
-
-                 if (ch < 0)
-                   m4_error (context, EXIT_FAILURE, 0,
-                             _("premature end of frozen file"));
-
-                 string[0][i] = ch;
-               }
-           }
-         string[0][number[0]] = '\0';
-
-         if ((m4_set_syntax (context->syntax, syntax, '=', string[0]) < 0)
+         /* Syntax under M4_SYNTAX_MASKS is handled specially; all
+            other characters are additive.  */
+         if ((m4_set_syntax (context->syntax, syntax,
+                             (m4_syntax_code (syntax) & M4_SYNTAX_MASKS
+                              ? '=' : '+'), string[0]) < 0)
              && (syntax != '\0'))
            {
              m4_error (context, 0, 0,

reply via email to

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