m4-patches
[Top][All Lists]
Advanced

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

Re: [PATCH] Line synchronisation output in comments


From: Sergey Poznyakoff
Subject: Re: [PATCH] Line synchronisation output in comments
Date: Fri, 25 May 2007 18:41:18 +0300

Eric Blake <address@hidden> ha escrit:

> However, the issue is not just multiline comments, but also multiline
> strings, so I think creating a new TOKEN_COMMENT is not strictly
> necessary, since the fix for one should be applied to the other.

Yes, that's reasonable.

> Note the double #line 7, neither of which were necessary (since the string
> came from the combination of line 6 and 7); and with your patch, if #line
> 4 were suppressed because it was in the middle of a comment, then hello
> needs a leading #line 5, but I'm not sure your patch did that.

No, it does not.  After thinking its over I came to the another patch,
attached below (this time it is made against the CVS version).  The two
testcases (my initial one, and the one based on your last posting) are
provided in the attachements 2 and 3.

Running the second one (as `m4 -s 2.m4 | nl -ba') yields:

-- begin output --
     1  #line 2 "2.m4"
     2  
     3  
     4  /*
     5  */
     6  #line 4
     7  
     8  hello (at line 5)
     9  a
    10  b
    11  #line 7
    12  
    13  bye (at line 8)
-- end output --

Thus, the line numbers are preserved in this case too, and multiline
quoted strings are not split.

Regards,
Sergey

2007-05-25  Sergey Poznyakoff  <address@hidden>

         * m4/output.c (sync_line): New function
         (shipout_text): Output line synchronisation directive after
         or before the token.

Index: m4/output.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/output.c,v
retrieving revision 1.42
diff -p -u -r1.42 output.c
--- m4/output.c 2 Apr 2007 12:06:23 -0000       1.42
+++ m4/output.c 25 May 2007 15:28:29 -0000
@@ -443,6 +443,30 @@ output_text (m4 *context, const char *te
     }
 }
 
+static void
+sync_line (m4 *context)
+{
+  char line[20];
+  const char *cursor;
+
+  sprintf (line, "#line %lu",
+          (unsigned long int) m4_get_current_line (context));
+
+  for (cursor = line; *cursor; cursor++)
+    OUTPUT_CHARACTER (*cursor);
+  if (m4_get_output_line (context) < 1
+      && m4_get_current_file (context)[0] != '\0')
+    {
+      OUTPUT_CHARACTER (' ');
+      OUTPUT_CHARACTER ('"');
+      for (cursor = m4_get_current_file (context); *cursor; cursor++)
+       OUTPUT_CHARACTER (*cursor);
+      OUTPUT_CHARACTER ('"');
+    }
+  OUTPUT_CHARACTER ('\n');
+  m4_set_output_line (context, m4_get_current_line (context));
+}
+
 /* 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
    or an in-memory diversion buffer.  If OBS is NULL, and there is no
@@ -457,8 +481,6 @@ m4_shipout_text (m4 *context, m4_obstack
                 const char *text, size_t length)
 {
   static bool start_of_output_line = true;
-  char line[20];
-  const char *cursor;
 
   /* If output goes to an obstack, merely add TEXT to it.  */
 
@@ -498,49 +520,50 @@ m4_shipout_text (m4 *context, m4_obstack
        output_text (context, text, length);
       }
   else
-    for (; length-- > 0; text++)
-      {
-       if (start_of_output_line)
-         {
-           start_of_output_line = false;
-           m4_set_output_line (context, m4_get_output_line (context) + 1);
+    {
+      bool need_sync = false;
+      for (; length-- > 0; text++)
+       {
+         if (start_of_output_line)
+           {
+             start_of_output_line = false;
+             m4_set_output_line (context, m4_get_output_line (context) + 1);
 
 #ifdef DEBUG_OUTPUT
-           fprintf (stderr, "DEBUG: cur %lu, cur out %lu\n",
-                    (unsigned long int) m4_get_current_line (context),
-                    (unsigned long int) m4_get_output_line (context));
+             fprintf (stderr, "DEBUG: cur %lu, cur out %lu\n",
+                      (unsigned long int) m4_get_current_line (context),
+                      (unsigned long int) m4_get_output_line (context));
 #endif
-
-           /* Output a `#line NUM' synchronization directive if needed.
-              If output_line was previously given a negative
-              value (invalidated), then output `#line NUM "FILE"'.  */
-
-           if (m4_get_output_line (context) != m4_get_current_line (context))
-             {
-               sprintf (line, "#line %lu",
-                        (unsigned long int) m4_get_current_line (context));
-               for (cursor = line; *cursor; cursor++)
-                 OUTPUT_CHARACTER (*cursor);
-               if (m4_get_output_line (context) < 1
-                   && m4_get_current_file (context)[0] != '\0')
-                 {
-                   OUTPUT_CHARACTER (' ');
-                   OUTPUT_CHARACTER ('"');
-                   for (cursor = m4_get_current_file (context);
-                        *cursor; cursor++)
-                     {
-                       OUTPUT_CHARACTER (*cursor);
-                     }
-                   OUTPUT_CHARACTER ('"');
-                 }
-               OUTPUT_CHARACTER ('\n');
-               m4_set_output_line (context, m4_get_current_line (context));
-             }
-         }
-       OUTPUT_CHARACTER (*text);
-       if (*text == '\n')
-         start_of_output_line = true;
-      }
+             if (m4_get_output_line (context)
+                 != m4_get_current_line (context))           
+               {
+                 /* If output_line was previously given a negative
+                    value (invalidated), output `#line NUM "FILE"'
+                    immediately */
+                 if (m4_get_output_line (context) < 1)
+                   sync_line (context);
+                 else
+                   {
+                     /* Otherwise, schedule the line synchronisation output
+                        after finishing outputting the token */
+                     need_sync = true;
+                     m4_set_output_line (context,
+                                         m4_get_current_line (context));
+                   }
+               }
+           }
+         OUTPUT_CHARACTER (*text);
+         if (*text == '\n')
+           start_of_output_line = true;
+       }
+      /* Output a `#line NUM' synchronization directive if needed. */
+      if (need_sync)
+       {
+         if (!start_of_output_line)
+           OUTPUT_CHARACTER ('\n');
+         sync_line (context);
+       }
+    }
 }
 
 /* Format an int VAL, and stuff it into an obstack OBS.  Used for
changecom(/*,*/)
/* line 1
   line 2
*/
TEST (at line 5)
define(twoline,/*
*/)
changecom(/*,*/)
twoline
hello (at line 5)
`a
b'
bye (at line 8)

reply via email to

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