OSDN Git Service

* cpphash.h (struct cpp_buffer): Move saved_flags from cpp_reader.
[pf3gnuchains/gcc-fork.git] / gcc / cpplex.c
index fa737a9..3ff23b4 100644 (file)
@@ -159,9 +159,13 @@ trigraph_ok (pfile, from_char)
                               "trigraph ??%c converted to %c",
                               (int) from_char,
                               (int) _cpp_trigraph_map[from_char]);
-      else
-       cpp_warning_with_line (pfile, buffer->lineno, CPP_BUF_COL (buffer) - 2,
-                              "trigraph ??%c ignored", (int) from_char);
+      else if (buffer->cur != buffer->last_Wtrigraphs)
+       {
+         buffer->last_Wtrigraphs = buffer->cur;
+         cpp_warning_with_line (pfile, buffer->lineno,
+                                CPP_BUF_COL (buffer) - 2,
+                                "trigraph ??%c ignored", (int) from_char);
+       }
     }
 
   return accept;
@@ -181,71 +185,77 @@ trigraph_ok (pfile, from_char)
 
 /* Skips any escaped newlines introduced by NEXT, which is either a
    '?' or a '\\'.  Returns the next character, which will also have
-   been placed in buffer->read_ahead.  */
+   been placed in buffer->read_ahead.  This routine performs
+   preprocessing stages 1 and 2 of the ISO C standard.  */
 static cppchar_t
 skip_escaped_newlines (buffer, next)
      cpp_buffer *buffer;
      cppchar_t next;
 {
-  cppchar_t next1;
-  const unsigned char *saved_cur;
-  int space;
-
-  do
+  /* Only do this if we apply stages 1 and 2.  */
+  if (!buffer->from_stage3)
     {
-      if (buffer->cur == buffer->rlimit)
-       break;
-      
-      SAVE_STATE ();
-      if (next == '?')
+      cppchar_t next1;
+      const unsigned char *saved_cur;
+      int space;
+
+      do
        {
-         next1 = *buffer->cur++;
-         if (next1 != '?' || buffer->cur == buffer->rlimit)
+         if (buffer->cur == buffer->rlimit)
+           break;
+      
+         SAVE_STATE ();
+         if (next == '?')
            {
-             RESTORE_STATE ();
-             break;
+             next1 = *buffer->cur++;
+             if (next1 != '?' || buffer->cur == buffer->rlimit)
+               {
+                 RESTORE_STATE ();
+                 break;
+               }
+
+             next1 = *buffer->cur++;
+             if (!_cpp_trigraph_map[next1]
+                 || !trigraph_ok (buffer->pfile, next1))
+               {
+                 RESTORE_STATE ();
+                 break;
+               }
+
+             /* We have a full trigraph here.  */
+             next = _cpp_trigraph_map[next1];
+             if (next != '\\' || buffer->cur == buffer->rlimit)
+               break;
+             SAVE_STATE ();
            }
 
-         next1 = *buffer->cur++;
-         if (!_cpp_trigraph_map[next1] || !trigraph_ok (buffer->pfile, next1))
+         /* We have a backslash, and room for at least one more character.  */
+         space = 0;
+         do
+           {
+             next1 = *buffer->cur++;
+             if (!is_nvspace (next1))
+               break;
+             space = 1;
+           }
+         while (buffer->cur < buffer->rlimit);
+
+         if (!is_vspace (next1))
            {
              RESTORE_STATE ();
              break;
            }
 
-         /* We have a full trigraph here.  */
-         next = _cpp_trigraph_map[next1];
-         if (next != '\\' || buffer->cur == buffer->rlimit)
-           break;
-         SAVE_STATE ();
-       }
-
-      /* We have a backslash, and room for at least one more character.  */
-      space = 0;
-      do
-       {
-         next1 = *buffer->cur++;
-         if (!is_nvspace (next1))
-           break;
-         space = 1;
-       }
-      while (buffer->cur < buffer->rlimit);
+         if (space && !buffer->pfile->state.lexing_comment)
+           cpp_warning (buffer->pfile,
+                        "backslash and newline separated by space");
 
-      if (!is_vspace (next1))
-       {
-         RESTORE_STATE ();
-         break;
+         next = handle_newline (buffer, next1);
+         if (next == EOF)
+           cpp_pedwarn (buffer->pfile, "backslash-newline at end of file");
        }
-
-      if (space)
-       cpp_warning (buffer->pfile,
-                    "backslash and newline separated by space");
-
-      next = handle_newline (buffer, next1);
-      if (next == EOF)
-       cpp_pedwarn (buffer->pfile, "backslash-newline at end of file");
+      while (next == '\\' || next == '?');
     }
-  while (next == '\\' || next == '?');
 
   buffer->read_ahead = next;
   return next;
@@ -511,10 +521,10 @@ parse_identifier (pfile, c)
        cpp_error (pfile, "attempt to use poisoned \"%s\"", result->name);
 
       /* Constraint 6.10.3.5: __VA_ARGS__ should only appear in the
-        replacement list of a variable-arguments macro.  */
+        replacement list of a variadic macro.  */
       if (result == pfile->spec_nodes.n__VA_ARGS__
          && !pfile->state.va_args_ok)
-       cpp_pedwarn (pfile, "__VA_ARGS__ can only appear in the expansion of a C99 variable-argument macro");
+       cpp_pedwarn (pfile, "__VA_ARGS__ can only appear in the expansion of a C99 variadic macro");
     }
 
   return result;
@@ -529,7 +539,7 @@ parse_number (pfile, number, c, leading_period)
      int leading_period;
 {
   cpp_buffer *buffer = pfile->buffer;
-  cpp_pool *pool = pfile->string_pool;
+  cpp_pool *pool = &pfile->ident_pool;
   unsigned char *dest, *limit;
 
   dest = POOL_FRONT (pool);
@@ -608,7 +618,7 @@ unescaped_terminator_p (pfile, dest)
   if (pfile->state.angled_headers)
     return 1;
 
-  start = POOL_FRONT (pfile->string_pool);
+  start = POOL_FRONT (&pfile->ident_pool);
 
   /* An odd number of consecutive backslashes represents an escaped
      terminator.  */
@@ -630,7 +640,7 @@ parse_string (pfile, token, terminator)
      cppchar_t terminator;
 {
   cpp_buffer *buffer = pfile->buffer;
-  cpp_pool *pool = pfile->string_pool;
+  cpp_pool *pool = &pfile->ident_pool;
   unsigned char *dest, *limit;
   cppchar_t c;
   unsigned int nulls = 0;
@@ -663,14 +673,14 @@ parse_string (pfile, token, terminator)
          /* In assembly language, silently terminate string and
             character literals at end of line.  This is a kludge
             around not knowing where comments are.  */
-         if (CPP_OPTION (pfile, lang_asm) && terminator != '>')
+         if (CPP_OPTION (pfile, lang) == CLK_ASM && terminator != '>')
            break;
 
          /* Character constants and header names may not extend over
             multiple lines.  In Standard C, neither may strings.
             Unfortunately, we accept multiline strings as an
-            extension.  */
-         if (terminator != '"')
+            extension, except in #include family directives.  */
+         if (terminator != '"' || pfile->state.angled_headers)
            {
              unterminated (pfile, terminator);
              break;
@@ -724,7 +734,11 @@ save_comment (pfile, token, from)
   unsigned int len;
   
   len = pfile->buffer->cur - from + 1; /* + 1 for the initial '/'.  */
-  buffer = _cpp_pool_alloc (pfile->string_pool, len);
+  /* C++ comments probably (not definitely) have moved past a new
+     line, which we don't want to save in the comment.  */
+  if (pfile->buffer->read_ahead != EOF)
+    len--;
+  buffer = _cpp_pool_alloc (&pfile->ident_pool, len);
   
   token->type = CPP_COMMENT;
   token->val.str.len = len;
@@ -834,13 +848,17 @@ _cpp_lex_token (pfile, result)
      cpp_token *result;
 {
   cppchar_t c;
-  cpp_buffer *buffer = pfile->buffer;
+  cpp_buffer *buffer;
   const unsigned char *comment_start;
-  unsigned char was_skip_newlines = pfile->state.skip_newlines;
-  unsigned char newline_in_args = 0;
-
-  pfile->state.skip_newlines = 0;
-  result->flags = 0;
+  unsigned char bol;
+
+ skip:
+  bol = pfile->state.next_bol;
+ done_directive:
+  buffer = pfile->buffer;
+  pfile->state.next_bol = 0;
+  result->flags = buffer->saved_flags;
+  buffer->saved_flags = 0;
  next_char:
   pfile->lexer_pos.line = buffer->lineno;
  next_char2:
@@ -859,12 +877,14 @@ _cpp_lex_token (pfile, result)
     {
     case EOF:
       /* Non-empty files should end in a newline.  Ignore for command
-        line - we get e.g. -A options with no trailing \n.  */
-      if (pfile->lexer_pos.col != 0 && pfile->done_initializing)
+        line and _Pragma buffers.  */
+      if (pfile->lexer_pos.col != 0 && !buffer->from_stage3)
        cpp_pedwarn (pfile, "no newline at end of file");
-      pfile->state.skip_newlines = 1;
+      pfile->state.next_bol = 1;
+      pfile->skipping = 0;     /* In case missing #endif.  */
       result->type = CPP_EOF;
-      break;
+      /* Don't do MI optimisation.  */
+      return;
 
     case ' ': case '\t': case '\f': case '\v': case '\0':
       skip_whitespace (pfile, c);
@@ -872,36 +892,24 @@ _cpp_lex_token (pfile, result)
       goto next_char2;
 
     case '\n': case '\r':
-      /* Don't let directives spill over to the next line.  */
-      if (pfile->state.in_directive)
-       buffer->read_ahead = c;
-      else
+      if (!pfile->state.in_directive)
        {
          handle_newline (buffer, c);
-
+         bol = 1;
          pfile->lexer_pos.output_line = buffer->lineno;
-
-         /* Skip newlines in macro arguments (except in directives).  */
-         if (pfile->state.parsing_args)
-           {
-             /* Set the whitespace flag.   */
-             newline_in_args = 1;
-             result->flags |= PREV_WHITE;
-             goto next_char;
-           }
-
-         if (was_skip_newlines)
-           {
-             /* Clear any whitespace flag.   */
-             result->flags &= ~PREV_WHITE;
-             goto next_char;
-           }
+         /* This is a new line, so clear any white space flag.
+            Newlines in arguments are white space (6.10.3.10);
+            parse_arg takes care of that.  */
+         result->flags &= ~(PREV_WHITE | AVOID_LPASTE);
+         goto next_char;
        }
 
-      /* Next we're at BOL, so skip new lines.  */
-      pfile->state.skip_newlines = 1;
+      /* Don't let directives spill over to the next line.  */
+      buffer->read_ahead = c;
+      pfile->state.next_bol = 1;
       result->type = CPP_EOF;
-      break;
+      /* Don't break; pfile->skipping might be true.  */
+      return;
 
     case '?':
     case '\\':
@@ -921,7 +929,7 @@ _cpp_lex_token (pfile, result)
        result->type = CPP_QUERY;
        buffer->read_ahead = EOF;
        if (c == '\\')
-         result->type = CPP_BACKSLASH;
+         goto random_char;
        else if (c != '?')
          goto do_switch;
       }
@@ -1000,11 +1008,9 @@ _cpp_lex_token (pfile, result)
              && !CPP_IN_SYSTEM_HEADER (pfile))
            break;
 
-         /* We silently allow C++ comments in system headers,
-            irrespective of conformance mode, because lots of
-            broken systems do that and trying to clean it up in
-            fixincludes is a nightmare.  */
-         if (CPP_OPTION (pfile, c89) && CPP_PEDANTIC (pfile)
+         /* Warn about comments only if pedantically GNUC89, and not
+            in system headers.  */
+         if (CPP_OPTION (pfile, lang) == CLK_GNUC89 && CPP_PEDANTIC (pfile)
              && ! buffer->warned_cplusplus_comments)
            {
              cpp_pedwarn (pfile,
@@ -1030,7 +1036,8 @@ _cpp_lex_token (pfile, result)
 
       /* Save the comment as a token in its own right.  */
       save_comment (pfile, result, comment_start);
-      break;
+      /* Don't do MI optimisation.  */
+      return;
 
     case '<':
       if (pfile->state.angled_headers)
@@ -1150,19 +1157,54 @@ _cpp_lex_token (pfile, result)
       break;
          
     case '#':
-      if (get_effective_char (buffer) == '#')
-       ACCEPT_CHAR (CPP_PASTE);
+      c = buffer->extra_char;  /* Can be set by error condition below.  */
+      if (c != EOF)
+       {
+         buffer->read_ahead = c;
+         buffer->extra_char = EOF;
+       }
       else
+       c = get_effective_char (buffer);
+
+      if (c == '#')
+       {
+         ACCEPT_CHAR (CPP_PASTE);
+         break;
+       }
+
+      result->type = CPP_HASH;
+    do_hash:
+      if (bol)
        {
-         result->type = CPP_HASH;
-       do_hash:
-         /* CPP_DHASH is the hash introducing a directive.  */
-         if (was_skip_newlines || newline_in_args)
+         if (pfile->state.parsing_args)
            {
-             result->type = CPP_DHASH;
+             /* 6.10.3 paragraph 11: If there are sequences of
+                preprocessing tokens within the list of arguments that
+                would otherwise act as preprocessing directives, the
+                behavior is undefined.
+
+                This implementation will report a hard error, terminate
+                the macro invocation, and proceed to process the
+                directive.  */
+             cpp_error (pfile,
+                        "directives may not be used inside a macro argument");
+
+             /* Put a '#' in lookahead, return CPP_EOF for parse_arg.  */
+             buffer->extra_char = buffer->read_ahead;
+             buffer->read_ahead = '#';
+             pfile->state.next_bol = 1;
+             result->type = CPP_EOF;
+
              /* Get whitespace right - newline_in_args sets it.  */
              if (pfile->lexer_pos.col == 1)
-               result->flags &= ~PREV_WHITE;
+               result->flags &= ~(PREV_WHITE | AVOID_LPASTE);
+           }
+         else
+           {
+             /* This is the hash introducing a directive.  */
+             if (_cpp_handle_directive (pfile, result->flags & PREV_WHITE))
+               goto done_directive; /* bol still 1.  */
+             /* This is in fact an assembler #.  */
            }
        }
       break;
@@ -1231,9 +1273,16 @@ _cpp_lex_token (pfile, result)
     random_char:
     default:
       result->type = CPP_OTHER;
-      result->val.aux = c;
+      result->val.c = c;
       break;
     }
+
+  if (pfile->skipping)
+    goto skip;
+
+  /* If not in a directive, this token invalidates controlling macros.  */
+  if (!pfile->state.in_directive)
+    pfile->mi_state = MI_FAILED;
 }
 
 /* An upper bound on the number of bytes needed to spell a token,
@@ -1311,7 +1360,7 @@ cpp_spell_token (pfile, token, buffer)
       break;
 
     case SPELL_CHAR:
-      *buffer++ = token->val.aux;
+      *buffer++ = token->val.c;
       break;
 
     case SPELL_NONE:
@@ -1330,7 +1379,7 @@ cpp_token_as_text (pfile, token)
      const cpp_token *token;
 {
   unsigned int len = cpp_token_len (token);
-  unsigned char *start = _cpp_pool_alloc (&pfile->temp_string_pool, len), *end;
+  unsigned char *start = _cpp_pool_alloc (&pfile->ident_pool, len), *end;
 
   end = cpp_spell_token (pfile, token, start);
   end[0] = '\0';
@@ -1400,7 +1449,7 @@ cpp_output_token (token, fp)
       break;
 
     case SPELL_CHAR:
-      putc (token->val.aux, fp);
+      putc (token->val.c, fp);
       break;
 
     case SPELL_NONE:
@@ -1421,9 +1470,9 @@ _cpp_equiv_tokens (a, b)
       case SPELL_OPERATOR:
        return 1;
       case SPELL_CHAR:
-       return a->val.aux == b->val.aux; /* Character.  */
+       return a->val.c == b->val.c; /* Character.  */
       case SPELL_NONE:
-       return (a->type != CPP_MACRO_ARG || a->val.aux == b->val.aux);
+       return (a->type != CPP_MACRO_ARG || a->val.arg_no == b->val.arg_no);
       case SPELL_IDENT:
        return a->val.node == b->val.node;
       case SPELL_STRING:
@@ -1555,7 +1604,7 @@ cpp_can_paste (pfile, token1, token2, digraph)
       break;
 
     case CPP_OTHER:
-      if (CPP_OPTION (pfile, objc) && token1->val.aux == '@')
+      if (CPP_OPTION (pfile, objc) && token1->val.c == '@')
        {
          if (b == CPP_NAME)    return CPP_NAME;
          if (b == CPP_STRING)  return CPP_OSTRING;
@@ -1608,7 +1657,7 @@ cpp_avoid_paste (pfile, token1, token2)
     case CPP_OR:       return c == '|';
     case CPP_COLON:    return c == ':' || c == '>';
     case CPP_DEREF:    return c == '*';
-    case CPP_DOT:      return c == '.' || c == '%';
+    case CPP_DOT:      return c == '.' || c == '%' || b == CPP_NUMBER;
     case CPP_HASH:     return c == '#' || c == '%'; /* Digraph form.  */
     case CPP_NAME:     return ((b == CPP_NUMBER
                                 && name_p (pfile, &token2->val.str))
@@ -1617,7 +1666,7 @@ cpp_avoid_paste (pfile, token1, token2)
     case CPP_NUMBER:   return (b == CPP_NUMBER || b == CPP_NAME
                                || c == '.' || c == '+' || c == '-');
     case CPP_OTHER:    return (CPP_OPTION (pfile, objc)
-                               && token1->val.aux == '@'
+                               && token1->val.c == '@'
                                && (b == CPP_NAME || b == CPP_STRING));
     default:           break;
     }
@@ -1634,12 +1683,12 @@ cpp_output_line (pfile, fp)
 {
   cpp_token token;
 
-  _cpp_get_token (pfile, &token);
+  cpp_get_token (pfile, &token);
   token.flags &= ~PREV_WHITE;
   while (token.type != CPP_EOF)
     {
       cpp_output_token (&token, fp);
-      _cpp_get_token (pfile, &token);
+      cpp_get_token (pfile, &token);
     }
 
   putc ('\n', fp);