This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Preliminary patch for




I knocked this out rather quickly and gave it a spin on my
Linux box.  It seemed to work.  Unless someone finds problems,
it should forever fix the incorrect comments that sometimes
appear, without ever breaking anything.  Ha!  C code can be a
little more rigorous than sed.

Regards,
	Bruce

Index: inclhack.def
===================================================================
RCS file: /cvs/gcc/egcs/gcc/fixinc/inclhack.def,v
retrieving revision 1.38
diff -u -r1.38 inclhack.def
--- inclhack.def	1999/10/15 06:02:01	1.38
+++ inclhack.def	1999/10/15 17:37:06
@@ -582,47 +582,10 @@
 
     /*
      *  Select files that contain '#endif' or '#else' directives with
-     *  some sort of following junk.  (Between the ascii '.'
-     *  and '0' lies the character '/'.  This will *NOT*
-     *  match '#endif / * foo * /', but it also wont match
-     *  '#endif / done' either.
-     *
-     *  We have a second regexp in the selector to detect
-     *  #endif followed by a / followed by anything other
-     *  than a *.  For example "#endif / * foo * /" or 
-     *  "#endif /% blah %/ which appear on OSF4.0A and AIX4.2
-     *  repsectively.
-     * 
-     *  We use the pattern [!-.0-z{|}~] instead of [^/ \t] to match a
-     *  noncomment following #else or #endif because some buggy egreps
-     *  think [^/] matches newline, and they thus think `#else ' matches
-     *  `#e[ndiflse]*[ \t]+[^/ \t]'.
-     *  [!-.0-~] does not work properly on AIX 4.1.
+     *  some sort of following junk.
      */
-    select   = "^[ \t]*#[ \t]*(else|endif)[ \t]+"
-               "("  '[!-.0-z\{\|\}\~]'  "|"  '/[^\*]'  ")";
-
-    /*
-     *  First, join the continued input lines.
-     *  IF the resulting line is an endif preprocessing directive,
-     *  then trim off the following patterns:
-     *  1.  sequences that start with '/' and is *NOT* followed by '*'
-     *  2.  Sequences that start with '*' and is *NOT* followed by '/'
-     *  3.  sequences that do not start with any of '/', '*', '\t' or ' '.
-     *
-     * The fixinc_eol stuff is to work around a bug in the sed
-     */
-    sed =      ":loop\n"
-               '/\\\\$/'                       "N\n"
-               's/\\\\$/\\\\+++fixinc_eol+++/' "\n"
-               '/\\\\$/'                       "b loop\n"
-               's/\\\\+++fixinc_eol+++/\\\\/g' "\n"
-
-               "s%^\\([ \t]*#[ \t]*else\\)[ \t][ \t]*/[^*].*%\\1%\n"
-               "s%^\\([ \t]*#[ \t]*else\\)[ \t][ \t]*[^/ \t].*%\\1%\n"
-               "s%^\\([ \t]*#[ \t]*endif\\)[ \t][ \t]*/[^*].*%\\1%\n"
-               "s%^\\([ \t]*#[ \t]*endif\\)[ \t][ \t]*\\*[^/].*%\\1%\n"
-               "s%^\\([ \t]*#[ \t]*endif\\)[ \t][ \t]*[^/* \t].*%\\1%";
+    c_test = "else_endif_label";
+    c_fix  = "else_endif_label";
 };
 
 
Index: fixtests.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/fixinc/fixtests.c,v
retrieving revision 1.2
diff -u -r1.2 fixtests.c
--- fixtests.c	1999/10/12 14:30:29	1.2
+++ fixtests.c	1999/10/15 17:37:06
@@ -62,7 +62,8 @@
 } test_entry_t;
 
 #define FIX_TEST_TABLE \
-  _FT_( "double_slash", double_slash_test )
+  _FT_( "double_slash",     double_slash_test ) \
+  _FT_( "else_endif_label", else_endif_label_test )
 
 
 #define TEST_FOR_FIX_PROC_HEAD( test ) \
@@ -154,6 +155,133 @@
   return SKIP_FIX;
 }
 
+
+TEST_FOR_FIX_PROC_HEAD( else_endif_label_test )
+{
+  static int compiled = 0;
+  static const char label_pat[] = "^[ \t]*#[ \t]*(else|endif)";
+  static regex_t label_re;
+
+  char ch;
+  const char* pz_next = (char*)NULL;
+  regmatch_t match[2];
+
+  /*
+     This routine may be run many times within a single execution.
+     Do the compile once only in that case.  In the standalone case,
+     we waste 10 bytes of memory and a test, branch and increment delay.  */
+  if (! compiled)
+    {
+      compiled++;
+      re_set_syntax (RE_SYNTAX_EGREP);
+      (void)re_compile_pattern (label_pat, sizeof (label_pat)-1,
+                                &label_re);
+    }
+
+  for (;;) /* entire file */
+    {
+      /*
+        See if we need to advance to the next candidate directive
+        If the scanning pointer passes over the end of the directive,
+        then the directive is inside a comment */
+      if (pz_next < text)
+        {
+          if (regexec (&label_re, text, 2, match, 0) != 0)
+            break;
+          pz_next = text + match[0].rm_eo;
+        }
+
+      /*
+        IF the scan pointer has not reached the directive end, ... */
+      if (pz_next > text)
+        {
+          /*
+            Advance the scanning pointer.  If we are at the start
+            of a quoted string or a comment, then skip the entire unit */
+          ch = *(text++);
+
+          switch (ch)
+            {
+            case '/':
+              /*
+                Skip comments */
+              if (*text == '*')
+                {
+                  text = strstr( text+1, "*/" );
+                  if (text == (char*)NULL)
+                    return SKIP_FIX;
+                  text += 2;
+                  continue;
+                }
+              break;
+
+            case '"':
+            case '\'':
+              text = skip_quote( ch, text );
+              break;
+            } /* switch (ch) */
+          continue;
+        } /* if (still shy of directive end) */
+
+      /*
+         The scanning pointer (text) has reached the end of the current
+         directive under test, then check for bogons here */
+      for (;;) /* bogon check */
+        {
+          char ch = *(pz_next++);
+          if (isspace (ch))
+            {
+              if (ch == '\n')
+                {
+                  /*
+                    It is clean.  No bogons on this directive */
+                  text = pz_next;
+                  pz_next = (char*)NULL; /* force a new regex search */
+                  break;
+                }
+              continue;
+            }
+
+          switch (ch)
+            {
+            case '\\':
+              /*
+                Skip escaped newlines.  Otherwise, we have a bogon */
+              if (*pz_next != '\n')
+                return APPLY_FIX;
+
+              pz_next++;
+              break;
+
+            case '/':
+              /*
+                Skip comments.  Otherwise, we have a bogon */
+              if (*pz_next == '*')
+                {
+                  pz_next = strstr( pz_next+1, "*/" );
+                  if (pz_next == (char*)NULL)
+                    return SKIP_FIX;
+                  pz_next += 2;
+                  break;
+                }
+
+              /*
+                FIXME:  if this is a C++ file, then a double slash comment
+                is allowed to follow the directive.  */
+
+              /* FALLTHROUGH */
+
+            default:
+              /*
+                GOTTA BE A BOGON */
+              return APPLY_FIX;
+            } /* switch (ch) */
+        } /* for (bogon check loop) */
+    } /* for (entire file) loop */
+
+  return SKIP_FIX;
+}
+
 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
 
      test for fix selector
@@ -179,6 +307,7 @@
     {
       if (strcmp( pte->test_name, tname ) == 0)
         return (*pte->test_proc)( fname, text );
+      pte++;
     } while (--ct > 0);
   fprintf( stderr, "fixincludes error:  the `%s' fix test is unknown\n",
            tname );
Index: fixfixes.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/fixinc/fixfixes.c,v
retrieving revision 1.2
diff -u -r1.2 fixfixes.c
--- fixfixes.c	1999/10/12 14:27:31	1.2
+++ fixfixes.c	1999/10/15 17:37:07
@@ -72,7 +72,8 @@
 } fix_entry_t;
 
 #define FIXUP_TABLE \
-  _FT_( "no_double_slash", double_slash_fix )
+  _FT_( "no_double_slash",  double_slash_fix ) \
+  _FT_( "else_endif_label", else_endif_label_fix )
 
 
 #define FIX_PROC_HEAD( fix ) \
@@ -180,6 +181,184 @@
   fclose (stdout);;
 }
 
+
+FIX_PROC_HEAD( else_endif_label_fix )
+{
+  static const char label_pat[] = "^[ \t]*#[ \t]*(else|endif)";
+  static regex_t label_re;
+
+  char ch;
+  char* pz_next = (char*)NULL;
+  regmatch_t match[2];
+
+  re_set_syntax (RE_SYNTAX_EGREP);
+  (void)re_compile_pattern (label_pat, sizeof (label_pat)-1,
+                            &label_re);
+
+  for (;;) /* entire file */
+    {
+      /*
+        See if we need to advance to the next candidate directive
+        If the scanning pointer passes over the end of the directive,
+        then the directive is inside a comment */
+      if (pz_next < text)
+        {
+          if (regexec (&label_re, text, 2, match, 0) != 0)
+            {
+              fputs( text, stdout );
+              break;
+            }
+
+          pz_next = text + match[0].rm_eo;
+        }
+
+      /*
+        IF the scan pointer has not reached the directive end, ... */
+      if (pz_next > text)
+        {
+          /*
+            Advance the scanning pointer.  If we are at the start
+            of a quoted string or a comment, then skip the entire unit */
+          ch = *text;
+
+          switch (ch)
+            {
+            case '/':
+              /*
+                Skip comments */
+              if (text[1] == '*')
+                {
+                  char* pz = strstr( text+2, "*/" );
+                  if (pz == (char*)NULL)
+                    {
+                      fputs( text, stdout );
+                      return;
+                    }
+                  pz += 2;
+                  fwrite( text, 1, (pz - text), stdout );
+                  text = pz;
+                  continue;
+                }
+              putc( ch, stdout );
+              text++;
+              break;
+
+            case '"':
+            case '\'':
+              text = print_quote( ch, text+1 );
+              break;
+
+            default:
+              putc( ch, stdout );
+              text++;
+            } /* switch (ch) */
+          continue;
+        } /* if (still shy of directive end) */
+
+      /*
+         The scanning pointer (text) has reached the end of the current
+         directive under test.  Check for bogons here.  */
+      for (;;) /* bogon check */
+        {
+          char ch = *(text++);
+          if (isspace (ch))
+            {
+              putc( ch, stdout );
+              if (ch == '\n')
+                {
+                  /*
+                    It is clean.  No bogons on this directive */
+                  pz_next = (char*)NULL; /* force a new regex search */
+                  goto dont_fix_bogon;
+                }
+              continue;
+            }
+
+          switch (ch)
+            {
+            case NUL:
+              return;
+
+            case '\\':
+              /*
+                Skip escaped newlines.  Otherwise, we have a bogon */
+              if (*text != '\n') {
+                text--;
+                goto fix_the_bogon;
+              }
+
+              /*
+                Emit the escaped newline and keep scanning for possible junk */
+              putc( '\\', stdout );
+              putc( '\n', stdout );
+              text++;
+              break;
+
+            case '/':
+              /*
+                Skip comments.  Otherwise, we have a bogon */
+              if (*text == '*')
+                {
+                  text--;
+                  pz_next = strstr( text+2, "*/" );
+                  if (pz_next == (char*)NULL)
+                    {
+                      putc( '\n', stdout );
+                      return;
+                    }
+                  pz_next += 2;
+                  fwrite( text, 1, (pz_next - text), stdout );
+                  text = pz_next;
+                  break;
+                }
+
+              /*
+                FIXME:  if this is a C++ file, then a double slash comment
+                is allowed to follow the directive.  */
+
+              /* FALLTHROUGH */
+
+            default:
+              /*
+                GOTTA BE A BOGON */
+              text--;
+              goto fix_the_bogon;
+            } /* switch (ch) */
+        } /* for (bogon check loop) */
+
+    fix_the_bogon:
+      /*
+        `text' points to the start of the bogus data */
+      for (;;)
+        {
+          /*
+            NOT an escaped newline.  Find the end of line that
+            is not preceeded by an escape character:  */
+          pz_next = strchr( text, '\n' );
+          if (pz_next == (char*)NULL)
+            {
+              putc( '\n', stdout );
+              return;
+            }
+
+          if (pz_next[-1] != '\\')
+            {
+              text = pz_next;
+              pz_next = (char*)NULL; /* force a new regex search */
+              break;
+            }
+
+          /*
+            The newline was escaped.  We gotta keep going.  */
+          text = pz_next + 1;
+        }
+
+    dont_fix_bogon:;
+    } /* for (entire file) loop */
+
+  return;
+}
+
 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
 
      test for fix selector
@@ -206,11 +385,12 @@
       if (strcmp (pfe->fix_name, fixname) == 0)
         break;
       if (--ct <= 0)
-	{
-	  fprintf (stderr, "fixincludes error:  the `%s' fix is unknown\n",
-		   fixname );
-	  exit (3);
-	}
+        {
+          fprintf (stderr, "fixincludes error:  the `%s' fix is unknown\n",
+                   fixname );
+          exit (3);
+        }
+      pfe++;
     }
 
   buf = load_file_data (stdin);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]