]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
cppfiles.c (stack_include_file): Check for stacked contexts here.
authorNeil Booth <neilb@earthling.net>
Mon, 30 Oct 2000 22:29:00 +0000 (22:29 +0000)
committerNeil Booth <neil@gcc.gnu.org>
Mon, 30 Oct 2000 22:29:00 +0000 (22:29 +0000)
* cppfiles.c (stack_include_file): Check for stacked contexts
here.
* cpphash.h (_cpp_do__Pragma): New prototype.
* cppinit.c (cpp_reader_init): Add _Pragma keyword to hash table.

* cpplex.c (skip_escaped_newlines): Only process trigraphs and
escaped newlines if !(buffer->from_stage3).
(_cpp_lex_token): Warn about missing newlines iff
!buffer->from_stage3.

* cpplib.c (get__Pragma_string, destringize,
_cpp_do__Pragma): New functions.
(run_directive): Set output_line for _Pragma to avoid line
markers in output.  Set from_stage3 and prevent macro expansion
for _Pragma and command-line options.  Check buffer exhaustion.
(cpp_push_buffer): Don't check for stacked macro contexts, as
this is perfectly legitimate for _Pragma.  Move the check to
stack_include_file instead. Set from_stage3 iff buffer is
preprocessed input.

* cpplib.h (struct cpp_buffer): Make warned_cplusplus_comments
unsigned. New boolean from_stage3.
(struct spec_nodes): Add n__Pragma.

* cppmacro.c (enter_macro_context): Flip sense of return value.
(_cpp_get_token): Handle _Pragma operator.

From-SVN: r37147

gcc/ChangeLog
gcc/cppfiles.c
gcc/cpphash.h
gcc/cppinit.c
gcc/cpplex.c
gcc/cpplib.c
gcc/cpplib.h
gcc/cppmacro.c

index 70b91723c1eae10aa9616d096450be27e04bd6e3..0cc78dbcfa4e56a804acb26f65b997bc484a9764 100644 (file)
@@ -1,3 +1,32 @@
+2000-10-30  Neil Booth  <neilb@earthling.net>
+
+       * cppfiles.c (stack_include_file): Check for stacked contexts
+       here.
+       * cpphash.h (_cpp_do__Pragma): New prototype.
+       * cppinit.c (cpp_reader_init): Add _Pragma keyword to hash table.
+
+       * cpplex.c (skip_escaped_newlines): Only process trigraphs and
+       escaped newlines if !(buffer->from_stage3).
+       (_cpp_lex_token): Warn about missing newlines iff
+       !buffer->from_stage3.
+
+       * cpplib.c (get__Pragma_string, destringize,
+       _cpp_do__Pragma): New functions.
+       (run_directive): Set output_line for _Pragma to avoid line
+       markers in output.  Set from_stage3 and prevent macro expansion
+       for _Pragma and command-line options.  Check buffer exhaustion.
+       (cpp_push_buffer): Don't check for stacked macro contexts, as
+       this is perfectly legitimate for _Pragma.  Move the check to
+       stack_include_file instead. Set from_stage3 iff buffer is
+       preprocessed input.
+
+       * cpplib.h (struct cpp_buffer): Make warned_cplusplus_comments
+       unsigned. New boolean from_stage3.
+       (struct spec_nodes): Add n__Pragma.
+
+       * cppmacro.c (enter_macro_context): Flip sense of return value.
+       (_cpp_get_token): Handle _Pragma operator.
+
 2000-10-30  Phil Edwards  <pme@sources.redhat.com>
 
        * gcc.texi:  The C++ standard isn't "draft" anymore.
index f54fe8a155a2c626aacc7535ff0db8d9c4a8037f..1009fa784a1f7c1f7bef2415caad6a6c8a391b62 100644 (file)
@@ -206,6 +206,9 @@ stack_include_file (pfile, inc)
 {
   cpp_buffer *fp;
 
+  if (pfile->context->prev)
+    cpp_ice (pfile, "attempt to push file buffer with contexts stacked");
+
   if (DO_NOT_REREAD (inc))
     return 0;
 
index bba1ba91df33ebe4197f5be91c78236069039e4b..a1c859de66aca3d940013e64fa37fe461f00e4a9 100644 (file)
@@ -203,6 +203,7 @@ extern void _cpp_unlock_pool                PARAMS ((cpp_pool *));
 extern int _cpp_test_assertion PARAMS ((cpp_reader *, int *));
 extern int _cpp_handle_directive PARAMS ((cpp_reader *, int));
 extern void _cpp_define_builtin        PARAMS ((cpp_reader *, const char *));
+extern void _cpp_do__Pragma    PARAMS ((cpp_reader *));
 extern void _cpp_init_stacks   PARAMS ((cpp_reader *));
 extern void _cpp_cleanup_stacks        PARAMS ((cpp_reader *));
 extern void _cpp_init_internal_pragmas PARAMS ((cpp_reader *));
index 20dfc633e3cc7be9613cccc838111f1e040d46f5..512a0ff151fe89d4ec359dd8bcfcc6ad0c10c837 100644 (file)
@@ -487,6 +487,7 @@ cpp_reader_init (pfile)
   s = &pfile->spec_nodes;
   s->n_L                = cpp_lookup (pfile, DSC("L"));
   s->n_defined         = cpp_lookup (pfile, DSC("defined"));
+  s->n__Pragma         = cpp_lookup (pfile, DSC("_Pragma"));
   s->n__STRICT_ANSI__   = cpp_lookup (pfile, DSC("__STRICT_ANSI__"));
   s->n__CHAR_UNSIGNED__ = cpp_lookup (pfile, DSC("__CHAR_UNSIGNED__"));
   s->n__VA_ARGS__       = cpp_lookup (pfile, DSC("__VA_ARGS__"));
index ac8c3c48406f0f6f5c641214537f92a93b39069d..43e090bf6fd01b31a438e790ec759e88773b47e9 100644 (file)
@@ -181,71 +181,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 ();
+           }
+
+         /* 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);
 
-         next1 = *buffer->cur++;
-         if (!_cpp_trigraph_map[next1] || !trigraph_ok (buffer->pfile, next1))
+         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 ();
-       }
+         if (space)
+           cpp_warning (buffer->pfile,
+                        "backslash and newline separated by space");
 
-      /* 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;
+         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;
@@ -863,8 +869,8 @@ _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;
       result->type = CPP_EOF;
index 18b44be305ad65908050d43208d39ee505eb009c..12fa982885639c1cf64206043b4b92a8bad706fa 100644 (file)
@@ -99,6 +99,9 @@ static void do_pragma_once    PARAMS ((cpp_reader *));
 static void do_pragma_poison   PARAMS ((cpp_reader *));
 static void do_pragma_system_header    PARAMS ((cpp_reader *));
 static void do_pragma_dependency       PARAMS ((cpp_reader *));
+static int get__Pragma_string  PARAMS ((cpp_reader *, cpp_token *));
+static unsigned char *destringize      PARAMS ((const cpp_string *,
+                                                unsigned int *));
 static int parse_answer PARAMS ((cpp_reader *, struct answer **, int));
 static cpp_hashnode *parse_assertion PARAMS ((cpp_reader *, struct answer **,
                                              int));
@@ -345,7 +348,7 @@ run_directive (pfile, dir_no, buf, count, name)
      size_t count;
      const char *name;
 {
-  if (cpp_push_buffer (pfile, (const U_CHAR *)buf, count) != NULL)
+  if (cpp_push_buffer (pfile, (const U_CHAR *) buf, count) != NULL)
     {
       const struct directive *dir = &dtable[dir_no];
 
@@ -353,15 +356,27 @@ run_directive (pfile, dir_no, buf, count, name)
        CPP_BUFFER (pfile)->nominal_fname = name;
       else
        CPP_BUFFER (pfile)->nominal_fname = _("<command line>");
-      CPP_BUFFER (pfile)->lineno = (unsigned int)-1;
 
+      /* A kludge to avoid line markers for _Pragma.  */
+      if (dir_no == T_PRAGMA)
+       pfile->lexer_pos.output_line = CPP_BUFFER (pfile)->prev->lineno;
+
+      /* For _Pragma, the text is passed through preprocessing stage 3
+        only, i.e. no trigraphs, no escaped newline removal, and no
+        macro expansion.  Do the same for command-line directives.  */
+      pfile->buffer->from_stage3 = 1;
       pfile->state.in_directive = 1;
       pfile->directive = dir;
+      pfile->state.prevent_expansion++;
       (void) (*dir->handler) (pfile);
+      pfile->state.prevent_expansion--;
       pfile->directive = 0;
       pfile->state.in_directive = 0;
 
       skip_rest_of_line (pfile);
+      if (pfile->buffer->cur != pfile->buffer->rlimit)
+       cpp_error (pfile, "extra text after end of #%s directive",
+                  dtable[dir_no].name);
       cpp_pop_buffer (pfile);
     }
 }
@@ -1069,6 +1084,68 @@ do_pragma_dependency (pfile)
     }
 }
 
+/* Check syntax is "(string-literal)".  Returns 0 on success.  */
+static int
+get__Pragma_string (pfile, string)
+     cpp_reader *pfile;
+     cpp_token *string;
+{
+  cpp_token paren;
+
+  cpp_get_token (pfile, &paren);
+  if (paren.type != CPP_OPEN_PAREN)
+    return 1;
+
+  cpp_get_token (pfile, string);
+  if (string->type != CPP_STRING && string->type != CPP_WSTRING)
+    return 1;
+
+  cpp_get_token (pfile, &paren);
+  return paren.type != CPP_CLOSE_PAREN;
+}
+
+/* Returns a malloced buffer containing a destringized cpp_string by
+   removing the first \ of \" and \\ sequences.  */
+static unsigned char *
+destringize (in, len)
+     const cpp_string *in;
+     unsigned int *len;
+{
+  const unsigned char *src, *limit;
+  unsigned char *dest, *result;
+
+  dest = result = (unsigned char *) xmalloc (in->len);
+  for (src = in->text, limit = src + in->len; src < limit;)
+    {
+      /* We know there is a character following the backslash.  */
+      if (*src == '\\' && (src[1] == '\\' || src[1] == '"'))
+       src++;
+      *dest++ = *src++;
+    }
+
+  *len = dest - result;
+  return result;
+}
+
+void
+_cpp_do__Pragma (pfile)
+     cpp_reader *pfile;
+{
+  cpp_token string;
+  unsigned char *buffer;
+  unsigned int len;
+
+  if (get__Pragma_string (pfile, &string))
+    {
+      cpp_error (pfile, "_Pragma takes a parenthesized string literal");
+      return;
+    }
+
+  buffer = destringize (&string.val.str, &len);
+  run_directive (pfile, T_PRAGMA, (char *) buffer, len, _("<_Pragma>"));
+  free ((PTR) buffer);
+}
+
 /* Just ignore #sccs, on systems where we define it at all.  */
 #ifdef SCCS_DIRECTIVE
 static void
@@ -1626,12 +1703,6 @@ cpp_push_buffer (pfile, buffer, length)
       return NULL;
     }
 
-  if (pfile->context->prev)
-    {
-      cpp_ice (pfile, "buffer pushed with contexts stacked");
-      skip_rest_of_line (pfile);
-    }
-
   new = xobnew (pfile->buffer_ob, cpp_buffer);
   /* Clears, amongst other things, if_stack and mi_cmacro.  */
   memset (new, 0, sizeof (cpp_buffer));
@@ -1641,6 +1712,8 @@ cpp_push_buffer (pfile, buffer, length)
   new->rlimit = buffer + length;
   new->prev = buf;
   new->pfile = pfile;
+  /* Preprocessed files don't do trigraph and escaped newline processing.  */
+  new->from_stage3 = CPP_OPTION (pfile, preprocessed);
   /* No read ahead or extra char initially.  */
   new->read_ahead = EOF;
   new->extra_char = EOF;
index 747ff18bad127862f0c9ead33ade5e36a4b3b13c..de7a1a54caa770c7eb4e70b8661dc30a36e040d0 100644 (file)
@@ -287,7 +287,12 @@ struct cpp_buffer
      The warning happens only for C89 extended mode with -pedantic on,
      or for -Wtraditional, and only once per file (otherwise it would
      be far too noisy).  */
-  char warned_cplusplus_comments;
+  unsigned char warned_cplusplus_comments;
+
+  /* True if we don't process trigraphs and escaped newlines.  True
+     for preprocessed input, command line directives, and _Pragma
+     buffers.  */
+  unsigned char from_stage3;
 };
 
 /* Maximum nesting of cpp_buffers.  We use a static limit, partly for
@@ -509,6 +514,7 @@ struct spec_nodes
 {
   cpp_hashnode *n_L;                   /* L"str" */
   cpp_hashnode *n_defined;             /* defined operator */
+  cpp_hashnode *n__Pragma;             /* _Pragma operator */
   cpp_hashnode *n__STRICT_ANSI__;      /* STDC_0_IN_SYSTEM_HEADERS */
   cpp_hashnode *n__CHAR_UNSIGNED__;    /* plain char is unsigned */
   cpp_hashnode *n__VA_ARGS__;          /* C99 vararg macros */
index 9bd8884956b4bfeba320669fd4f475fdbb74894e..484ce037a55bf7e3241cfbd851d4603d1ad398fb 100644 (file)
@@ -689,7 +689,8 @@ funlike_invocation_p (pfile, node, list)
 
 /* Push the context of a macro onto the context stack.  TOKEN is the
    macro name.  If we can successfully start expanding the macro,
-   TOKEN is replaced with the first token of the expansion.  */
+   TOKEN is replaced with the first token of the expansion, and we
+   return non-zero.  */
 static int
 enter_macro_context (pfile, token)
      cpp_reader *pfile;
@@ -704,7 +705,7 @@ enter_macro_context (pfile, token)
   if (macro->disabled)
     {
       token->flags |= NO_EXPAND;
-      return 1;
+      return 0;
     }
 
   /* Save the position of the outermost macro invocation.  */
@@ -718,7 +719,7 @@ enter_macro_context (pfile, token)
     {
       if (!pfile->context->prev)
        unlock_pools (pfile);
-      return 1;
+      return 0;
     }
 
   /* Now push its context.  */
@@ -740,7 +741,7 @@ enter_macro_context (pfile, token)
   /* Disable the macro within its expansion.  */
   macro->disabled = 1;
 
-  return 0;
+  return 1;
 }
 
 /* Move to the next context.  Create one if there is none.  */
@@ -922,6 +923,7 @@ _cpp_get_token (pfile, token)
      cpp_reader *pfile;
      cpp_token *token;
 {
+ next_token:
   for (;;)
     {
       cpp_context *context = pfile->context;
@@ -959,22 +961,34 @@ _cpp_get_token (pfile, token)
       if (token->flags & PASTE_LEFT)
        paste_all_tokens (pfile, token);
 
-      if (token->type != CPP_NAME
-         || token->val.node->type != NT_MACRO
-         || pfile->state.prevent_expansion
-         || token->flags & NO_EXPAND)
+      if (token->type != CPP_NAME)
        break;
 
-      /* Macros, built-in or not, invalidate controlling macros.  */
-      pfile->mi_state = MI_FAILED;
-
-      if (token->val.node->flags & NODE_BUILTIN)
+      /* Handle macros and the _Pragma operator.  */
+      if (token->val.node->type == NT_MACRO
+         && !pfile->state.prevent_expansion
+         && !(token->flags & NO_EXPAND))
        {
-         builtin_macro (pfile, token);
-         break;
+         /* Macros invalidate controlling macros.  */
+         pfile->mi_state = MI_FAILED;
+
+         if (token->val.node->flags & NODE_BUILTIN)
+           {
+             builtin_macro (pfile, token);
+             break;
+           }
+
+         if (enter_macro_context (pfile, token))
+           continue;
        }
-      else if (enter_macro_context (pfile, token))
+
+      if (token->val.node != pfile->spec_nodes.n__Pragma)
        break;
+
+      /* Invalidate controlling macros.  */
+      pfile->mi_state = MI_FAILED;
+      _cpp_do__Pragma (pfile);
+      goto next_token;
     }
 }