tradcif.y: Move lexptr to top of file.
authorNeil Booth <neilb@earthling.net>
Mon, 4 Dec 2000 22:05:19 +0000 (22:05 +0000)
committerNeil Booth <neil@gcc.gnu.org>
Mon, 4 Dec 2000 22:05:19 +0000 (22:05 +0000)
        * tradcif.y: Move lexptr to top of file.  Add rule to handle
        assertions in conditional expressions.
        * tradcpp.c (parse_answer): Assertions do not need to go to
        end of line in conditional directives.
        (parse_assertion): Get first character of identifiers correct.
        (test_assertion): New function.
        * tradcpp.h (test_assertion): New prototype.

From-SVN: r38011

gcc/ChangeLog
gcc/tradcif.y
gcc/tradcpp.c
gcc/tradcpp.h

index 522d51d1dc49127b93646eb59dd64b3ecd78c907..1941372aa1e0becd55b43503c4a33a079a8e6b8c 100644 (file)
@@ -1,3 +1,13 @@
+2000-12-04  Neil Booth  <neilb@earthling.net>
+
+        * tradcif.y: Move lexptr to top of file.  Add rule to handle
+        assertions in conditional expressions.
+        * tradcpp.c (parse_answer): Assertions do not need to go to
+        end of line in conditional directives.
+        (parse_assertion): Get first character of identifiers correct.
+        (test_assertion): New function.
+        * tradcpp.h (test_assertion): New prototype.
+
 2000-12-01  Rodney Brown  <RodneyBrown@mynd.com>
 
        * config.gcc: Fix typo for UnixWare 7.
index db95563826e0e85db677296a7e43c1325d904eed..19e8b51598c8b8d5b2c01165d240deee69e8c47c 100644 (file)
@@ -36,6 +36,11 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
   static int expression_value;
   static jmp_buf parse_return_error;
+
+  /* During parsing of a C expression, the pointer to the next
+     character is in this variable.  */
+
+  static const char *lexptr;
 %}
 
 %union {
@@ -199,14 +204,11 @@ exp       :       exp '*' exp
        |       NAME
                        { $$.value = 0;
                          $$.unsignedp = 0; }
+       |       '#'     { $$.value =
+                           test_assertion ((unsigned char **) &lexptr); }
        ;
 %%
 \f
-/* During parsing of a C expression, the pointer to the next character
-   is in this variable.  */
-
-static const char *lexptr;
-
 /* Take care of parsing a number (anything that starts with a digit).
    Set yylval and return the token type; update lexptr.
    LEN is the number of characters in it.  */
@@ -389,6 +391,7 @@ yylex ()
   case '{':
   case '}':
   case ',':
+  case '#':
     lexptr++;
     return c;
     
index 51c8aff2b0f273f6d8fefc6c8478e8d8451cc5af..5db2a84086ea96c147fd517785962cfea341d007 100644 (file)
@@ -3057,11 +3057,14 @@ parse_answer (buf, limit, answerp, type)
     buf++;
 
   /* Parentheses are optional here.  */
-  if (buf == limit && (type == T_IF || type == T_UNASSERT))
+  if (buf == limit && type == T_UNASSERT)
     return 0;
 
   if (buf == limit || *buf++ != '(')
     {
+      if (type == T_IF)
+       return 0;
+
       error ("missing '(' after predicate");
       return 1;
     }
@@ -3118,8 +3121,12 @@ parse_assertion (buf, limit, answerp, type)
   unsigned int len;
 
   bp = symname;
-  while (bp < climit && is_idchar[*bp])
-    bp++;
+  if (bp < climit && is_idstart[*bp])
+    {
+      do
+       bp++;
+      while (bp < climit && is_idchar[*bp]);
+    }
   len = bp - symname;
 
   *answerp = 0;
@@ -3130,6 +3137,8 @@ parse_assertion (buf, limit, answerp, type)
       else
        error ("predicate must be an identifier");
     }
+  /* Unfortunately, because of the way we handle #if, we don't avoid
+     macro expansion in answers.  This is not easy to fix.  */
   else if (parse_answer (bp, climit, answerp, type) == 0)
     {
       unsigned char *sym = alloca (len + 1);
@@ -3148,6 +3157,40 @@ parse_assertion (buf, limit, answerp, type)
   return result;
 }
 
+/* Test an assertion within a preprocessor conditional.  Returns zero
+   on error or failure, one on success.  */
+int
+test_assertion (pbuf)
+     unsigned char **pbuf;     /* NUL-terminated.  */
+{
+  unsigned char *buf = *pbuf;
+  unsigned char *limit = buf + strlen ((char *) buf);
+  struct answer *answer;
+  HASHNODE *node;
+  int result = 0;
+
+  node = parse_assertion (buf, limit, &answer, T_IF);
+  if (node)
+    {
+      result = (node->type == T_ASSERT &&
+               (answer == 0 || *find_answer (node, answer) != 0));
+
+      /* Yuk.  We update pbuf to point after the assertion test.
+        First, move past the identifier.  */
+      if (is_space[*buf])
+       buf++;
+      while (is_idchar[*buf])
+       buf++;
+      /* If we have an answer, we need to move past the parentheses.  */
+      if (answer)
+       while (*buf++ != ')')
+         ;
+      *pbuf = buf;
+    }
+
+  return result;
+}
+
 /* Handle a #assert directive.  */
 static void
 do_assert (buf, limit, op)
index 023e642e1fa3de70fbf2f079f80057531872359b..b646939528e76a3ff05eddf02fc80e31aaf88210 100644 (file)
@@ -34,6 +34,7 @@ extern void fancy_abort PARAMS ((int, const char *)) ATTRIBUTE_NORETURN;
 
 extern struct hashnode *lookup PARAMS ((const unsigned char *, int, int));
 extern int parse_c_expression PARAMS ((const char *));  /* in tradcif.y */
+extern int test_assertion PARAMS ((unsigned char **));
 
 /* some external tables of character types */
 extern unsigned char is_idstart[], is_idchar[];