Index: gcc/gcc/plugin.def
===================================================================
--- gcc.orig/gcc/plugin.def
+++ gcc/gcc/plugin.def
@@ -89,6 +89,37 @@ DEFEVENT (PLUGIN_EARLY_GIMPLE_PASSES_END
 /* Called when a pass is first instantiated.  */
 DEFEVENT (PLUGIN_NEW_PASS)
 
+/* Called when a cpp token is extracted.  */
+DEFEVENT (PLUGIN_CPP_TOKEN)
+
+/* Called when a c token is extracted.  */
+DEFEVENT (PLUGIN_C_TOKEN)
+
+/* An extern declaration (file-scope) is encounted. */
+DEFEVENT (PLUGIN_EXTERN_DECL)
+
+/* Cooperate PLUGIN_EXTERN_FUNC to parse a function with old-style parameter
+ * declaration. */
+DEFEVENT (PLUGIN_EXTERN_FUNC_OLD_PARAM)
+
+/* Called when an extern function definition is parsed. */
+DEFEVENT (PLUGIN_EXTERN_FUNC)
+
+/* Called when an extern variable definition is parsed. */
+DEFEVENT (PLUGIN_EXTERN_VAR)
+
+/* An extern declaration specifier definition is parsed. */
+DEFEVENT (PLUGIN_EXTERN_DECLSPECS)
+
+/* A function is called. */
+DEFEVENT (PLUGIN_CALL_FUNCTION)
+
+/* Called when an enumerator is parsed. */
+DEFEVENT (PLUGIN_ENUMERATOR)
+
+/* Function pointer is assigned. */
+DEFEVENT (PLUGIN_FUNP_ALIAS)
+
 /* After the hard-coded events above, plugins can dynamically allocate events
    at run time.
    PLUGIN_EVENT_FIRST_DYNAMIC only appears as last enum element.  */
Index: gcc/gcc/c-family/c-lex.c
===================================================================
--- gcc.orig/gcc/c-family/c-lex.c
+++ gcc/gcc/c-family/c-lex.c
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3.  
 #include "splay-tree.h"
 #include "debug.h"
 #include "target.h"
+#include "plugin.h"
 
 /* We may keep statistics about how long which files took to compile.  */
 static int header_time, body_time;
@@ -362,6 +363,7 @@ c_lex_with_flags (tree *value, location_
 	    case CPP_STRING32:
 	    case CPP_UTF8STRING:
 	      type = lex_string (tok, value, true, true);
+		  tok = NULL;
 	      break;
 
 	    case CPP_NAME:
@@ -431,6 +433,7 @@ c_lex_with_flags (tree *value, location_
 	{
 	  type = lex_string (tok, value, false,
 			     (lex_flags & C_LEX_STRING_NO_TRANSLATE) == 0);
+	  tok = NULL;
 	  break;
 	}
       *value = build_string (tok->val.str.len, (const char *) tok->val.str.text);
@@ -465,6 +468,7 @@ c_lex_with_flags (tree *value, location_
     }
 
   timevar_pop (TV_CPP);
+  invoke_plugin_callbacks (PLUGIN_CPP_TOKEN, tok);
 
   return type;
 }
Index: gcc/gcc/c-parser.c
===================================================================
--- gcc.orig/gcc/c-parser.c
+++ gcc/gcc/c-parser.c
@@ -386,6 +386,7 @@ c_lex_one_token (c_parser *parser, c_tok
       break;
     }
   timevar_pop (TV_LEX);
+  invoke_plugin_callbacks (PLUGIN_C_TOKEN, token);
 }
 
 /* Return a pointer to the next token from PARSER, reading it in if
@@ -1329,6 +1330,7 @@ c_parser_external_declaration (c_parser 
 	 an @interface or @protocol with prefix attributes).  We can
 	 only tell which after parsing the declaration specifiers, if
 	 any, and the first declarator.  */
+      invoke_plugin_callbacks (PLUGIN_EXTERN_DECL, NULL);
       c_parser_declaration_or_fndef (parser, true, true, true, false, true, NULL);
       break;
     }
@@ -1457,6 +1459,15 @@ c_parser_declaration_or_fndef (c_parser 
       return;
     }
   finish_declspecs (specs);
+  {
+    void* pair[2]; pair[0] = specs; pair[1] = (void*) parser->tokens_avail;
+    tree tmp = specs->type;
+    /* mark external struct/union. */
+    if (TREE_CODE (tmp) == RECORD_TYPE || TREE_CODE (tmp) == UNION_TYPE)
+      TYPE_FILE_SCOPE (tmp) = true;
+    if (!nested)
+      invoke_plugin_callbacks (PLUGIN_EXTERN_DECLSPECS, pair);
+  }
   if (c_parser_next_token_is (parser, CPP_SEMICOLON))
     {
       if (empty_ok)
@@ -1590,6 +1601,11 @@ c_parser_declaration_or_fndef (c_parser 
 	{
 	  tree asm_name = NULL_TREE;
 	  tree postfix_attrs = NULL_TREE;
+	  {
+	    void* pair[2]; pair[0] = specs; pair[1] = declarator;
+        if (!nested)
+          invoke_plugin_callbacks (PLUGIN_EXTERN_VAR, pair);
+	  }
 	  if (!diagnosed_no_specs && !specs->declspecs_seen_p)
 	    {
 	      diagnosed_no_specs = true;
@@ -1618,6 +1634,8 @@ c_parser_declaration_or_fndef (c_parser 
 	      init_loc = c_parser_peek_token (parser)->location;
 	      init = c_parser_initializer (parser);
 	      finish_init ();
+          if (!nested)
+        invoke_plugin_callbacks (PLUGIN_FUNP_ALIAS, init.value);
 	      if (d != error_mark_node)
 		{
 		  maybe_warn_string_init (TREE_TYPE (d), init);
@@ -1709,11 +1727,15 @@ c_parser_declaration_or_fndef (c_parser 
 	 declarator with a nonempty identifier list in a definition;
 	 and postfix attributes have never been accepted here in
 	 function definitions either.  */
+      if (!nested)
+        invoke_plugin_callbacks (PLUGIN_EXTERN_FUNC_OLD_PARAM, NULL);
       while (c_parser_next_token_is_not (parser, CPP_EOF)
 	     && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
 	c_parser_declaration_or_fndef (parser, false, false, false,
 				       true, false, NULL);
       store_parm_decls ();
+      if (!nested)
+        invoke_plugin_callbacks (PLUGIN_EXTERN_FUNC, declarator);
       DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
 	= c_parser_peek_token (parser)->location;
       fnbody = c_parser_compound_statement (parser);
@@ -2211,6 +2233,7 @@ c_parser_enum_specifier (c_parser *parse
 	    }
 	  token = c_parser_peek_token (parser);
 	  enum_id = token->value;
+      invoke_plugin_callbacks (PLUGIN_ENUMERATOR, enum_id);
 	  /* Set the location in case we create a decl now.  */
 	  c_parser_set_source_position_from_token (token);
 	  decl_loc = value_loc = token->location;
@@ -6563,6 +6586,7 @@ c_parser_postfix_expression_after_primar
 	  break;
 	case CPP_OPEN_PAREN:
 	  /* Function call.  */
+      invoke_plugin_callbacks (PLUGIN_CALL_FUNCTION, expr.value);
 	  c_parser_consume_token (parser);
 	  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
 	    exprlist = NULL;
@@ -6706,6 +6730,7 @@ c_parser_expression (c_parser *parser)
       expr.original_code = COMPOUND_EXPR;
       expr.original_type = next.original_type;
     }
+  invoke_plugin_callbacks (PLUGIN_FUNP_ALIAS, expr.value);
   return expr;
 }
 
Index: gcc/gcc/plugin.c
===================================================================
--- gcc.orig/gcc/plugin.c
+++ gcc/gcc/plugin.c
@@ -438,6 +438,16 @@ register_callback (const char *plugin_na
       case PLUGIN_EARLY_GIMPLE_PASSES_START:
       case PLUGIN_EARLY_GIMPLE_PASSES_END:
       case PLUGIN_NEW_PASS:
+      case PLUGIN_CPP_TOKEN:
+      case PLUGIN_C_TOKEN:
+      case PLUGIN_EXTERN_DECL:
+      case PLUGIN_EXTERN_FUNC_OLD_PARAM:
+      case PLUGIN_EXTERN_FUNC:
+      case PLUGIN_EXTERN_VAR:
+      case PLUGIN_EXTERN_DECLSPECS:
+      case PLUGIN_CALL_FUNCTION:
+      case PLUGIN_ENUMERATOR:
+      case PLUGIN_FUNP_ALIAS:
         {
           struct callback_info *new_callback;
           if (!callback)
@@ -514,6 +524,16 @@ invoke_plugin_callbacks_full (int event,
       case PLUGIN_EARLY_GIMPLE_PASSES_START:
       case PLUGIN_EARLY_GIMPLE_PASSES_END:
       case PLUGIN_NEW_PASS:
+      case PLUGIN_CPP_TOKEN:
+      case PLUGIN_C_TOKEN:
+      case PLUGIN_EXTERN_DECL:
+      case PLUGIN_EXTERN_FUNC_OLD_PARAM:
+      case PLUGIN_EXTERN_FUNC:
+      case PLUGIN_EXTERN_VAR:
+      case PLUGIN_EXTERN_DECLSPECS:
+      case PLUGIN_CALL_FUNCTION:
+      case PLUGIN_ENUMERATOR:
+      case PLUGIN_FUNP_ALIAS:
         {
           /* Iterate over every callback registered with this event and
              call it.  */
Index: gcc/gcc/doc/plugins.texi
===================================================================
--- gcc.orig/gcc/doc/plugins.texi
+++ gcc/gcc/doc/plugins.texi
@@ -183,6 +183,25 @@ enum plugin_event
   PLUGIN_EARLY_GIMPLE_PASSES_END,
   /* Called when a pass is first instantiated.  */
   PLUGIN_NEW_PASS,
+  PLUGIN_CPP_TOKEN,                /* Called when GCC gets a cpp token. */
+  PLUGIN_C_TOKEN,                  /* Called when GCC gets a c token. */
+  /* An extern declaration (file-scope) is encounted. */
+  PLUGIN_EXTERN_DECL,
+  /* Cooperate PLUGIN_EXTERN_FUNC to parse a function with old-style parameter
+   * declaration. */
+  PLUGIN_EXTERN_FUNC_OLD_PARAM,
+  /* An extern function definition is parsed. */
+  PLUGIN_EXTERN_FUNC,
+  /* An extern variable definition is parsed. */
+  PLUGIN_EXTERN_VAR,
+  /* An extern declaration specifier definition is parsed. */
+  PLUGIN_EXTERN_DECLSPECS,
+  /* A function is called. */
+  PLUGIN_CALL_FUNCTION,
+  /* An enumerator is parsed. */
+  PLUGIN_ENUMERATOR,
+  /* Function pointer is assigned. */
+  PLUGIN_FUNP_ALIAS,
 
   PLUGIN_EVENT_FIRST_DYNAMIC    /* Dummy event used for indexing callback
                                    array.  */
Index: gcc/gcc/tree.h
===================================================================
--- gcc.orig/gcc/tree.h
+++ gcc/gcc/tree.h
@@ -2327,6 +2327,10 @@ extern enum machine_mode vector_type_mod
 #define TYPE_SYMTAB_IS_POINTER (1)
 #define TYPE_SYMTAB_IS_DIE (2)
 
+/* To C, all record/union types has file-scope even it's defined inside other
+   record/union, for special usage, the field mark it.  */
+#define TYPE_FILE_SCOPE(NODE) (RECORD_OR_UNION_CHECK (NODE)->type.file_scope)
+
 struct die_struct;
 
 struct GTY(()) tree_type {
@@ -2355,6 +2359,8 @@ struct GTY(()) tree_type {
   unsigned lang_flag_5 : 1;
   unsigned lang_flag_6 : 1;
 
+  bool file_scope;
+
   unsigned int align;
   alias_set_type alias_set;
   tree pointer_to;
