OSDN Git Service

* directives.c (cpp_handle_deferred_pragma): Save, clear and restore
[pf3gnuchains/gcc-fork.git] / libcpp / directives.c
index f9ff2ce..b60b7bc 100644 (file)
@@ -23,16 +23,9 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "system.h"
 #include "cpplib.h"
 #include "internal.h"
+#include "mkdeps.h"
 #include "obstack.h"
 
-/* Chained list of answers to an assertion.  */
-struct answer
-{
-  struct answer *next;
-  unsigned int count;
-  cpp_token first[1];
-};
-
 /* Stack of conditionals currently in progress
    (including both successful and failing conditionals).  */
 struct if_stack
@@ -51,7 +44,8 @@ struct pragma_entry
 {
   struct pragma_entry *next;
   const cpp_hashnode *pragma;  /* Name and length.  */
-  int is_nspace;
+  bool is_nspace;
+  bool is_internal;
   union {
     pragma_cb handler;
     struct pragma_entry *space;
@@ -113,7 +107,10 @@ static struct pragma_entry *lookup_pragma_entry (struct pragma_entry *,
 static struct pragma_entry *insert_pragma_entry (cpp_reader *,
                                                  struct pragma_entry **,
                                                  const cpp_hashnode *,
-                                                 pragma_cb);
+                                                 pragma_cb,
+                                                bool);
+static void register_pragma (cpp_reader *, const char *, const char *,
+                            pragma_cb, bool);
 static int count_registered_pragmas (struct pragma_entry *);
 static char ** save_registered_pragmas (struct pragma_entry *, char **);
 static char ** restore_registered_pragmas (cpp_reader *, struct pragma_entry *,
@@ -226,6 +223,7 @@ start_directive (cpp_reader *pfile)
   /* Setup in-directive state.  */
   pfile->state.in_directive = 1;
   pfile->state.save_comments = 0;
+  pfile->directive_result.type = CPP_PADDING;
 
   /* Some handlers need the position of the # for diagnostics.  */
   pfile->directive_line = pfile->line_table->highest_line;
@@ -336,8 +334,12 @@ _cpp_handle_directive (cpp_reader *pfile, int indented)
   const directive *dir = 0;
   const cpp_token *dname;
   bool was_parsing_args = pfile->state.parsing_args;
+  bool was_discarding_output = pfile->state.discarding_output;
   int skip = 1;
 
+  if (was_discarding_output)
+    pfile->state.prevent_expansion = 0;
+
   if (was_parsing_args)
     {
       if (CPP_OPTION (pfile, pedantic))
@@ -432,6 +434,8 @@ _cpp_handle_directive (cpp_reader *pfile, int indented)
       pfile->state.parsing_args = 2;
       pfile->state.prevent_expansion = 1;
     }
+  if (was_discarding_output)
+    pfile->state.prevent_expansion = 1;
   return skip;
 }
 
@@ -443,7 +447,7 @@ run_directive (cpp_reader *pfile, int dir_no, const char *buf, size_t count)
   cpp_push_buffer (pfile, (const uchar *) buf, count,
                   /* from_stage3 */ true);
   /* Disgusting hack.  */
-  if (dir_no == T_PRAGMA)
+  if (dir_no == T_PRAGMA && pfile->buffer->prev)
     pfile->buffer->file = pfile->buffer->prev->file;
   start_directive (pfile);
 
@@ -549,30 +553,13 @@ do_undef (cpp_reader *pfile)
 /* Undefine a single macro/assertion/whatever.  */
 
 static int
-undefine_macros (cpp_reader *pfile, cpp_hashnode *h,
+undefine_macros (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *h,
                 void *data_p ATTRIBUTE_UNUSED)
 {
-  switch (h->type)
-    {
-    case NT_VOID:
-      break;
-
-    case NT_MACRO:
-      if (pfile->cb.undef)
-        (*pfile->cb.undef) (pfile, pfile->directive_line, h);
-
-      if (CPP_OPTION (pfile, warn_unused_macros))
-        _cpp_warn_if_unused_macro (pfile, h, NULL);
-
-      /* And fall through....  */
-    case NT_ASSERTION:
-      _cpp_free_definition (h);
-      break;
-
-    default:
-      abort ();
-    }
-  h->flags &= ~NODE_POISONED;
+  /* Body of _cpp_free_definition inlined here for speed.
+     Macros and assertions no longer have anything to free.  */
+  h->type = NT_VOID;
+  h->flags &= ~(NODE_POISONED|NODE_BUILTIN|NODE_DISABLED);
   return 1;
 }
 
@@ -972,10 +959,12 @@ lookup_pragma_entry (struct pragma_entry *chain, const cpp_hashnode *pragma)
 
 /* Create and insert a pragma entry for NAME at the beginning of a
    singly-linked CHAIN.  If handler is NULL, it is a namespace,
-   otherwise it is a pragma and its handler.  */
+   otherwise it is a pragma and its handler.  If INTERNAL is true
+   this pragma is being inserted by libcpp itself. */
 static struct pragma_entry *
 insert_pragma_entry (cpp_reader *pfile, struct pragma_entry **chain,
-                    const cpp_hashnode *pragma, pragma_cb handler)
+                    const cpp_hashnode *pragma, pragma_cb handler,
+                    bool internal)
 {
   struct pragma_entry *new;
 
@@ -993,6 +982,7 @@ insert_pragma_entry (cpp_reader *pfile, struct pragma_entry **chain,
       new->u.space = NULL;
     }
 
+  new->is_internal = internal;
   new->next = *chain;
   *chain = new;
   return new;
@@ -1000,10 +990,12 @@ insert_pragma_entry (cpp_reader *pfile, struct pragma_entry **chain,
 
 /* Register a pragma NAME in namespace SPACE.  If SPACE is null, it
    goes in the global namespace.  HANDLER is the handler it will call,
-   which must be non-NULL.  */
-void
-cpp_register_pragma (cpp_reader *pfile, const char *space, const char *name,
-                    pragma_cb handler)
+   which must be non-NULL.  INTERNAL is true if this is a pragma
+   registered by cpplib itself, false if it is registered via
+   cpp_register_pragma */
+static void
+register_pragma (cpp_reader *pfile, const char *space, const char *name,
+                pragma_cb handler, bool internal)
 {
   struct pragma_entry **chain = &pfile->pragmas;
   struct pragma_entry *entry;
@@ -1017,7 +1009,7 @@ cpp_register_pragma (cpp_reader *pfile, const char *space, const char *name,
       node = cpp_lookup (pfile, U space, strlen (space));
       entry = lookup_pragma_entry (*chain, node);
       if (!entry)
-       entry = insert_pragma_entry (pfile, chain, node, NULL);
+       entry = insert_pragma_entry (pfile, chain, node, NULL, internal);
       else if (!entry->is_nspace)
        goto clash;
       chain = &entry->u.space;
@@ -1040,7 +1032,17 @@ cpp_register_pragma (cpp_reader *pfile, const char *space, const char *name,
        cpp_error (pfile, CPP_DL_ICE, "#pragma %s is already registered", name);
     }
   else
-    insert_pragma_entry (pfile, chain, node, handler);
+    insert_pragma_entry (pfile, chain, node, handler, internal);
+}
+
+/* Register a pragma NAME in namespace SPACE.  If SPACE is null, it
+   goes in the global namespace.  HANDLER is the handler it will call,
+   which must be non-NULL.  This function is exported from libcpp. */
+void
+cpp_register_pragma (cpp_reader *pfile, const char *space, const char *name,
+                    pragma_cb handler)
+{
+  register_pragma (pfile, space, name, handler, false);
 }
 
 /* Register the pragmas the preprocessor itself handles.  */
@@ -1048,12 +1050,12 @@ void
 _cpp_init_internal_pragmas (cpp_reader *pfile)
 {
   /* Pragmas in the global namespace.  */
-  cpp_register_pragma (pfile, 0, "once", do_pragma_once);
+  register_pragma (pfile, 0, "once", do_pragma_once, true);
 
   /* New GCC-specific pragmas should be put in the GCC namespace.  */
-  cpp_register_pragma (pfile, "GCC", "poison", do_pragma_poison);
-  cpp_register_pragma (pfile, "GCC", "system_header", do_pragma_system_header);
-  cpp_register_pragma (pfile, "GCC", "dependency", do_pragma_dependency);
+  register_pragma (pfile, "GCC", "poison", do_pragma_poison, true);
+  register_pragma (pfile, "GCC", "system_header", do_pragma_system_header, true);
+  register_pragma (pfile, "GCC", "dependency", do_pragma_dependency, true);
 }
 
 /* Return the number of registered pragmas in PE.  */
@@ -1095,7 +1097,7 @@ char **
 _cpp_save_pragma_names (cpp_reader *pfile)
 {
   int ct = count_registered_pragmas (pfile->pragmas);
-  char **result = xnewvec (char *, ct);
+  char **result = XNEWVEC (char *, ct);
   (void) save_registered_pragmas (pfile->pragmas, result);
   return result;
 }
@@ -1131,7 +1133,11 @@ _cpp_restore_pragma_names (cpp_reader *pfile, char **saved)
    front end.  C99 defines three pragmas and says that no macro
    expansion is to be performed on them; whether or not macro
    expansion happens for other pragmas is implementation defined.
-   This implementation never macro-expands the text after #pragma.  */
+   This implementation never macro-expands the text after #pragma.
+
+   The library user has the option of deferring execution of
+   #pragmas not handled by cpplib, in which case they are converted
+   to CPP_PRAGMA tokens and inserted into the output stream.  */
 static void
 do_pragma (cpp_reader *pfile)
 {
@@ -1139,6 +1145,11 @@ do_pragma (cpp_reader *pfile)
   const cpp_token *token, *pragma_token = pfile->cur_token;
   unsigned int count = 1;
 
+  /* Save the current position so that defer_pragmas mode can
+     copy the entire current line to a string.  It will not work
+     to use _cpp_backup_tokens as that does not reverse buffer->cur.  */
+  const uchar *line_start = CPP_BUFFER (pfile)->cur;
+
   pfile->state.prevent_expansion++;
 
   token = cpp_get_token (pfile);
@@ -1156,7 +1167,7 @@ do_pragma (cpp_reader *pfile)
        }
     }
 
-  if (p)
+  if (p && (p->is_internal || !CPP_OPTION (pfile, defer_pragmas)))
     {
       /* Since the handler below doesn't get the line number, that it
         might need for diagnostics, make sure it has the right
@@ -1165,6 +1176,29 @@ do_pragma (cpp_reader *pfile)
        (*pfile->cb.line_change) (pfile, pragma_token, false);
       (*p->u.handler) (pfile);
     }
+  else if (CPP_OPTION (pfile, defer_pragmas))
+    {
+      /* Squirrel away the pragma text.  Pragmas are newline-terminated. */
+      const uchar *line_end;
+      uchar *s;
+      cpp_string body;
+      cpp_token *ptok;
+
+      line_end = ustrchr (line_start, '\n');
+
+      body.len = (line_end - line_start) + 1;
+      s = _cpp_unaligned_alloc (pfile, body.len + 1);
+      memcpy (s, line_start, body.len);
+      s[body.len] = '\0';
+      body.text = s;
+
+      /* Create a CPP_PRAGMA token.  */
+      ptok = &pfile->directive_result;
+      ptok->src_loc = pragma_token->src_loc;
+      ptok->type = CPP_PRAGMA;
+      ptok->flags = pragma_token->flags | NO_EXPAND;
+      ptok->val.str = body;
+    }
   else if (pfile->cb.def_pragma)
     {
       _cpp_backup_tokens (pfile, count);
@@ -1336,11 +1370,11 @@ destringize_and_run (cpp_reader *pfile, const cpp_string *in)
     cpp_token *saved_cur_token = pfile->cur_token;
     tokenrun *saved_cur_run = pfile->cur_run;
 
-    pfile->context = xnew (cpp_context);
+    pfile->context = XNEW (cpp_context);
     pfile->context->macro = 0;
     pfile->context->prev = 0;
     run_directive (pfile, T_PRAGMA, result, dest - result);
-    free (pfile->context);
+    XDELETE (pfile->context);
     pfile->context = saved_context;
     pfile->cur_token = saved_cur_token;
     pfile->cur_run = saved_cur_run;
@@ -1368,6 +1402,7 @@ void
 _cpp_do__Pragma (cpp_reader *pfile)
 {
   const cpp_token *string = get__Pragma_string (pfile);
+  pfile->directive_result.type = CPP_PADDING;
 
   if (string)
     destringize_and_run (pfile, &string->val.str);
@@ -1376,6 +1411,33 @@ _cpp_do__Pragma (cpp_reader *pfile)
               "_Pragma takes a parenthesized string literal");
 }
 
+/* Handle a pragma that the front end deferred until now. */
+void
+cpp_handle_deferred_pragma (cpp_reader *pfile, const cpp_string *s)
+{
+  cpp_context *saved_context = pfile->context;
+  cpp_token *saved_cur_token = pfile->cur_token;
+  tokenrun *saved_cur_run = pfile->cur_run;
+  bool saved_defer_pragmas = CPP_OPTION (pfile, defer_pragmas);
+  void (*saved_line_change) (cpp_reader *, const cpp_token *, int)
+    = pfile->cb.line_change;
+
+  pfile->context = XNEW (cpp_context);
+  pfile->context->macro = 0;
+  pfile->context->prev = 0;
+  pfile->cb.line_change = NULL;
+  CPP_OPTION (pfile, defer_pragmas) = false;
+
+  run_directive (pfile, T_PRAGMA, s->text, s->len);
+
+  XDELETE (pfile->context);
+  pfile->context = saved_context;
+  pfile->cur_token = saved_cur_token;
+  pfile->cur_run = saved_cur_run;
+  pfile->cb.line_change = saved_line_change;
+  CPP_OPTION (pfile, defer_pragmas) = saved_defer_pragmas;
+}
+
 /* Ignore #sccs on all systems.  */
 static void
 do_sccs (cpp_reader *pfile ATTRIBUTE_UNUSED)
@@ -1550,7 +1612,7 @@ push_conditional (cpp_reader *pfile, int skip, int type,
   struct if_stack *ifs;
   cpp_buffer *buffer = pfile->buffer;
 
-  ifs = xobnew (&pfile->buffer_ob, struct if_stack);
+  ifs = XOBNEW (&pfile->buffer_ob, struct if_stack);
   ifs->line = pfile->directive_line;
   ifs->next = buffer->if_stack;
   ifs->skip_elses = pfile->state.skipping || !skip;
@@ -1737,6 +1799,8 @@ do_assert (cpp_reader *pfile)
   node = parse_assertion (pfile, &new_answer, T_ASSERT);
   if (node)
     {
+      size_t answer_size;
+
       /* Place the new answer in the answer list.  First check there
          is not a duplicate.  */
       new_answer->next = 0;
@@ -1751,11 +1815,20 @@ do_assert (cpp_reader *pfile)
          new_answer->next = node->value.answers;
        }
 
+      answer_size = sizeof (struct answer) + ((new_answer->count - 1)
+                                             * sizeof (cpp_token));
+      /* Commit or allocate storage for the object.  */
+      if (pfile->hash_table->alloc_subobject)
+       {
+         struct answer *temp_answer = new_answer;
+         new_answer = pfile->hash_table->alloc_subobject (answer_size);
+         memcpy (new_answer, temp_answer, answer_size);
+       }
+      else
+       BUFF_FRONT (pfile->a_buff) += answer_size;
+
       node->type = NT_ASSERTION;
       node->value.answers = new_answer;
-      BUFF_FRONT (pfile->a_buff) += (sizeof (struct answer)
-                                    + (new_answer->count - 1)
-                                    * sizeof (cpp_token));
       check_eol (pfile);
     }
 }
@@ -1913,6 +1986,15 @@ cpp_set_callbacks (cpp_reader *pfile, cpp_callbacks *cb)
   pfile->cb = *cb;
 }
 
+/* The dependencies structure.  (Creates one if it hasn't already been.)  */
+struct deps *
+cpp_get_deps (cpp_reader *pfile)
+{
+  if (!pfile->deps)
+    pfile->deps = deps_init ();
+  return pfile->deps;
+}
+
 /* Push a new buffer on the buffer stack.  Returns the new buffer; it
    doesn't fail.  It does not generate a file change call back; that
    is the responsibility of the caller.  */
@@ -1920,7 +2002,7 @@ cpp_buffer *
 cpp_push_buffer (cpp_reader *pfile, const uchar *buffer, size_t len,
                 int from_stage3)
 {
-  cpp_buffer *new = xobnew (&pfile->buffer_ob, cpp_buffer);
+  cpp_buffer *new = XOBNEW (&pfile->buffer_ob, cpp_buffer);
 
   /* Clears, amongst other things, if_stack and mi_cmacro.  */
   memset (new, 0, sizeof (cpp_buffer));