This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: compile server design document


Attached is a recent snapshot of the compile server.
This predates the C++ work which I've just started,
and is C-only.  I.e. you should configure with
--enable-languages=c if you want to try it.
But mainly this is for illustration.  It is certainly
not being proposed for checking into cvs as is!
--
	--Per Bothner
per at bothner dot com   http://www.bothner.com/per/
Index: c-common.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.h,v
retrieving revision 1.167
diff -c -r1.167 c-common.h
*** c-common.h	18 Jan 2003 02:26:40 -0000	1.167
--- c-common.h	8 Feb 2003 20:05:02 -0000
***************
*** 180,185 ****
--- 180,236 ----
    struct cpp_hashnode node;
  };
  
+ #define DECL_FRAGMENT(DECL) \
+   ((struct c_include_fragment *) DECL_CHECK (DECL)->decl.defining_fragment)
+ #define SET_DECL_FRAGMENT(DECL, FRAGMENT) \
+   (DECL_CHECK (DECL)->decl.defining_fragment = (tree) (FRAGMENT))
+ #define C_FRAGMENT(FRAG) ((struct c_include_fragment *) (FRAG)->start_marker)
+ 
+ struct c_include_fragment GTY(())
+ {
+   struct tree_common common;
+   const char *name;
+   /* Value of c_timestamp when this fragment was last read (parsed). */
+   int read_timestamp;
+   /* Value of c_timestamp when this fragment was last logically included. */
+   int include_timestamp;
+   /* True if a declaration in this fragmemt was used in current_c_fragment. */
+   unsigned used_in_current : 1;
+   unsigned valid : 1;
+   /* A TREE_VEC whose members are other c_include_fragments.  An element is in
+     uses_fragments iff the current fragments uses (references) a declartion
+     in that element. */
+   tree uses_fragments;
+   tree bindings;
+ };
+ 
+ extern int main_timestamp;
+ extern int c_timestamp;
+ extern GTY(()) struct c_include_fragment *current_c_fragment;
+ extern int currently_nested;
+ 
+ extern void register_decl_dependency PARAMS ((tree));
+ extern struct c_include_fragment * alloc_include_fragment PARAMS ((void));
+ extern void remember_fragment_start PARAMS ((struct c_include_fragment *));
+ extern void remember_fragment_end PARAMS ((struct c_include_fragment *));
+ extern void restore_from_fragment PARAMS ((struct c_include_fragment *));
+ extern void note_fragment_binding_1 PARAMS ((tree));
+ extern void note_fragment_binding_2 PARAMS ((tree, tree));
+ extern void note_fragment_binding_3 PARAMS ((tree, tree, tree));
+ extern void setup_globals PARAMS ((void));
+ 
+ extern void* cb_push_fragment PARAMS ((cpp_reader*, cpp_fragment*, const char*, int));
+ extern void cb_pop_fragment PARAMS ((cpp_reader*, cpp_fragment*));
+ 
+ #if 0
+ #define FRAGMENT_OLDEST_DECL(NODE) \
+   (((struct c_include_fragment *) (NODE))->oldest_decl)
+ #define FRAGMENT_NEWEST_DECL(NODE) \
+   (((struct c_include_fragment *) (NODE))->newest_decl)
+ #define FRAGMENT_PREVIOUS_FRAGMENT_DECL(NODE) \
+   (((struct c_include_fragment *) (NODE))->previous_fragment_decl)
+ #endif
+ 
  #define wchar_type_node			c_global_trees[CTI_WCHAR_TYPE]
  #define signed_wchar_type_node		c_global_trees[CTI_SIGNED_WCHAR_TYPE]
  #define unsigned_wchar_type_node	c_global_trees[CTI_UNSIGNED_WCHAR_TYPE]
***************
*** 916,921 ****
--- 967,974 ----
  extern tree convert_and_check			PARAMS ((tree, tree));
  extern void overflow_warning			PARAMS ((tree));
  extern void unsigned_conversion_warning		PARAMS ((tree, tree));
+ 
+ extern void c_initially_decl_processing		PARAMS ((void));
  
  /* Read the rest of the current #-directive line.  */
  extern char *get_directive_line			PARAMS ((void));
Index: cpphash.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cpphash.h,v
retrieving revision 1.175
diff -c -r1.175 cpphash.h
*** cpphash.h	21 Jan 2003 00:12:52 -0000	1.175
--- cpphash.h	8 Feb 2003 20:05:03 -0000
***************
*** 267,272 ****
--- 267,297 ----
    unsigned char printed;	/* Nonzero if something output at line.  */
  };
  
+ struct cpp_fragment
+ {
+   const char *name;		/* actual path name of file REDUNDANT */
+   cpp_fragment *next;
+   const unsigned char *start;
+   const unsigned char *end;
+   unsigned was_reused : 1;
+   /*unsigned int valid : 1;*/
+   void *start_marker;		/* Returned from front-end - kludge. */
+   unsigned int start_line;
+   unsigned int end_line;
+   const unsigned char *end_line_base;
+ };
+ 
+ /* Used by compile server to restore previous macro state. */
+ struct cpp_macro_note
+ {
+   cpp_hashnode *node;
+   struct cpp_macro *macro; /* null for an #undef */
+ };
+ extern void _cpp_note_macro PARAMS ((cpp_reader *,
+ 				     cpp_hashnode *, cpp_macro *));
+ extern void _cpp_restore_macros PARAMS ((cpp_reader *,
+ 					 struct cpp_macro_note *, int));
+ 
  /* Represents the contents of a file cpplib has read in.  */
  struct cpp_buffer
  {
***************
*** 323,328 ****
--- 348,355 ----
  
    /* Used for buffer overlays by cpptrad.c.  */
    const uchar *saved_cur, *saved_rlimit;
+ 
+   cpp_fragment *saved_current_fragment;
  };
  
  /* A cpp_reader encapsulates the "state" of a pre-processor run.
***************
*** 343,348 ****
--- 370,376 ----
    struct line_maps line_maps;
    const struct line_map *map;
    unsigned int line;
+   const char *main_input_filename;
  
    /* The line of the '#' of the current directive.  */
    unsigned int directive_line;
***************
*** 386,391 ****
--- 414,426 ----
  
    /* Tree of other included files.  See cppfiles.c.  */
    struct splay_tree_s *all_include_files;
+ 
+   cpp_fragment *current_fragment;
+ 
+   int do_note_macros;
+   struct cpp_macro_note *macro_notes;
+   int macro_notes_alloc_length;
+   int macro_notes_count;
  
    /* Current maximum length of directory names in the search path
       for include files.  (Altered as we get more of them.)  */
Index: cpplib.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cpplib.h,v
retrieving revision 1.242
diff -c -r1.242 cpplib.h
*** cpplib.h	28 Jan 2003 19:30:00 -0000	1.242
--- cpplib.h	8 Feb 2003 20:05:04 -0000
***************
*** 39,44 ****
--- 39,45 ----
  typedef struct cpp_hashnode cpp_hashnode;
  typedef struct cpp_macro cpp_macro;
  typedef struct cpp_callbacks cpp_callbacks;
+ typedef struct cpp_fragment cpp_fragment;
  
  struct answer;
  struct file_name_map_list;
***************
*** 419,424 ****
--- 420,428 ----
    void (*file_change) PARAMS ((cpp_reader *, const struct line_map *));
    void (*include) PARAMS ((cpp_reader *, unsigned int,
  			   const unsigned char *, const cpp_token *));
+   void* (*push_fragment) PARAMS ((cpp_reader *, cpp_fragment *,
+ 				  const char*, int));
+   void (*pop_fragment) PARAMS ((cpp_reader *, cpp_fragment *));
    void (*define) PARAMS ((cpp_reader *, unsigned int, cpp_hashnode *));
    void (*undef) PARAMS ((cpp_reader *, unsigned int, cpp_hashnode *));
    void (*ident) PARAMS ((cpp_reader *, unsigned int, const cpp_string *));
***************
*** 540,545 ****
--- 544,551 ----
  extern int cpp_handle_options PARAMS ((cpp_reader *, int, char **));
  extern int cpp_handle_option PARAMS ((cpp_reader *, int, char **));
  
+ /* FIXME this comment needs fixing, but leave it until later,
+    due to gcc-3.3 and gcc-3.4 type fix causing patch hassles. */
  /* This function reads the file, but does not start preprocessing.  It
     returns the name of the original file; this is the same as the
     input file, except for preprocessed input.  This will generate at
***************
*** 550,557 ****
     pointer.  Otherwise you should pass in an initialized hash table
     that cpplib will share; this technique is used by the C front
     ends.  */
! extern const char *cpp_read_main_file PARAMS ((cpp_reader *, const char *,
! 					       struct ht *));
  
  /* Deferred handling of command line options that can generate debug
     callbacks, such as -D and -imacros.  Call this after
--- 556,563 ----
     pointer.  Otherwise you should pass in an initialized hash table
     that cpplib will share; this technique is used by the C front
     ends.  */
! extern const char *cpp_read_main_file PARAMS ((cpp_reader *, const char *));
! extern void cpp_init_tables PARAMS ((cpp_reader *, struct ht *));
  
  /* Deferred handling of command line options that can generate debug
     callbacks, such as -D and -imacros.  Call this after
***************
*** 590,595 ****
--- 596,604 ----
  extern const unsigned char *cpp_macro_definition PARAMS ((cpp_reader *,
  						  const cpp_hashnode *));
  extern void _cpp_backup_tokens PARAMS ((cpp_reader *, unsigned int));
+ extern void _cpp_start_fragment PARAMS ((cpp_reader *));
+ extern void _cpp_push_fragment PARAMS ((cpp_reader *, cpp_fragment*));
+ extern void _cpp_pop_fragment PARAMS ((cpp_reader *, cpp_fragment*));
  
  /* Evaluate a CPP_CHAR or CPP_WCHAR token.  */
  extern cppchar_t
Index: c-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-tree.h,v
retrieving revision 1.109
diff -c -r1.109 c-tree.h
*** c-tree.h	16 Sep 2002 18:33:18 -0000	1.109
--- c-tree.h	8 Feb 2003 20:05:04 -0000
***************
*** 244,249 ****
--- 244,250 ----
  /* in c-objc-common.c */
  extern int c_disregard_inline_limits		PARAMS ((tree));
  extern int c_cannot_inline_tree_fn		PARAMS ((tree *));
+ extern void c_objc_common_initially		PARAMS ((void));
  extern const char *c_objc_common_init		PARAMS ((const char *));
  extern int c_missing_noreturn_ok_p		PARAMS ((tree));
  extern void c_objc_common_finish_file		PARAMS ((void));
Index: flags.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/flags.h,v
retrieving revision 1.96
diff -c -r1.96 flags.h
*** flags.h	24 Jan 2003 15:17:24 -0000	1.96
--- flags.h	8 Feb 2003 20:05:04 -0000
***************
*** 664,669 ****
--- 664,671 ----
  /* Nonzero means disable transformations observable by signaling NaNs.  */
  extern int flag_signaling_nans;
  
+ extern int is_server;
+ 
  /* True if the given mode has a NaN representation and the treatment of
     NaN operands is important.  Certain optimizations, such as folding
     x * 0 into x, are not correct for NaN operands, and are normally
Index: langhooks-def.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/langhooks-def.h,v
retrieving revision 1.40
diff -c -r1.40 langhooks-def.h
*** langhooks-def.h	16 Dec 2002 18:19:40 -0000	1.40
--- langhooks-def.h	8 Feb 2003 20:05:05 -0000
***************
*** 85,90 ****
--- 85,91 ----
  #define LANG_HOOKS_NAME			"GNU unknown"
  #define LANG_HOOKS_IDENTIFIER_SIZE	sizeof (struct lang_identifier)
  #define LANG_HOOKS_INIT			lhd_do_nothing
+ #define LANG_HOOKS_INITIALLY		lhd_do_nothing
  #define LANG_HOOKS_FINISH		lhd_do_nothing
  #define LANG_HOOKS_PARSE_FILE		lhd_do_nothing_i
  #define LANG_HOOKS_CLEAR_BINDING_STACK	lhd_clear_binding_stack
***************
*** 228,233 ****
--- 229,235 ----
    LANG_HOOKS_INIT_OPTIONS, \
    LANG_HOOKS_DECODE_OPTION, \
    LANG_HOOKS_POST_OPTIONS, \
+   LANG_HOOKS_INITIALLY, \
    LANG_HOOKS_INIT, \
    LANG_HOOKS_FINISH, \
    LANG_HOOKS_PARSE_FILE, \
Index: langhooks.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/langhooks.h,v
retrieving revision 1.49
diff -c -r1.49 langhooks.h
*** langhooks.h	16 Dec 2002 18:19:41 -0000	1.49
--- langhooks.h	8 Feb 2003 20:05:05 -0000
***************
*** 206,217 ****
       immediately and the finish hook is not called.  */
    bool (*post_options) PARAMS ((void));
  
!   /* Called after post_options, to initialize the front end.  The main
!      input filename is passed, which may be NULL; the front end should
       return the original filename (e.g. foo.i -> foo.c).  Return NULL
       to indicate a serious error of some sort; in that case no
!      compilation is performed, and the finish hook is called
!      immediately.  */
    const char * (*init) PARAMS ((const char *));
  
    /* Called at the end of compilation, as a finalizer.  */
--- 206,221 ----
       immediately and the finish hook is not called.  */
    bool (*post_options) PARAMS ((void));
  
!   /* Called after post_options, to initialize the front end.
!      This only gets call once, even if we're invoked as a server. */
!   void (*initially) PARAMS ((void));
! 
!   /* Called (after initially) to initially the front-end for a main file.
!      If we're invoked as a server, this is called once for each request.
!      The input filename is passed, which may be NULL; the front end should
       return the original filename (e.g. foo.i -> foo.c).  Return NULL
       to indicate a serious error of some sort; in that case no
!      compilation is performed, and the finish hook is called immediately. */
    const char * (*init) PARAMS ((const char *));
  
    /* Called at the end of compilation, as a finalizer.  */
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.379
diff -c -r1.379 tree.h
*** tree.h	31 Jan 2003 14:46:47 -0000	1.379
--- tree.h	8 Feb 2003 20:05:07 -0000
***************
*** 1792,1797 ****
--- 1792,1799 ----
  {
    struct tree_common common;
    location_t locus;
+   /* FIXME make part of locus - or of context! */
+   tree defining_fragment;
    unsigned int uid;
    tree size;
    ENUM_BITFIELD(machine_mode) mode : 8;
Index: c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.399
diff -c -r1.399 c-common.c
*** c-common.c	30 Jan 2003 07:23:57 -0000	1.399
--- c-common.c	8 Feb 2003 20:05:11 -0000
***************
*** 38,43 ****
--- 38,44 ----
  #include "tm_p.h"
  #include "obstack.h"
  #include "cpplib.h"
+ #include "cpphash.h"
  #include "target.h"
  #include "langhooks.h"
  #include "except.h"		/* For USING_SJLJ_EXCEPTIONS.  */
***************
*** 3185,3190 ****
--- 3186,3195 ----
  
  static void c_init_attributes PARAMS ((void));
  
+ static void reserve_fragment_binding PARAMS ((int));
+ 
+ static int common_nodes_and_builtins_done;
+ 
  /* Build tree nodes and builtin functions common to both C and C++ language
     frontends.  */
  
***************
*** 3225,3230 ****
--- 3230,3239 ----
    tree va_list_ref_type_node;
    tree va_list_arg_type_node;
  
+   setup_globals ();
+   if (common_nodes_and_builtins_done++ > 0)
+     return; /* FIXME - never happens? */
+ 
    /* Define `int' and `char' first so that dbx will output them first.  */
    record_builtin_type (RID_INT, NULL, integer_type_node);
    record_builtin_type (RID_CHAR, "char", char_type_node);
***************
*** 4725,4730 ****
--- 4734,4973 ----
    return val;
  }
  
+ /* A stack of include fragments that are used by current_c_fragment
+    or other not-yet popped headers.  The ones in current_c_fragment
+    are whose at index from 0    to current_fragment_deps_end (exclusive). */
+ static GTY (()) tree current_fragment_deps_stack;
+ /* The number of elements in current_include_deps_stack that are in use. */
+ static int current_fragment_deps_end;
+ 
+ struct c_include_fragment *current_c_fragment;
+ 
+ extern void register_fragment_dependency PARAMS ((struct c_include_fragment*));
+ 
+ void
+ register_decl_dependency (used)
+      tree used;
+ {
+   struct c_include_fragment *fragment;
+   const char *file = DECL_SOURCE_FILE (used);
+   if (file == NULL)
+     return;
+   if (strcmp (file, "<built-in>") == 0)
+     return;
+ 
+   fragment = DECL_FRAGMENT (used);
+   if (fragment == NULL)
+     return;
+   register_fragment_dependency (fragment);
+ }
+ 
+ tree fragment_bindings_stack;
+ int fragment_bindings_end;
+ 
+ static void
+ reserve_fragment_binding (space_needed)
+      int space_needed;
+ {
+   if (fragment_bindings_stack == NULL_TREE)
+     fragment_bindings_stack = make_tree_vec (50);
+   else if (TREE_VEC_LENGTH (fragment_bindings_stack)
+ 	   < fragment_bindings_end + space_needed)
+     {
+       /* Re-size fragment_bindings_stack. */
+       int i = fragment_bindings_end;
+       tree new_vec = make_tree_vec (2 * i);
+       while (--i >= 0)
+ 	TREE_VEC_ELT (new_vec, i)
+ 	  = TREE_VEC_ELT (fragment_bindings_stack, i);
+       fragment_bindings_stack = new_vec;
+     }
+   fragment_bindings_end += space_needed;
+ }
+ 
+ void
+ note_fragment_binding_1 (tree1)
+      tree tree1;
+ {
+   reserve_fragment_binding (1);
+   TREE_VEC_ELT (fragment_bindings_stack, fragment_bindings_end - 1) = tree1;
+ }
+ 
+ void
+ note_fragment_binding_2 (tree1, tree2)
+      tree tree1, tree2;
+ {
+   reserve_fragment_binding (2);
+   TREE_VEC_ELT (fragment_bindings_stack, fragment_bindings_end - 2) = tree1;
+   TREE_VEC_ELT (fragment_bindings_stack, fragment_bindings_end - 1) = tree2;
+ }
+ 
+ void
+ note_fragment_binding_3 (tree1, tree2, tree3)
+      tree tree1, tree2, tree3;
+ {
+   reserve_fragment_binding (3);
+   TREE_VEC_ELT (fragment_bindings_stack, fragment_bindings_end - 3) = tree1;
+   TREE_VEC_ELT (fragment_bindings_stack, fragment_bindings_end - 2) = tree2;
+   TREE_VEC_ELT (fragment_bindings_stack, fragment_bindings_end - 1) = tree3;
+ }
+ 
+ void
+ register_fragment_dependency (used)
+      struct c_include_fragment* used;
+ {
+   if (! used->used_in_current && used != current_c_fragment
+       && current_c_fragment != NULL)
+     {
+       if (current_fragment_deps_stack == NULL_TREE)
+ 	current_fragment_deps_stack = make_tree_vec (50);
+       else if (TREE_VEC_LENGTH (current_fragment_deps_stack)
+ 	== current_fragment_deps_end)
+ 	{
+ 	  /* Re-size current_fragment_deps_stack. */
+ 	  int i = current_fragment_deps_end;
+ 	  tree new_vec = make_tree_vec (2 * i);
+ 	  while (--i >= 0)
+ 	    TREE_VEC_ELT (new_vec, i)
+ 	      = TREE_VEC_ELT (current_fragment_deps_stack, i);
+ 	  current_fragment_deps_stack = new_vec;
+ 	}
+       TREE_VEC_ELT (current_fragment_deps_stack, current_fragment_deps_end)
+ 	= (tree) used;
+       current_fragment_deps_end++;
+       used->used_in_current = 1;
+     }
+ }
+ 
+ int main_timestamp;
+ int c_timestamp;
+ /* Inside an incomple enum, for example. */
+ int currently_nested;
+ 
+ void*
+ cb_push_fragment (reader, fragment, name, line)
+      cpp_reader* reader ATTRIBUTE_UNUSED;
+      cpp_fragment *fragment;
+      const char* name;
+      int line;
+ {
+   struct c_include_fragment* st = C_FRAGMENT (fragment);
+   void *ret;
+   bool valid = 0;
+   if (st != NULL)
+     {
+       int i;
+       valid = st->valid && st->include_timestamp < main_timestamp && ! currently_nested;
+ 
+       if (valid)
+ 	{
+ 	  /* Check dependencies. */
+ 	  tree d = st->uses_fragments;
+ 	  for (i = d == NULL_TREE ? 0 : TREE_VEC_LENGTH (d);  --i >= 0; )
+ 	    {
+ 	      struct c_include_fragment *uses
+ 		= (struct c_include_fragment *) TREE_VEC_ELT (d, i);
+ 	      if (uses->include_timestamp < main_timestamp
+ 		  || uses->read_timestamp == 0
+ 		  || uses->read_timestamp > st->read_timestamp)
+ 		{
+ 		  valid = 0;
+ 		  break;
+ 		}
+ 	    }
+ 	}
+ 
+       if (! valid)
+ 	{
+ 	  st->valid = 0;
+ 	  if (! quiet_flag)
+ 	    fprintf (stderr, "(invalidating cached fragment %s:%d)\n", name, line);
+ 	}
+       else
+ 	{
+ 	  if (! quiet_flag)
+ 	    fprintf (stderr, "(reusing cached fragment %s:%d)\n", name, line);
+ 	  restore_from_fragment (st);
+ 	  ret = NULL;
+ 	}
+     }
+   else
+     {
+       st = alloc_include_fragment ();
+       st->name = name;
+       st->valid = 0;
+     }
+   st->include_timestamp = ++c_timestamp;
+   if (! valid)
+     {
+       st->read_timestamp = 0;
+       st->uses_fragments = NULL_TREE;
+       st->bindings = NULL_TREE;
+       /*st->used_in_current = 0;*/
+ 
+       ret = st;
+       current_fragment_deps_end = 0;
+       fragment_bindings_end = 0;
+       st->read_timestamp = st->include_timestamp;
+     }
+   current_c_fragment = st;
+   /* Note fragment->was_resued is redundant - it's same as
+      st->include_timestamp > st->read_timestamp */
+   fragment->was_reused = ret == NULL;
+   return ret;
+ }
+ 
+ void
+ cb_pop_fragment (reader, fragment)
+      cpp_reader *reader ATTRIBUTE_UNUSED;
+      cpp_fragment *fragment;
+ {
+   struct c_include_fragment* st = C_FRAGMENT (fragment);
+   if (st != NULL)
+     {
+       int i;
+ 
+       int uses_fragments_count = current_fragment_deps_end;
+       tree uses_fragments = (uses_fragments_count == 0 ? NULL_TREE
+ 			     : make_tree_vec (uses_fragments_count));
+ 
+       tree bindings = (fragment_bindings_end == 0 ? NULL_TREE
+ 		       : make_tree_vec (fragment_bindings_end));
+       for (i = 0;  i < fragment_bindings_end;  i++)
+ 	{
+ 	  TREE_VEC_ELT (bindings, i)
+ 	    = TREE_VEC_ELT (fragment_bindings_stack, i);
+ 	  /* Clean up for the sake of garbage collection. ??? */
+ 	  TREE_VEC_ELT (fragment_bindings_stack, i) = NULL;
+ 	}
+       st->bindings = bindings;
+       fragment_bindings_end = 0;
+ 
+       for (i = 0;  i < current_fragment_deps_end;  i++)
+ 	{
+ 	  tree uses = TREE_VEC_ELT (current_fragment_deps_stack, i);
+ 	  TREE_VEC_ELT (uses_fragments, i) = uses;
+ 	  ((struct c_include_fragment*) uses)->used_in_current = 0;
+ 	  /* Clean up for the sake of garbage collection. ??? */
+ 	  TREE_VEC_ELT (current_fragment_deps_stack, i) = NULL;
+ 	}
+       st->uses_fragments = uses_fragments;
+       current_fragment_deps_end = 0;
+       for (i = 0;  i < current_fragment_deps_end;  i++)
+ 	{
+ 	 ((struct c_include_fragment*)  TREE_VEC_ELT (current_fragment_deps_stack, i))->used_in_current = 1;
+ 	}
+ 
+       current_c_fragment = NULL;
+       st->valid = ! currently_nested;
+     }
+ #if 0
+   fprintf(stderr, "(pop deps start:%d end:%d for %s ret:%s)\n",
+ 	  current_fragment_deps_start, current_fragment_deps_end, st->name,
+ 	  (st ? "non-null":"null"));
+ #endif
+ }
+ 
  /* Define NAME with value TYPE precision.  */
  static void
  builtin_define_type_precision (name, type)
***************
*** 4918,4923 ****
--- 5161,5169 ----
    /* -undef turns off target-specific built-ins.  */
    if (flag_undef)
      return;
+ 
+   if (is_server)
+     pfile->do_note_macros = 1;
  
    if (c_language == clk_cplusplus)
      {
Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.361
diff -c -r1.361 c-decl.c
*** c-decl.c	24 Jan 2003 15:17:24 -0000	1.361
--- c-decl.c	8 Feb 2003 20:05:16 -0000
***************
*** 43,48 ****
--- 43,49 ----
  #include "ggc.h"
  #include "tm_p.h"
  #include "cpplib.h"
+ #include "cpphash.h"
  #include "target.h"
  #include "debug.h"
  #include "timevar.h"
***************
*** 344,349 ****
--- 345,474 ----
      }
  }
  
+ static int c_init_decl_done;
+ static GTY(()) tree builtins_end;
+ 
+ static void restore_fragment_bindings PARAMS ((struct c_include_fragment *));
+ 
+ static void
+ restore_fragment_bindings (fragment)
+      struct c_include_fragment *fragment;
+ {
+   int i;
+   tree bindings = fragment->bindings;
+   int len;
+   struct binding_level *b = current_binding_level;
+   if (bindings == NULL_TREE)
+     return;
+   len = TREE_VEC_LENGTH (bindings);
+   for (i = 0;  i < len;  )
+     {
+       tree x = TREE_VEC_ELT (bindings, i);
+ 
+       if (TREE_CODE_CLASS (TREE_CODE (x)) == 'd')
+ 	{
+ 	  tree n = DECL_NAME (x);
+ 	  if (n != NULL_TREE)
+ 	    IDENTIFIER_GLOBAL_VALUE (n) = x;
+ 	  TREE_CHAIN (x) = b->names;
+ 	  b->names = x;
+ 	  i++;
+ 	}
+       else if (TREE_CODE (x) == TREE_LIST) /* pushtag */
+ 	{
+ 	  tree type = TREE_VALUE (x);
+ 	  TREE_CHAIN (x) = b->tags;
+ 	  TYPE_SIZE (type) = NULL_TREE;
+ 	  TYPE_FIELDS (type) = NULL_TREE;
+ 	  b->tags = x;
+ 	  i++;
+ 	}
+       else if (TREE_CODE_CLASS (TREE_CODE (x)) == 't')
+ 	{ /* finish_struct */
+ 	  tree type = x;
+ 	  TYPE_FIELDS (type) = TREE_VEC_ELT (bindings, i + 1);
+ 	  TYPE_SIZE (type) = TREE_VEC_ELT (bindings, i + 2);
+ 	  i += 3;
+ 	}
+       else
+ 	abort ();
+     }
+ }
+ 
+ void
+ restore_from_fragment (fragment)
+      struct c_include_fragment *fragment;
+ {
+   restore_fragment_bindings (fragment);
+ }
+ 
+ extern int clear_identifiers PARAMS ((cpp_reader*, cpp_hashnode*, void*));
+ int
+ clear_identifiers (pfile, node, v)
+      cpp_reader *pfile ATTRIBUTE_UNUSED;
+      cpp_hashnode *node;
+      void *v ATTRIBUTE_UNUSED;
+ {
+   tree tnode = HT_IDENT_TO_GCC_IDENT (node);
+   struct lang_identifier * lang_id = (struct lang_identifier *) tnode;
+   node->flags &= ~ NODE_POISONED; /* ??? also clear NODE_DIAGNOSTIC? */
+   if (TREE_CODE (tnode) != IDENTIFIER_NODE)
+      abort();
+   if (lang_id != NULL)
+     lang_id->global_value = NULL_TREE;
+   if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
+     {
+       cpp_macro *macro = node->value.macro;
+       macro->used = 0;
+ 
+       _cpp_free_definition (node);
+     }
+ 
+   return 1;
+ }
+ 
+ void setup_globals ()
+ {
+   current_function_decl = NULL;
+   named_labels = NULL;
+   current_binding_level = NULL_BINDING_LEVEL;
+ 
+   /* Make the binding_level structure for global names.  */
+   pushlevel (0);
+   global_binding_level = current_binding_level;
+ }
+ 
+ void
+ c_init_decl_processing ()
+ {
+ 
+   main_timestamp = ++c_timestamp;
+   if (c_init_decl_done++ == 0)
+     {
+       setup_globals ();
+       parse_in->do_note_macros = 0;
+     }
+   else
+     {
+       tree d;
+       struct c_include_fragment *fragment;
+ 
+       cpp_forall_identifiers (parse_in, clear_identifiers, NULL);
+       _cpp_restore_macros (parse_in,
+ 			   parse_in->macro_notes, parse_in->macro_notes_count);
+ 
+       global_binding_level->names = builtins_end;
+       global_binding_level->tags = NULL_TREE;
+       
+       for (d = builtins_end;  d != NULL_TREE;  d = TREE_CHAIN (d))
+ 	{
+ 	  tree n = DECL_NAME (d);
+ 	  if (n != NULL_TREE)
+ 	    IDENTIFIER_GLOBAL_VALUE (n) = d;
+ 	}
+   }
+ }
+ 
  /* Reuse or create a struct for this binding level.  */
  
  static struct binding_level *
***************
*** 831,836 ****
--- 956,966 ----
  
    b->tags = tree_cons (name, type, b->tags);
  
+   if (b == global_binding_level && is_server)
+     {
+       note_fragment_binding_1 (b->tags);
+     }
+ 
    /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the
       tagged type we just added to the current binding level.  This fake
       NULL-named TYPE_DECL node helps dwarfout.c to know when it needs
***************
*** 1839,1844 ****
--- 1969,1979 ----
  	    TREE_PUBLIC (name) = 1;
  
  	  IDENTIFIER_GLOBAL_VALUE (name) = x;
+ 	  if (is_server)
+ 	    {
+ 	      SET_DECL_FRAGMENT (x, current_c_fragment);
+ 	      note_fragment_binding_1 (x);
+ 	    }
  
  	  /* We no longer care about any previous block level declarations.  */
  	  IDENTIFIER_LIMBO_VALUE (name) = 0;
***************
*** 2432,2437 ****
--- 2567,2574 ----
      val = IDENTIFIER_LOCAL_VALUE (name);
    else
      val = IDENTIFIER_GLOBAL_VALUE (name);
+   if (val != NULL_TREE && is_server)
+     register_decl_dependency (val);
    return val;
  }
  
***************
*** 2462,2468 ****
     Make definitions for built-in primitive functions.  */
  
  void
! c_init_decl_processing ()
  {
    tree endlink;
    tree ptr_ftype_void, ptr_ftype_ptr;
--- 2599,2605 ----
     Make definitions for built-in primitive functions.  */
  
  void
! c_initially_decl_processing ()
  {
    tree endlink;
    tree ptr_ftype_void, ptr_ftype_ptr;
***************
*** 2470,2484 ****
    /* Adds some ggc roots, and reserved words for c-parse.in.  */
    c_parse_init ();
  
-   current_function_decl = NULL;
-   named_labels = NULL;
-   current_binding_level = NULL_BINDING_LEVEL;
    free_binding_level = NULL_BINDING_LEVEL;
  
-   /* Make the binding_level structure for global names.  */
-   pushlevel (0);
-   global_binding_level = current_binding_level;
- 
    build_common_tree_nodes (flag_signed_char);
  
    c_common_nodes_and_builtins ();
--- 2607,2614 ----
***************
*** 2509,2514 ****
--- 2639,2645 ----
  
    make_fname_decl = c_make_fname_decl;
    start_fname_decls ();
+   builtins_end = global_binding_level->names;
  }
  
  /* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
***************
*** 5302,5307 ****
--- 5433,5443 ----
  
    layout_type (t);
  
+   if (is_server)
+     {
+       note_fragment_binding_3 (t, fieldlist, TYPE_SIZE (t));
+     }
+ 
    /* Delete all zero-width bit-fields from the fieldlist */
    {
      tree *fieldlistp = &fieldlist;
***************
*** 5450,5455 ****
--- 5586,5593 ----
    if (flag_short_enums)
      TYPE_PACKED (enumtype) = 1;
  
+   currently_nested++;
+ 
    return enumtype;
  }
  
***************
*** 5470,5475 ****
--- 5608,5615 ----
    int precision, unsign;
    int toplevel = (global_binding_level == current_binding_level);
  
+   currently_nested--;
+ 
    if (in_parm_level_p ())
      warning ("enum defined inside parms");
  
***************
*** 5562,5567 ****
--- 5702,5712 ----
  	}
  
        TYPE_VALUES (enumtype) = values;
+     }
+ 
+   if (is_server)
+     {
+       note_fragment_binding_3 (enumtype, values, TYPE_SIZE (enumtype));
      }
  
    /* Fix up all variant types of this enum type.  */
Index: c-lang.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-lang.c,v
retrieving revision 1.101
diff -c -r1.101 c-lang.c
*** c-lang.c	16 Dec 2002 18:19:02 -0000	1.101
--- c-lang.c	8 Feb 2003 20:05:16 -0000
***************
*** 37,42 ****
--- 37,44 ----
  
  #undef LANG_HOOKS_NAME
  #define LANG_HOOKS_NAME "GNU C"
+ #undef LANG_HOOKS_INITIALLY
+ #define LANG_HOOKS_INITIALLY c_objc_common_initially
  #undef LANG_HOOKS_INIT
  #define LANG_HOOKS_INIT c_objc_common_init
  #undef LANG_HOOKS_FINISH
Index: c-lex.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-lex.c,v
retrieving revision 1.193
diff -c -r1.193 c-lex.c
*** c-lex.c	13 Jan 2003 00:14:58 -0000	1.193
--- c-lex.c	8 Feb 2003 20:05:17 -0000
***************
*** 139,146 ****
    /* Start it at 0.  */
    lineno = 0;
  
!   return cpp_read_main_file (parse_in, filename, ident_hash);
  }
  
  /* A thin wrapper around the real parser that initializes the 
     integrated preprocessor after debug output has been initialized.
--- 139,149 ----
    /* Start it at 0.  */
    lineno = 0;
  
!   return cpp_read_main_file (parse_in, filename);
  }
+ 
+ /* kludge to reduce patch conflicts with Apple PFE */
+ #define cpp_finish_options(parse_in) ((void)0)
  
  /* A thin wrapper around the real parser that initializes the 
     integrated preprocessor after debug output has been initialized.
Index: c-objc-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-objc-common.c,v
retrieving revision 1.20
diff -c -r1.20 c-objc-common.c
*** c-objc-common.c	10 Jan 2003 02:21:58 -0000	1.20
--- c-objc-common.c	8 Feb 2003 20:05:17 -0000
***************
*** 28,33 ****
--- 28,34 ----
  #include "integrate.h"
  #include "expr.h"
  #include "c-tree.h"
+ #include "c-pragma.h"
  #include "function.h"
  #include "flags.h"
  #include "toplev.h"
***************
*** 237,242 ****
--- 238,279 ----
      return false;
  
    return true;
+ }
+ 
+ /* APPLE local hack - remove for FSF */
+ void print_INCLUDE_FRAGMENT () { abort(); }
+ 
+ struct c_include_fragment *
+ alloc_include_fragment ()
+ {
+   int length = sizeof (struct c_include_fragment);
+   tree t = ggc_alloc_tree (length);
+   memset ((PTR) t, 0, length);
+   TREE_SET_CODE (t, INCLUDE_FRAGMENT);
+   return (struct c_include_fragment *) t;
+ }
+ 
+ /* Initialization common to C and Objective-C front ends.  */
+ void
+ c_objc_common_initially ()
+ {
+   cpp_init_tables (parse_in, ident_hash);
+ 
+   /*
+   if (! CPP_OPTION (pfile, preprocessed))
+     {
+       struct pending_option *p;
+ 
+       _cpp_do_file_change (pfile, LC_RENAME, _("<built-in>"), 1, 0);
+     }
+   */
+   init_pragma ();
+ 
+   c_initially_decl_processing ();
+ 
+   c_common_initially ();
+ 
+   cpp_finish_options (parse_in);
  }
  
  /* Initialization common to C and Objective-C front ends.  */
Index: c-opts.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-opts.c,v
retrieving revision 1.28
diff -c -r1.28 c-opts.c
*** c-opts.c	28 Jan 2003 19:29:57 -0000	1.28
--- c-opts.c	8 Feb 2003 20:05:18 -0000
***************
*** 1430,1439 ****
      cpp_preprocess_file (parse_in, in_fname, out_stream);
  }
  
! /* Front end initialization common to C, ObjC and C++.  */
! const char *
! c_common_init (filename)
!      const char *filename;
  {
    /* Set up preprocessor arithmetic.  Must be done after call to
       c_common_nodes_and_builtins for type nodes to be good.  */
--- 1430,1437 ----
      cpp_preprocess_file (parse_in, in_fname, out_stream);
  }
  
! void
! c_common_initially ()
  {
    /* Set up preprocessor arithmetic.  Must be done after call to
       c_common_nodes_and_builtins for type nodes to be good.  */
***************
*** 1446,1452 ****
--- 1444,1461 ----
    /* Register preprocessor built-ins before calls to
       cpp_main_file.  */
    cpp_get_callbacks (parse_in)->register_builtins = cb_register_builtins;
+   if (is_server)
+     {
+       cpp_get_callbacks (parse_in)->push_fragment = cb_push_fragment;
+       cpp_get_callbacks (parse_in)->pop_fragment = cb_pop_fragment;
+     }
+ }
  
+ /* Front end initialization common to C, ObjC and C++.  */
+ const char *
+ c_common_init (filename)
+      const char *filename;
+ {
    /* NULL is passed up to toplev.c and we exit quickly.  */
    if (flag_preprocess_only)
      {
***************
*** 1457,1465 ****
    /* Do this before initializing pragmas, as then cpplib's hash table
       has been set up.  NOTE: we are using our own file name here, not
       the one supplied.  */
    filename = init_c_lex (in_fname);
- 
-   init_pragma ();
  
    return filename;
  }
--- 1466,1473 ----
    /* Do this before initializing pragmas, as then cpplib's hash table
       has been set up.  NOTE: we are using our own file name here, not
       the one supplied.  */
+   in_fname = filename;
    filename = init_c_lex (in_fname);
  
    return filename;
  }
Index: cppfiles.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cppfiles.c,v
retrieving revision 1.160
diff -c -r1.160 cppfiles.c
*** cppfiles.c	10 Jan 2003 02:21:58 -0000	1.160
--- cppfiles.c	8 Feb 2003 20:05:22 -0000
***************
*** 94,99 ****
--- 94,100 ----
  				/* location in search path where file was
  				   found, for #include_next and sysp.  */
    const unsigned char *buffer;	/* pointer to cached file contents */
+   cpp_fragment *fragments;	/* head of fragment chain */
    struct stat st;		/* copy of stat(2) data for file */
    int fd;			/* fd open on file (short term storage only) */
    int err_no;			/* errno obtained if opening a file failed */
***************
*** 121,127 ****
  /* The cmacro works like this: If it's NULL, the file is to be
     included again.  If it's NEVER_REREAD, the file is never to be
     included again.  Otherwise it is a macro hashnode, and the file is
!    to be included again if the macro is defined.  */
  #define NEVER_REREAD ((const cpp_hashnode *) -1)
  #define DO_NOT_REREAD(inc) \
  ((inc)->cmacro && ((inc)->cmacro == NEVER_REREAD \
--- 122,128 ----
  /* The cmacro works like this: If it's NULL, the file is to be
     included again.  If it's NEVER_REREAD, the file is never to be
     included again.  Otherwise it is a macro hashnode, and the file is
!    to be included again if the macro is undefined.  */
  #define NEVER_REREAD ((const cpp_hashnode *) -1)
  #define DO_NOT_REREAD(inc) \
  ((inc)->cmacro && ((inc)->cmacro == NEVER_REREAD \
***************
*** 148,153 ****
--- 149,155 ----
  static int read_include_file	PARAMS ((cpp_reader *, struct include_file *));
  static bool stack_include_file	PARAMS ((cpp_reader *, struct include_file *));
  static void purge_cache 	PARAMS ((struct include_file *));
+ static void purge_fragments 	PARAMS ((struct include_file *));
  static void destroy_node	PARAMS ((splay_tree_value));
  static int report_missing_guard		PARAMS ((splay_tree_node, void *));
  static splay_tree_node find_or_create_entry PARAMS ((cpp_reader *,
***************
*** 467,472 ****
--- 469,479 ----
  			/* from_stage3 */ CPP_OPTION (pfile, preprocessed), 0);
    fp->inc = inc;
    fp->inc->refcnt++;
+   pfile->current_fragment = inc->fragments;
+ #if 0
+   if (inc->fragments)
+     _cpp_push_fragment (pfile, inc->fragments);
+ #endif
  
    /* Initialize controlling macro state.  */
    pfile->mi_valid = true;
***************
*** 481,486 ****
--- 488,531 ----
    return true;
  }
  
+ void
+ _cpp_push_fragment (pfile, fragment)
+      cpp_reader *pfile;
+      cpp_fragment *fragment;
+ {
+   if (pfile->cb.push_fragment != NULL)
+     {
+       void *start
+ 	= pfile->cb.push_fragment (pfile, fragment,
+ 				   fragment->name,
+ 				   SOURCE_LINE (lookup_line (&pfile->line_maps, pfile->line), pfile->line));
+       if (start == NULL)
+ 	{
+ 	  pfile->buffer->cur = fragment->end;
+ 	  pfile->buffer->line_base = fragment->end_line_base;
+ 	  pfile->line += fragment->end_line - fragment->start_line;
+ 	  return;
+ 	}
+       fragment->start_marker = start;
+       fragment->start_line = pfile->line;
+     }
+ }
+ 
+ void
+ _cpp_pop_fragment (pfile, fragment)
+      cpp_reader *pfile;
+      cpp_fragment *fragment;
+ {
+   if (pfile->cb.pop_fragment != NULL
+       && ! pfile->state.skipping
+       && ! fragment->was_reused)
+     {
+       pfile->cb.pop_fragment (pfile, fragment);
+       fragment->end_line = pfile->line;
+       fragment->end_line_base = pfile->buffer->line_base;
+     }
+ }
+ 
  /* Read the file referenced by INC into the file cache.
  
     If fd points to a plain file, we might be able to mmap it; we can
***************
*** 500,505 ****
--- 545,551 ----
       cpp_reader *pfile;
       struct include_file *inc;
  {
+   cpp_fragment *fragment;
    ssize_t size, offset, count;
    uchar *buf;
  #if MMAP_THRESHOLD
***************
*** 601,606 ****
--- 647,668 ----
      }
  
    inc->buffer = buf;
+ 
+   if (pfile->cb.pop_fragment != NULL)
+     {
+       size = strlen (inc->name);
+       if (size > 2 && inc->name[size-1] != 'c') /* FIXME */
+ 	{
+ 	  purge_fragments (inc);
+ 	  fragment = xcnew (cpp_fragment);
+ 	  fragment->name = inc->name;
+ 	  fragment->next = NULL;
+ 	  fragment->start = buf;
+ 	  fragment->end = 0;
+ 	  inc->fragments = fragment;
+ 	}
+     }
+ 
    return 0;
  
   perror_fail:
***************
*** 631,636 ****
--- 693,713 ----
  	free ((PTR) inc->buffer);
        inc->buffer = NULL;
      }
+   purge_fragments (inc);
+ }
+ 
+ static void
+ purge_fragments (inc)
+      struct include_file *inc;
+ {
+   cpp_fragment *fragment = inc->fragments;;
+   while (fragment != NULL)
+     {
+       cpp_fragment *next = fragment->next;
+       free ((PTR) fragment);
+       fragment = next;
+     }
+   inc->fragments = NULL;
  }
  
  /* Return 1 if the file named by FNAME has been included before in
***************
*** 895,902 ****
--- 972,981 ----
    pfile->mi_valid = false;
  
    inc->refcnt--;
+ #if 0
    if (inc->refcnt == 0 && DO_NOT_REREAD (inc))
      purge_cache (inc);
+ #endif
  }
  
  /* Returns the first place in the include chain to start searching for
Index: cppinit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cppinit.c,v
retrieving revision 1.266
diff -c -r1.266 cppinit.c
*** cppinit.c	28 Jan 2003 19:29:57 -0000	1.266
--- cppinit.c	8 Feb 2003 20:05:23 -0000
***************
*** 911,924 ****
    deps_add_target (pfile->deps, target, quote);
  }
  
! /* This is called after options have been parsed, and partially
!    processed.  Setup for processing input from the file named FNAME,
!    or stdin if it is the empty string.  Return the original filename
!    on success (e.g. foo.i->foo.c), or NULL on failure.  */
! const char *
! cpp_read_main_file (pfile, fname, table)
       cpp_reader *pfile;
-      const char *fname;
       hash_table *table;
  {
    static const char *const lang_env_vars[] =
--- 911,919 ----
    deps_add_target (pfile->deps, target, quote);
  }
  
! void
! cpp_init_tables (pfile, table)
       cpp_reader *pfile;
       hash_table *table;
  {
    static const char *const lang_env_vars[] =
***************
*** 963,969 ****
--- 958,975 ----
  	}
        fprintf (stderr, _("End of search list.\n"));
      }
+ }
  
+ /* This is called after options have been parsed, and partially
+    processed.  Setup for processing input from the file named FNAME,
+    or stdin if it is the empty string.  Return the original filename
+    on success (e.g. foo.i->foo.c), or NULL on failure.  */
+ const char *
+ cpp_read_main_file (pfile, fname)
+      cpp_reader *pfile;
+      const char *fname;
+ {
+   pfile->main_input_filename = fname;
    if (CPP_OPTION (pfile, deps.style) != DEPS_NONE)
      {
        if (!pfile->deps)
***************
*** 1078,1084 ****
  	{
  	  /* All done; restore the line map from <command line>.  */
  	  _cpp_do_file_change (pfile, LC_RENAME,
! 			       pfile->line_maps.maps[0].to_file, 1, 0);
  	  /* Don't come back here again.  */
  	  pfile->next_include_file = NULL;
  	}
--- 1084,1091 ----
  	{
  	  /* All done; restore the line map from <command line>.  */
  	  _cpp_do_file_change (pfile, LC_RENAME,
! 			       pfile->main_input_filename, 1, 0);
! 	  /*			       pfile->line_maps.maps[0].to_file, 1, 0);*/
  	  /* Don't come back here again.  */
  	  pfile->next_include_file = NULL;
  	}
Index: cpplib.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cpplib.c,v
retrieving revision 1.329
diff -c -r1.329 cpplib.c
*** cpplib.c	28 Jan 2003 19:30:00 -0000	1.329
--- cpplib.c	8 Feb 2003 20:05:25 -0000
***************
*** 238,249 ****
--- 238,261 ----
  start_directive (pfile)
       cpp_reader *pfile;
  {
+   cpp_fragment *fragment;
+   const unsigned char *cur;
+ 
    /* Setup in-directive state.  */
    pfile->state.in_directive = 1;
    pfile->state.save_comments = 0;
  
    /* Some handlers need the position of the # for diagnostics.  */
    pfile->directive_line = pfile->line;
+ 
+   cur = pfile->buffer->cur - 1;
+   if ((fragment = pfile->current_fragment) != NULL
+       && (fragment->end == NULL
+ 	  || fragment->end == cur))
+     {
+       fragment->end = cur;
+       _cpp_pop_fragment (pfile, fragment);
+     }
  }
  
  /* Called when leaving a directive, _Pragma or command-line directive.  */
***************
*** 277,282 ****
--- 289,335 ----
    pfile->state.in_expression = 0;
    pfile->state.angled_headers = 0;
    pfile->directive = 0;
+   _cpp_start_fragment (pfile);
+ }
+ 
+ void
+ _cpp_start_fragment (pfile)
+      cpp_reader *pfile;
+ {
+   cpp_fragment *fragment;
+   if ((fragment = pfile->current_fragment) != NULL
+       && ! pfile->state.skipping)
+     {
+       const unsigned char *cur = pfile->buffer->cur;
+       for (;;)
+ 	{
+ 	  cpp_fragment *next_fragment = fragment->next;
+ 	  if (next_fragment == NULL || next_fragment->start > cur)
+ 	    break;
+ 	  fragment = next_fragment;
+ 	}
+       if (fragment->start < cur)
+ 	{
+ 	  cpp_fragment *next_fragment;
+ 	  if (1 /*fragment->start != fragment->end*/
+ 	      /* && contains more than whitespace ... FIXME */)
+ 	    {
+ #if 0
+ 	      if (fragment->start != fragment->end)
+ 		fragment->start_marker = NULL;  /* FIXME */
+ #endif
+ 	      next_fragment = xcnew (cpp_fragment);
+ 	      next_fragment->name = fragment->name;
+ 	      next_fragment->next = fragment->next;
+ 	      fragment->next = next_fragment;
+ 	      fragment = next_fragment;
+ 	    }
+ 	  fragment->start = cur;
+ 	  fragment->end = 0;
+ 	}
+       pfile->current_fragment = fragment;
+       _cpp_push_fragment (pfile, fragment);
+     }
  }
  
  /* Prepare to handle the directive in pfile->directive.  */
***************
*** 520,525 ****
--- 573,634 ----
    return NULL;
  }
  
+ void
+ _cpp_restore_macros (pfile, notes, count)
+      cpp_reader *pfile ATTRIBUTE_UNUSED;
+      struct cpp_macro_note *notes;
+      int count;
+ {
+   for (;  --count >= 0;  notes++)
+     {
+       cpp_hashnode *node = notes->node;
+       struct cpp_macro *macro = notes->macro;
+       if (macro != NULL)
+ 	{
+ 	  /* #define */
+ 	  node->type = NT_MACRO;
+ 	  node->value.macro = macro;
+ 	}
+       else
+ 	{
+ 	  /* #undef */
+ 	  _cpp_free_definition (node);
+ 	}
+     }
+ }
+ 
+ void
+ _cpp_note_macro (pfile, node, macro)
+      cpp_reader *pfile;
+      cpp_hashnode *node;
+      struct cpp_macro *macro;
+ {
+   int count, alloc;
+   if (! pfile->do_note_macros)
+     return;
+ 
+   count = pfile->macro_notes_count;
+   if (pfile->macro_notes == NULL)
+     {
+       alloc = 64;
+       pfile->macro_notes = xmalloc (alloc * sizeof (struct cpp_macro_note));
+       pfile->macro_notes_alloc_length = alloc;
+     }
+   else if (count >= (alloc = pfile->macro_notes_alloc_length))
+     {
+       struct cpp_macro_note *new_notes
+ 	= xmalloc (2 * alloc * sizeof (struct cpp_macro_note));
+       memcpy (new_notes, pfile->macro_notes,
+ 	      count * sizeof (struct cpp_macro_note));
+       free (pfile->macro_notes);
+       pfile->macro_notes = new_notes;
+       pfile->macro_notes_alloc_length = 2 * alloc;
+     }
+   pfile->macro_notes[count].node = node;
+   pfile->macro_notes[count].macro = macro;
+   pfile->macro_notes_count = count + 1;
+ }
+ 
  /* Process a #define directive.  Most work is done in cppmacro.c.  */
  static void
  do_define (pfile)
***************
*** 534,542 ****
        pfile->state.save_comments =
  	! CPP_OPTION (pfile, discard_comments_in_macro_exp);
  
        if (_cpp_create_definition (pfile, node))
! 	if (pfile->cb.define)
! 	  (*pfile->cb.define) (pfile, pfile->directive_line, node);
      }
  }
  
--- 643,655 ----
        pfile->state.save_comments =
  	! CPP_OPTION (pfile, discard_comments_in_macro_exp);
  
+ 
        if (_cpp_create_definition (pfile, node))
! 	{
! 	  _cpp_note_macro (pfile, node, node->value.macro);
! 	  if (pfile->cb.define)
! 	    (*pfile->cb.define) (pfile, pfile->directive_line, node);
! 	}
      }
  }
  
***************
*** 554,559 ****
--- 667,674 ----
        if (pfile->cb.undef)
  	(*pfile->cb.undef) (pfile, pfile->directive_line, node);
  
+       _cpp_note_macro (pfile, node, NULL);
+ 
        if (node->flags & NODE_WARN)
  	cpp_error (pfile, DL_WARNING, "undefining \"%s\"", NODE_NAME (node));
  
***************
*** 2030,2036 ****
--- 2145,2153 ----
    new->return_at_eof = return_at_eof;
    new->saved_flags = BOL;
  
+   new->saved_current_fragment = pfile->current_fragment;
    pfile->buffer = new;
+   pfile->current_fragment = NULL;
  
    return new;
  }
***************
*** 2054,2060 ****
--- 2171,2184 ----
    /* In case of a missing #endif.  */
    pfile->state.skipping = 0;
  
+   if (pfile->current_fragment != 0)
+     {
+       cpp_fragment *fragment = pfile->current_fragment;
+       fragment->end = buffer->cur;
+       _cpp_pop_fragment (pfile, fragment);
+     }
    /* _cpp_do_file_change expects pfile->buffer to be the new one.  */
+   pfile->current_fragment = buffer->saved_current_fragment;
    pfile->buffer = buffer->prev;
  
    /* Free the buffer object now; we may want to push a new buffer
***************
*** 2074,2079 ****
--- 2198,2204 ----
  	     files left to push.  */
  	  if (!pfile->buffer->prev)
  	    _cpp_maybe_push_include_file (pfile);
+ 	  _cpp_start_fragment (pfile);
  	}
      }
  }
Index: cppmain.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cppmain.c,v
retrieving revision 1.106
diff -c -r1.106 cppmain.c
*** cppmain.c	16 Dec 2002 18:19:18 -0000	1.106
--- cppmain.c	8 Feb 2003 20:05:25 -0000
***************
*** 72,81 ****
  
    setup_callbacks (pfile);
  
!   if (cpp_read_main_file (pfile, in_fname, NULL))
      {
        cpp_options *options = &pfile->opts;
!       cpp_finish_options (pfile);
  
        /* A successful cpp_read_main_file guarantees that we can call
  	 cpp_scan_nooutput or cpp_get_token next.  */
--- 72,81 ----
  
    setup_callbacks (pfile);
  
!   if (cpp_read_main_file (pfile, in_fname))
      {
        cpp_options *options = &pfile->opts;
!       /*cpp_finish_options (pfile);*/
  
        /* A successful cpp_read_main_file guarantees that we can call
  	 cpp_scan_nooutput or cpp_get_token next.  */
Index: fix-header.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fix-header.c,v
retrieving revision 1.85
diff -c -r1.85 fix-header.c
*** fix-header.c	16 Dec 2002 18:19:26 -0000	1.85
--- fix-header.c	8 Feb 2003 20:05:26 -0000
***************
*** 637,643 ****
    if (cpp_errors (scan_in))
      exit (FATAL_EXIT_CODE);
  
!   if (! cpp_read_main_file (scan_in, in_fname, NULL))
      exit (FATAL_EXIT_CODE);
  
    cpp_finish_options (scan_in);
--- 637,644 ----
    if (cpp_errors (scan_in))
      exit (FATAL_EXIT_CODE);
  
!   cpp_init_tables (scan_in, NULL);
!   if (! cpp_read_main_file (scan_in, in_fname))
      exit (FATAL_EXIT_CODE);
  
    cpp_finish_options (scan_in);
Index: ggc-page.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ggc-page.c,v
retrieving revision 1.61
diff -c -r1.61 ggc-page.c
*** ggc-page.c	30 Jan 2003 18:14:06 -0000	1.61
--- ggc-page.c	8 Feb 2003 20:05:29 -0000
***************
*** 1523,1528 ****
--- 1523,1529 ----
  void
  ggc_collect ()
  {
+ #if 0
    /* Avoid frequent unnecessary work by skipping collection if the
       total allocations haven't expanded much since the last
       collection.  */
***************
*** 1564,1569 ****
--- 1565,1571 ----
  
    if (!quiet_flag)
      fprintf (stderr, "%luk}", (unsigned long) G.allocated / 1024);
+ #endif
  }
  
  /* Print allocation statistics.  */
Index: regclass.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/regclass.c,v
retrieving revision 1.168
diff -c -r1.168 regclass.c
*** regclass.c	31 Jan 2003 23:34:13 -0000	1.168
--- regclass.c	8 Feb 2003 20:05:31 -0000
***************
*** 49,55 ****
  #endif
  
  static void init_reg_sets_1	PARAMS ((void));
- static void init_reg_modes	PARAMS ((void));
  static void init_reg_autoinc	PARAMS ((void));
  
  /* If we have auto-increment or auto-decrement and we can have secondary
--- 49,54 ----
***************
*** 549,555 ****
     These values are used to record death information for individual registers
     (as opposed to a multi-register mode).  */
  
! static void
  init_reg_modes ()
  {
    int i;
--- 548,554 ----
     These values are used to record death information for individual registers
     (as opposed to a multi-register mode).  */
  
! void
  init_reg_modes ()
  {
    int i;
***************
*** 577,584 ****
    /* This finishes what was started by init_reg_sets, but couldn't be done
       until after register usage was specified.  */
    init_reg_sets_1 ();
- 
-   init_reg_modes ();
  
    init_reg_autoinc ();
  }
--- 576,581 ----
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.703
diff -c -r1.703 toplev.c
*** toplev.c	26 Jan 2003 14:40:15 -0000	1.703
--- toplev.c	8 Feb 2003 20:05:34 -0000
***************
*** 142,147 ****
--- 142,150 ----
  /* Copy of arguments to toplev_main.  */
  int save_argc;
  char **save_argv;
+ 
+ int is_server;
+ static bool no_backend;
  
  /* Name of current original source file (what was input to cpp).
     This comes from each #-command in the actual input.  */
***************
*** 982,987 ****
--- 985,991 ----
  
  static const lang_independent_options f_options[] =
  {
+   {"server", &is_server, 1, N_("run compiler in server mode") },
    {"eliminate-dwarf2-dups", &flag_eliminate_dwarf2_dups, 1,
     N_("Perform DWARF2 duplicate elimination") },
    {"float-store", &flag_float_store, 1,
***************
*** 5214,5230 ****
  static void
  backend_init ()
  {
-   /* init_emit_once uses reg_raw_mode and therefore must be called
-      after init_regs which initialized reg_raw_mode.  */
    init_regs ();
-   init_emit_once (debug_info_level == DINFO_LEVEL_NORMAL
- 		  || debug_info_level == DINFO_LEVEL_VERBOSE
- #ifdef VMS_DEBUGGING_INFO
- 		    /* Enable line number info for traceback */
- 		    || debug_info_level > DINFO_LEVEL_NONE
- #endif
- 		    || flag_test_coverage
- 		    || warn_notreached);
    init_fake_stack_mems ();
    init_alias_once ();
    init_loop ();
--- 5218,5224 ----
***************
*** 5352,5359 ****
  }
  
  /* Initialize the compiler, and compile the input file.  */
! static void
! do_compile ()
  {
    /* All command line options have been parsed; allow the front end to
       perform consistency checks, etc.  */
--- 5346,5353 ----
  }
  
  /* Initialize the compiler, and compile the input file.  */
! static bool
! init_compile ()
  {
    /* All command line options have been parsed; allow the front end to
       perform consistency checks, etc.  */
***************
*** 5362,5370 ****
    /* The bulk of command line switch processing.  */
    process_options ();
  
!   /* If an error has already occurred, give up.  */
!   if (errorcount)
!     return;
  
    if (aux_base_name)
      /*NOP*/;
--- 5356,5380 ----
    /* The bulk of command line switch processing.  */
    process_options ();
  
!   /* init_emit_once uses reg_raw_mode and therefore must be called
!      after init_reg_modes which initialized reg_raw_mode.  */
!   init_reg_modes ();
!   init_emit_once (debug_info_level == DINFO_LEVEL_NORMAL
! 		  || debug_info_level == DINFO_LEVEL_VERBOSE
! #ifdef VMS_DEBUGGING_INFO
! 		    /* Enable line number info for traceback */
! 		    || debug_info_level > DINFO_LEVEL_NONE
! #endif
! 		    || flag_test_coverage
! 		    || warn_notreached);
! 
!   (*lang_hooks.initially) ();
!   return no_backend;
! }
! 
! static void
! do_compile ()
! {
  
    if (aux_base_name)
      /*NOP*/;
***************
*** 5398,5403 ****
--- 5408,5446 ----
    timevar_print (stderr);
  }
  
+ extern int
+ server_get_filename (void);
+ int
+ server_get_filename ()
+ {
+   char buffer[1024];
+   int len;
+ 
+   if (fgets (buffer, 1024, stdin) == NULL)
+     return 0;
+   len = strlen (buffer);
+   if (len == 0)
+     return 0;
+   if (buffer[len-1] == '\n')
+     buffer[--len] = '\0';
+   filename = xmalloc (len+1);
+   strcpy (filename, buffer);
+ 
+   if (fgets (buffer, 1024, stdin) == NULL)
+     return 0;
+   len = strlen (buffer);
+   if (len == 0)
+     return 0;
+   if (buffer[len-1] == '\n')
+     buffer[--len] = '\0';
+   asm_file_name = xmalloc (len+1);
+   strcpy (asm_file_name, buffer);
+ 
+   if (! quiet_flag)
+     fprintf (stderr, "serve '%s' -o '%s'\n", filename, asm_file_name);
+   return 1;
+ }
+ 
  /* Entry point of cc1, cc1plus, jc1, f771, etc.
     Decode command args, then call compile_file.
     Exit code is FATAL_EXIT_CODE if can't open files or if there were
***************
*** 5419,5425 ****
  
    /* Exit early if we can (e.g. -help).  */
    if (!exit_after_options)
!     do_compile ();
  
    if (errorcount || sorrycount)
      return (FATAL_EXIT_CODE);
--- 5462,5482 ----
  
    /* Exit early if we can (e.g. -help).  */
    if (!exit_after_options)
!     {
!       no_backend = init_compile ();
! 
!       /* If an error has already occurred, give up.  */
!       if (! errorcount)
! 	{
! 	  if (is_server)
! 	    {
! 	      while (server_get_filename ())
! 		do_compile ();
! 	    }
! 	  else
! 	    do_compile ();
! 	}
!     }
  
    if (errorcount || sorrycount)
      return (FATAL_EXIT_CODE);
Index: c-common.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.def,v
retrieving revision 1.13
diff -c -r1.13 c-common.def
*** c-common.def	29 Sep 2002 13:16:42 -0000	1.13
--- c-common.def	8 Feb 2003 20:05:35 -0000
***************
*** 28,33 ****
--- 28,35 ----
  /* A node to remember a source position.  */
  DEFTREECODE (SRCLOC, "srcloc", 'x', 2)
  
+ DEFTREECODE (INCLUDE_FRAGMENT, "include_fragment", 'x', 2)
+ 
  DEFTREECODE (SIZEOF_EXPR, "sizeof_expr", '1', 1)
  DEFTREECODE (ARROW_EXPR, "arrow_expr", 'e', 1)
  DEFTREECODE (ALIGNOF_EXPR, "alignof_expr", '1', 1)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]