bug-m4
[Top][All Lists]
Advanced

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

Syncoutput patch for m4-1.4ppre2


From: Andrew Bettison
Subject: Syncoutput patch for m4-1.4ppre2
Date: Thu, 27 Sep 2001 11:35:04 +1000

René,

Here is a patch that rolls together a bunch of fixes and enhancements I
submitted to m4-1.4n way back in 1998.  These never made it into m4-1.4o,
presumably because I was pretty sloppy -- no ChangeLog entry, no updates to the
texinfo documentation, and a pile of little patches instead of one big one.

This time I hope I've done it a bit better.

This patch fixes some problems with syncoutput on/off -- basically lines were
not being counted correctly.  I also added a little extra functionality to the
'syncoutput' builtin so it can be used to query the current state of sync
output.  Here's the ChangeLog entry (also included in the patch):

2001-09-27  Andrew Bettison  <address@hidden>

        * src/builtin.c (builtin_tab): "syncoutput" now expands if no
        parentheses ('blind' column now FALSE instead of TRUE).
        (m4_syncoutput): only accept arg1 values as documented, expand to 0 or
        1 if invoked without args.

        * src/m4.h: Added extern output_filename_synced, declared in output.c
        and used in input.c.

        * src/input.c: Fix bug where filename not emitted in first '#line';
        use flag output_filename_synced instead of placing value of -1 in
        output_current_line.

        * src/output.c (COUNT_LINES): Added.
        (count_lines): Added.
        (shipout_text): Modified line-counting logic to cope correctly with
        sync output being enabled and disabled willy-nilly.
        (output_text): Miniscule optimization.

        * doc/m4.texinfo (Syncoutput): Document no-parentheses case.

        * examples/Makefile.am (pkgdata_DATA): Added syncoutput.m4.

        * examples/Makefile.am (TESTS): Added syncoutput.test.

        * examples/syncoutput.m4: New file.

        * examples/syncoutput.test: New file.

Regards,
Andrew Bettison
diff -u -r -N --exclude config* --exclude aclocal.m4 --exclude Makefile.in 
--exclude Makefile --exclude intl --exclude po --exclude *~ --exclude tags 
--exclude testSubDir --exclude stamp-vti --exclude version.texi --exclude 
*.orig --exclude *.rej --exclude .indent.pro --exclude .deps --exclude *.o 
--exclude *.info* --exclude *.a m4-1.4ppre2.orig/ChangeLog m4-1.4ppre2/ChangeLog
--- m4-1.4ppre2.orig/ChangeLog  Mon Jan 17 03:18:38 2000
+++ m4-1.4ppre2/ChangeLog       Thu Sep 27 11:25:22 2001
@@ -1,3 +1,33 @@
+2001-09-27  Andrew Bettison  <address@hidden>
+
+       * src/builtin.c (builtin_tab): "syncoutput" now expands if no
+       parentheses ('blind' column now FALSE instead of TRUE).
+       (m4_syncoutput): only accept arg1 values as documented, expand to 0 or
+       1 if invoked without args.
+
+       * src/m4.h: Added extern output_filename_synced, declared in output.c
+       and used in input.c.
+
+       * src/input.c: Fix bug where filename not emitted in first '#line';
+       use flag output_filename_synced instead of placing value of -1 in
+       output_current_line.
+
+       * src/output.c (COUNT_LINES): Added.
+       (count_lines): Added.
+       (shipout_text): Modified line-counting logic to cope correctly with
+       sync output being enabled and disabled willy-nilly.
+       (output_text): Miniscule optimization.
+
+       * doc/m4.texinfo (Syncoutput): Document no-parentheses case.
+
+       * examples/Makefile.am (pkgdata_DATA): Added syncoutput.m4.
+
+       * examples/Makefile.am (TESTS): Added syncoutput.test.
+
+       * examples/syncoutput.m4: New file.
+
+       * examples/syncoutput.test: New file.
+
 2000-01-16  Rene' Seindal  <address@hidden>
 
        * modules/Makefile.am (TESTS): New tests for the module system.
diff -u -r -N --exclude config* --exclude aclocal.m4 --exclude Makefile.in 
--exclude Makefile --exclude intl --exclude po --exclude *~ --exclude tags 
--exclude testSubDir --exclude stamp-vti --exclude version.texi --exclude 
*.orig --exclude *.rej --exclude .indent.pro --exclude .deps --exclude *.o 
--exclude *.info* --exclude *.a m4-1.4ppre2.orig/doc/m4.texinfo 
m4-1.4ppre2/doc/m4.texinfo
--- m4-1.4ppre2.orig/doc/m4.texinfo     Mon Jan 10 15:35:58 2000
+++ m4-1.4ppre2/doc/m4.texinfo  Thu Sep 27 10:36:27 2001
@@ -3608,8 +3608,10 @@
 @code{syncoutput(0)}, @code{syncoutput(off)}, and @code{syncoutput(no)}
 turn them off.
 
-All other arguments are ignored as is @code{syncoutput} without
-parenthesis.
+All other arguments are ignored.
+
address@hidden with no parentheses expands to @samp{1} if sync output
+is currently enabled, and @samp{0} if not.
 
 @node Frozen files, Compatibility, Miscellaneous, Top
 @chapter Fast loading of frozen states
diff -u -r -N --exclude config* --exclude aclocal.m4 --exclude Makefile.in 
--exclude Makefile --exclude intl --exclude po --exclude *~ --exclude tags 
--exclude testSubDir --exclude stamp-vti --exclude version.texi --exclude 
*.orig --exclude *.rej --exclude .indent.pro --exclude .deps --exclude *.o 
--exclude *.info* --exclude *.a m4-1.4ppre2.orig/examples/Makefile.am 
m4-1.4ppre2/examples/Makefile.am
--- m4-1.4ppre2.orig/examples/Makefile.am       Fri Mar 26 22:17:53 1999
+++ m4-1.4ppre2/examples/Makefile.am    Wed Sep 12 13:43:19 2001
@@ -24,6 +24,7 @@
        pushpop.m4 \
        regexp.m4 \
        reverse.m4 \
+       syncoutput.m4 \
        sysv-args.m4 \
        trace.m4 \
        translit.m4 \
@@ -49,6 +50,7 @@
        pushpop.test \
        regexp.test \
        reverse.test \
+       syncoutput.test \
        sysv-args.test \
        trace.test \
        translit.test \
diff -u -r -N --exclude config* --exclude aclocal.m4 --exclude Makefile.in 
--exclude Makefile --exclude intl --exclude po --exclude *~ --exclude tags 
--exclude testSubDir --exclude stamp-vti --exclude version.texi --exclude 
*.orig --exclude *.rej --exclude .indent.pro --exclude .deps --exclude *.o 
--exclude *.info* --exclude *.a m4-1.4ppre2.orig/examples/syncoutput.m4 
m4-1.4ppre2/examples/syncoutput.m4
--- m4-1.4ppre2.orig/examples/syncoutput.m4     Thu Jan  1 10:00:00 1970
+++ m4-1.4ppre2/examples/syncoutput.m4  Tue Sep  4 23:00:20 2001
@@ -0,0 +1,35 @@
+traceon(`syncoutput')dnl
+one
+divert(-1)
+
+define(`NOSYNC', ``'pushdef(`_sync', 
syncoutput)syncoutput(0)$1`'syncoutput(_sync)`'popdef(`_sync')')
+
+define(`repeat', `ifelse($1, 0, , `$2`'repeat(decr(`$1'), `$2')')')
+
+define(`A', `>>$1<<')
+define(`B', `line $1
+line $2')
+define(`C', `repeat($1, `$2
+')')
+
+divert`'dnl
+syncoutput(1)dnl
+two
+A(three) A(three and a half) A(three and
+a bit more)
+four
+B(five, five and a half)
+six
+>B(seven, seven and a half)
+eight
+NOSYNC(`B(nine, nine and a half)')
+ten
+>NOSYNC(`B(eleven, eleven and a half)')
+twelve
+thirteen
+NOSYNC(`C(4, fourteen)')
+fifteen
+>NOSYNC(`C(5, sixteen)')
+seventeen
+syncoutput(0)dnl
+eighteen
diff -u -r -N --exclude config* --exclude aclocal.m4 --exclude Makefile.in 
--exclude Makefile --exclude intl --exclude po --exclude *~ --exclude tags 
--exclude testSubDir --exclude stamp-vti --exclude version.texi --exclude 
*.orig --exclude *.rej --exclude .indent.pro --exclude .deps --exclude *.o 
--exclude *.info* --exclude *.a m4-1.4ppre2.orig/examples/syncoutput.test 
m4-1.4ppre2/examples/syncoutput.test
--- m4-1.4ppre2.orig/examples/syncoutput.test   Thu Jan  1 10:00:00 1970
+++ m4-1.4ppre2/examples/syncoutput.test        Tue Sep  4 23:00:20 2001
@@ -0,0 +1,72 @@
+#!/bin/sh
+
+# syncoutput.test is part of the GNU m4 testsuite
+
+. ${srcdir}/defs
+
+cat ${srcdir}/syncoutput.m4 >in
+
+cat <<\EOF >ok
+one
+#line 17 "in"
+two
+>>three<< >>three and a half<< >>three and
+a bit more<<
+four
+line five
+#line 21
+line five and a half
+six
+>line seven
+#line 23
+line seven and a half
+eight
+line nine
+line nine and a half
+#line 26
+ten
+>line eleven
+line eleven and a half
+#line 28
+twelve
+thirteen
+fourteen
+fourteen
+fourteen
+fourteen
+#line 31
+
+#line 31
+fifteen
+>sixteen
+sixteen
+sixteen
+sixteen
+sixteen
+#line 33
+
+#line 33
+seventeen
+eighteen
+EOF
+
+cat <<\EOF >okerr
+m4trace: -1- syncoutput(`1')
+m4trace: -2- syncoutput -> `1'
+m4trace: -1- syncoutput(`0')
+m4trace: -1- syncoutput(`1')
+m4trace: -2- syncoutput -> `1'
+m4trace: -1- syncoutput(`0')
+m4trace: -1- syncoutput(`1')
+m4trace: -2- syncoutput -> `1'
+m4trace: -1- syncoutput(`0')
+m4trace: -1- syncoutput(`1')
+m4trace: -2- syncoutput -> `1'
+m4trace: -1- syncoutput(`0')
+m4trace: -1- syncoutput(`1')
+m4trace: -1- syncoutput(`0')
+EOF
+
+M4PATH=$srcdir:$srcdir/../tests $M4 -d in >out 2>err
+sed -e "s,../../src/m4: ,m4: ," err >sederr && mv sederr err
+$CMP -s out ok && $CMP -s err okerr
diff -u -r -N --exclude config* --exclude aclocal.m4 --exclude Makefile.in 
--exclude Makefile --exclude intl --exclude po --exclude *~ --exclude tags 
--exclude testSubDir --exclude stamp-vti --exclude version.texi --exclude 
*.orig --exclude *.rej --exclude .indent.pro --exclude .deps --exclude *.o 
--exclude *.info* --exclude *.a m4-1.4ppre2.orig/src/builtin.c 
m4-1.4ppre2/src/builtin.c
--- m4-1.4ppre2.orig/src/builtin.c      Sun Jan 16 13:17:41 2000
+++ m4-1.4ppre2/src/builtin.c   Tue Sep  4 23:18:22 2001
@@ -143,7 +143,7 @@
   { "sinclude",                FALSE,  FALSE,  TRUE,   m4_sinclude },
   { "substr",          FALSE,  FALSE,  TRUE,   m4_substr },
   { "symbols",         TRUE,   FALSE,  FALSE,  m4_symbols },
-  { "syncoutput",      TRUE,   FALSE,  TRUE,   m4_syncoutput },
+  { "syncoutput",      TRUE,   FALSE,  FALSE,  m4_syncoutput },
   { "syscmd",          FALSE,  FALSE,  TRUE,   m4_syscmd },
   { "sysval",          FALSE,  FALSE,  FALSE,  m4_sysval },
   { "traceoff",                FALSE,  FALSE,  FALSE,  m4_traceoff },
@@ -822,32 +822,55 @@
 }
 
 /*------------------------------------------------------------------------.
-| This contains macro which implements syncoutput() which takes one arg   |
-|   1, on, yes - turn on sync lines                                       |
-|   0, off, no - turn off sync lines                                      |
-|   everything else is silently ignored                                   |
+| This contains macro which implements syncoutput()                       |
+|   if one arg given,                                                     |
+|     1, on, yes - turn on sync lines                                     |
+|     0, off, no - turn off sync lines                                    |
+|     anything else is silently ignored                                   |
+|   if no arg given, expand to                                            |
+|     0 if sync lines currently turned off                                |
+|     1 if sync lines currently turned on                                 |
 |                                                                         |
 `------------------------------------------------------------------------*/
 
 static void
 m4_syncoutput (struct obstack *obs, int argc, token_data **argv)
 {
-  if (m4_bad_argc (argv[0], argc, 2, 2))
+  int value;
+
+  if (m4_bad_argc (argv[0], argc, 1, 2))
     return;
 
+  if (argc == 1)
+    {
+      m4_shipout_int (obs, sync_output);
+      return;
+    }
+
   if (TOKEN_DATA_TYPE (argv[1]) != TOKEN_TEXT)
     return;
 
-  if (TOKEN_DATA_TEXT(argv[1])[0] == '0'
-      || TOKEN_DATA_TEXT(argv[1])[0] == 'n'
-      || (TOKEN_DATA_TEXT(argv[1])[0] == 'o'
-         && TOKEN_DATA_TEXT(argv[1])[1] == 'f'))
-    sync_output = 0;
-  else if (TOKEN_DATA_TEXT(argv[1])[0] == '1'
-          || TOKEN_DATA_TEXT(argv[1])[0] == 'y'
-          || (TOKEN_DATA_TEXT(argv[1])[0] == 'o'
-              && TOKEN_DATA_TEXT(argv[1])[1] == 'n'))
-    sync_output = 1;
+  if (m4_numeric_arg (argv[0], M4ARG (1), &value))
+    sync_output = value ? 1 : 0;
+  else
+    {
+      if (   (TOKEN_DATA_TEXT(argv[1])[0] == 'n'
+             && TOKEN_DATA_TEXT(argv[1])[1] == 'o'
+             && TOKEN_DATA_TEXT(argv[1])[2] == '\0')
+         || (TOKEN_DATA_TEXT(argv[1])[0] == 'o'
+             && TOKEN_DATA_TEXT(argv[1])[1] == 'f'
+             && TOKEN_DATA_TEXT(argv[1])[2] == 'f'
+             && TOKEN_DATA_TEXT(argv[1])[3] == '\0'))
+       sync_output = 0;
+      else if (   (TOKEN_DATA_TEXT(argv[1])[0] == 'y'
+                  && TOKEN_DATA_TEXT(argv[1])[1] == 'e'
+                  && TOKEN_DATA_TEXT(argv[1])[2] == 's'
+                  && TOKEN_DATA_TEXT(argv[1])[3] == '\0')
+              || (TOKEN_DATA_TEXT(argv[1])[0] == 'o'
+                  && TOKEN_DATA_TEXT(argv[1])[1] == 'n'
+                  && TOKEN_DATA_TEXT(argv[1])[2] == '\0'))
+       sync_output = 1;
+    }
 }
 
 /*------------------------------------------------------------------------.
diff -u -r -N --exclude config* --exclude aclocal.m4 --exclude Makefile.in 
--exclude Makefile --exclude intl --exclude po --exclude *~ --exclude tags 
--exclude testSubDir --exclude stamp-vti --exclude version.texi --exclude 
*.orig --exclude *.rej --exclude .indent.pro --exclude .deps --exclude *.o 
--exclude *.info* --exclude *.a m4-1.4ppre2.orig/src/input.c 
m4-1.4ppre2/src/input.c
--- m4-1.4ppre2.orig/src/input.c        Sun Jan 16 13:17:41 2000
+++ m4-1.4ppre2/src/input.c     Tue Sep  4 23:00:20 2001
@@ -318,7 +318,7 @@
   output_current_line = isp->u.u_f.out_lineno;
   start_of_input_line = isp->u.u_f.advance_line;
   if (isp->prev != NULL)
-    output_current_line = -1;
+    output_filename_synced = FALSE;
 }
 
 static struct input_funcs file_funcs = {
@@ -351,7 +351,7 @@
 
   current_file = obstack_copy0 (current_input, title, strlen (title));
   current_line = 1;
-  output_current_line = -1;
+  output_filename_synced = FALSE;
 
   i->prev = isp;
   isp = i;
diff -u -r -N --exclude config* --exclude aclocal.m4 --exclude Makefile.in 
--exclude Makefile --exclude intl --exclude po --exclude *~ --exclude tags 
--exclude testSubDir --exclude stamp-vti --exclude version.texi --exclude 
*.orig --exclude *.rej --exclude .indent.pro --exclude .deps --exclude *.o 
--exclude *.info* --exclude *.a m4-1.4ppre2.orig/src/m4.h m4-1.4ppre2/src/m4.h
--- m4-1.4ppre2.orig/src/m4.h   Sun Jan 16 22:18:38 2000
+++ m4-1.4ppre2/src/m4.h        Tue Sep  4 23:00:20 2001
@@ -221,6 +221,7 @@
 
 /* File: output.c --- output functions.  */
 extern int current_diversion;
+extern boolean output_filename_synced;
 extern int output_current_line;
 
 void output_init M4_PARAMS((void));
diff -u -r -N --exclude config* --exclude aclocal.m4 --exclude Makefile.in 
--exclude Makefile --exclude intl --exclude po --exclude *~ --exclude tags 
--exclude testSubDir --exclude stamp-vti --exclude version.texi --exclude 
*.orig --exclude *.rej --exclude .indent.pro --exclude .deps --exclude *.o 
--exclude *.info* --exclude *.a m4-1.4ppre2.orig/src/output.c 
m4-1.4ppre2/src/output.c
--- m4-1.4ppre2.orig/src/output.c       Sun Jan 16 13:17:41 2000
+++ m4-1.4ppre2/src/output.c    Tue Sep  4 23:00:20 2001
@@ -76,6 +76,10 @@
 static char *output_cursor;    /* current value of (buffer + used) */
 static int output_unused;      /* current value of (size - used) */
 
+/* Whether we have written the current input file name during sync
+   output are generating output for.  */
+boolean output_filename_synced;
+
 /* Number of input line we are generating output for.  */
 int output_current_line;
 
@@ -347,9 +351,6 @@
 {
   int count;
 
-  if (!output_file && length > output_unused)
-    make_room_for (length);
-
   if (output_file)
     {
       count = fwrite (text, length, 1, output_file);
@@ -358,12 +359,33 @@
     }
   else
     {
+      if (length > output_unused)
+       make_room_for (length);
       memcpy (output_cursor, text, (size_t) length);
       output_cursor += length;
       output_unused -= length;
     }
 }
 
+/*------------------------------------------------------------------------.
+| Increment the output line counter if the given character is a newline.  |
+`------------------------------------------------------------------------*/
+
+#define COUNT_LINES(Char) (output_current_line += (Char) == '\n')
+
+/*------------------------------------------------------------------------.
+| Count the number of newlines in the given TEXT of LENGTH characters.    |
+`------------------------------------------------------------------------*/
+
+static int
+count_lines (const char *text, int length)
+{
+  int count = 0;
+  while (length--)
+    count += *text++ == '\n';
+  return count;
+}
+
 /*-------------------------------------------------------------------------.
 | Add some text into an obstack OBS, taken from TEXT, having LENGTH       |
 | characters.  If OBS is NULL, rather output the text to an external file  |
@@ -399,37 +421,44 @@
   /* Output TEXT to a file, or in-memory diversion buffer.  */
 
   if (!sync_output)
-    switch (length)
-      {
-
-       /* In-line short texts.  */
+    {
+      if (start_of_output_line)
+         output_current_line++;
 
-      case 8: OUTPUT_CHARACTER (*text); text++;
-      case 7: OUTPUT_CHARACTER (*text); text++;
-      case 6: OUTPUT_CHARACTER (*text); text++;
-      case 5: OUTPUT_CHARACTER (*text); text++;
-      case 4: OUTPUT_CHARACTER (*text); text++;
-      case 3: OUTPUT_CHARACTER (*text); text++;
-      case 2: OUTPUT_CHARACTER (*text); text++;
-      case 1: OUTPUT_CHARACTER (*text);
-      case 0:
-       return;
+      switch (length)
+       {
 
-       /* Optimize longer texts.  */
+         /* In-line short texts.  */
 
-      default:
-       output_text (text, length);
-      }
+       case 8: OUTPUT_CHARACTER (*text); COUNT_LINES(*text); text++;
+       case 7: OUTPUT_CHARACTER (*text); COUNT_LINES(*text); text++;
+       case 6: OUTPUT_CHARACTER (*text); COUNT_LINES(*text); text++;
+       case 5: OUTPUT_CHARACTER (*text); COUNT_LINES(*text); text++;
+       case 4: OUTPUT_CHARACTER (*text); COUNT_LINES(*text); text++;
+       case 3: OUTPUT_CHARACTER (*text); COUNT_LINES(*text); text++;
+       case 2: OUTPUT_CHARACTER (*text); COUNT_LINES(*text); text++;
+       case 1: OUTPUT_CHARACTER (*text);
+         start_of_output_line = *text == '\n';
+       case 0:
+         return;
+
+         /* Optimize longer texts.  */
+
+       default:
+         output_current_line += count_lines(text, length - 1);
+         start_of_output_line = text[length - 1] == '\n';
+         output_text (text, length);
+       }
+    }
   else
     for (; length-- > 0; text++)
       {
        if (start_of_output_line)
          {
-           start_of_output_line = FALSE;
            output_current_line++;
 
 #ifdef DEBUG_OUTPUT
-           printf ("DEBUG: cur %d, cur out %d\n",
+           printf ("DEBUG: cur in %d, cur out %d\n",
                    current_line, output_current_line);
 #endif
 
@@ -437,26 +466,26 @@
               If output_current_line was previously given a negative
               value (invalidated), rather output `#line NUM "FILE"'.  */
 
-           if (output_current_line != current_line)
+           if (!output_filename_synced || output_current_line != current_line)
              {
                sprintf (line, "#line %d", current_line);
                for (cursor = line; *cursor; cursor++)
                  OUTPUT_CHARACTER (*cursor);
-               if (output_current_line < 1)
+               if (!output_filename_synced)
                  {
                    OUTPUT_CHARACTER (' ');
                    OUTPUT_CHARACTER ('"');
                    for (cursor = current_file; *cursor; cursor++)
                      OUTPUT_CHARACTER (*cursor);
                    OUTPUT_CHARACTER ('"');
+                   output_filename_synced = TRUE;
                  }
                OUTPUT_CHARACTER ('\n');
                output_current_line = current_line;
              }
          }
        OUTPUT_CHARACTER (*text);
-       if (*text == '\n')
-         start_of_output_line = TRUE;
+       start_of_output_line = *text == '\n';
       }
 }
 
@@ -510,7 +539,7 @@
   output_file = output_diversion->file;
   output_cursor = output_diversion->buffer + output_diversion->used;
   output_unused = output_diversion->size - output_diversion->used;
-  output_current_line = -1;
+  output_filename_synced = FALSE;
 }
 
 /*-------------------------------------------------------------------.
@@ -574,7 +603,7 @@
       else if (diversion->buffer)
        output_text (diversion->buffer, diversion->used);
 
-      output_current_line = -1;
+      output_filename_synced = FALSE;
     }
 
   /* Return all space used by the diversion.  */

reply via email to

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