This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB 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]

RFC: preprocessor macro support (should actually work now)



This is a revised version of the preprocessor macro support patch I
posted before, tested against the current GCC sources.  I've fixed a
bunch of bugs, and made it tolerant of the GCC bugs that came up.

So please try it out; compile with the -gdwarf-2 -g3 flags.

  Breakpoint 3, value_primitive_field (arg1=0x88dc578, offset=0, fieldno=1, 
      arg_type=0x89f3f70)
      at /home/jimb/cygnus/src/sourceware/gdb/main/src/gdb/values.c:937
  (top-top-gdb) print TYPE_FIELD_BITPOS (arg_type, fieldno)
  $1 = 32
  (top-top-gdb) macro expand TYPE_FIELD_BITPOS (arg_type, fieldno)
  expands to: (((arg_type)->fields[fieldno]).loc.bitpos)
  (top-top-gdb) show macro TYPE_FIELD_BITPOS
  Defined at /home/jimb/cygnus/src/sourceware/gdb/main/src/gdb/gdbtypes.h:811
    included at /home/jimb/cygnus/src/sourceware/gdb/main/src/gdb/values.c:26
    included at /home/jimb/cygnus/src/sourceware/gdb/main/src/gdb/values.c:0
  #define TYPE_FIELD_BITPOS(thistype, n) FIELD_BITPOS(TYPE_FIELD(thistype,n))
  (top-top-gdb) 

I'll start breaking it into individual patches and submitting it soon.


Index: gdb/Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.166
diff -c -r1.166 Makefile.in
*** gdb/Makefile.in	2002/03/27 05:10:38	1.166
--- gdb/Makefile.in	2002/03/28 06:50:31
***************
*** 533,538 ****
--- 533,539 ----
  	m2-exp.y m2-lang.c m2-typeprint.c m2-valprint.c main.c maint.c \
  	memattr.c mem-break.c minsyms.c mipsread.c nlmread.c objfiles.c \
  	p-exp.y p-lang.c p-typeprint.c p-valprint.c parse.c \
+ 	macrotab.c macroexp.c macrocmd.c macroscope.c \
  	printcmd.c remote.c remote-nrom.c scm-exp.c scm-lang.c \
  	scm-valprint.c source.c stabsread.c stack.c symfile.c \
  	symmisc.c symtab.c linespec.c target.c thread.c top.c tracepoint.c \
***************
*** 564,569 ****
--- 565,571 ----
  remote-sim_h =	$(INCLUDE_DIR)/remote-sim.h
  demangle_h =    $(INCLUDE_DIR)/demangle.h
  obstack_h =     $(INCLUDE_DIR)/obstack.h
+ splay_tree_h =  $(INCLUDE_DIR)/splay-tree.h
  
  readline_headers = \
  	$(READLINE_SRC)/chardefs.h \
***************
*** 589,595 ****
  bcache_h =	bcache.h
  breakpoint_h =	breakpoint.h $(frame_h) $(value_h)
  buildsym_h =	buildsym.h
! c_lang_h =	c-lang.h $(value_h)
  call_cmds_h =	call-cmds.h
  cli_cmds_h =	$(srcdir)/cli/cli-cmds.h
  cli_decode_h =	$(srcdir)/cli/cli-decode.h $(command_h)
--- 591,597 ----
  bcache_h =	bcache.h
  breakpoint_h =	breakpoint.h $(frame_h) $(value_h)
  buildsym_h =	buildsym.h
! c_lang_h =	c-lang.h $(value_h) $(macroexp_h)
  call_cmds_h =	call-cmds.h
  cli_cmds_h =	$(srcdir)/cli/cli-cmds.h
  cli_decode_h =	$(srcdir)/cli/cli-decode.h $(command_h)
***************
*** 622,627 ****
--- 624,632 ----
  inferior_h =	inferior.h $(breakpoint_h)
  language_h =	language.h
  linespec_h =	linespec.h
+ macroexp_h =	macroexp.h
+ macrotab_h =    macrotab.h $(obstack_h) $(bcache_h)
+ macroscope_h =  macroscope.h $(macrotab_h) $(symtab_h)
  memattr_h =     memattr.h
  monitor_h =	monitor.h
  objfiles_h =	objfiles.h
***************
*** 660,665 ****
--- 665,671 ----
  	gdb-stabs.h $(inferior_h) language.h minimon.h monitor.h \
  	objfiles.h parser-defs.h serial.h solib.h \
  	symfile.h stabsread.h target.h terminal.h typeprint.h xcoffsolib.h \
+ 	macrotab.h macroexp.h macroscope.h \
  	c-lang.h ch-lang.h f-lang.h \
  	jv-lang.h \
  	m2-lang.h  p-lang.h \
***************
*** 702,707 ****
--- 708,714 ----
  	source.o values.o eval.o valops.o valarith.o valprint.o printcmd.o \
  	symtab.o symfile.o symmisc.o linespec.o infcmd.o infrun.o \
  	expprint.o environ.o stack.o thread.o \
+ 	macrotab.o macrocmd.o macroexp.o macroscope.o \
  	event-loop.o event-top.o inf-loop.o completer.o \
  	gdbarch.o arch-utils.o gdbtypes.o copying.o $(DEPFILES) \
  	memattr.o mem-break.o target.o parse.o language.o $(YYOBJ) buildsym.o \
***************
*** 1268,1277 ****
  	$(completer_h) $(gdb_h)
  
  buildsym.o: buildsym.c $(bfd_h) $(buildsym_h) $(complaints_h) $(defs_h) \
! 	$(objfiles_h) $(symfile_h) $(symtab_h) $(gdb_string_h)
  
  c-lang.o: c-lang.c $(c_lang_h) $(defs_h) $(expression_h) $(gdbtypes_h) \
! 	$(language_h) $(parser_defs_h) $(symtab_h)
  
  c-typeprint.o: c-typeprint.c $(c_lang_h) $(defs_h) $(expression_h) \
  	$(gdbcmd_h) $(gdbcore_h) $(gdbtypes_h) $(language_h) $(symtab_h) \
--- 1275,1286 ----
  	$(completer_h) $(gdb_h)
  
  buildsym.o: buildsym.c $(bfd_h) $(buildsym_h) $(complaints_h) $(defs_h) \
! 	$(objfiles_h) $(symfile_h) $(symtab_h) $(gdb_string_h) \
! 	$(macrotab.h)
  
  c-lang.o: c-lang.c $(c_lang_h) $(defs_h) $(expression_h) $(gdbtypes_h) \
! 	$(language_h) $(parser_defs_h) $(symtab_h) $(macroscope_h) \
! 	gdb_assert.h
  
  c-typeprint.o: c-typeprint.c $(c_lang_h) $(defs_h) $(expression_h) \
  	$(gdbcmd_h) $(gdbcore_h) $(gdbtypes_h) $(language_h) $(symtab_h) \
***************
*** 1376,1382 ****
  
  dwarf2read.o: dwarf2read.c $(bfd_h) $(buildsym_h) $(defs_h) \
  	$(expression_h) $(gdbtypes_h) $(language_h) $(objfiles_h) \
! 	$(symfile_h) $(symtab_h) $(gdb_string_h)
  
  elfread.o: elfread.c $(bfd_h) $(buildsym_h) $(complaints_h) $(defs_h) \
  	$(gdb_stabs_h) $(objfiles_h) $(symfile_h) $(symtab_h) $(gdb_string_h) \
--- 1385,1391 ----
  
  dwarf2read.o: dwarf2read.c $(bfd_h) $(buildsym_h) $(defs_h) \
  	$(expression_h) $(gdbtypes_h) $(language_h) $(objfiles_h) \
! 	$(symfile_h) $(symtab_h) $(gdb_string_h) $(macrotab_h)
  
  elfread.o: elfread.c $(bfd_h) $(buildsym_h) $(complaints_h) $(defs_h) \
  	$(gdb_stabs_h) $(objfiles_h) $(symfile_h) $(symtab_h) $(gdb_string_h) \
***************
*** 2089,2094 ****
--- 2098,2110 ----
  linespec.o: linespec.c $(linespec_h) $(defs_h) $(frame_h) $(value_h) \
  	$(objfiles_h) $(symfile_h) $(completer_h) $(symtab_h) \
  	$(demangle_h) $(command_h) $(cp_abi_h)
+ 
+ macroexp.o: macroexp.c $(defs_h) $(macrotab_h)
+ 
+ macrotab.o: macrotab.c $(defs_h) $(obstack_h) $(objfiles_h) $(symtab_h) \
+ 	$(macrotab_h) $(splay_tree_h) gdb_assert.h $(bcache_h)
+ 
+ macroscope.o: macroscope.c $(defs_h) $(macroscope_h)
  
  target.o: target.c $(bfd_h) $(defs_h) $(gdbcmd_h) $(inferior_h) \
  	$(objfiles_h) $(symfile_h) $(target_h) $(gdb_string_h) $(regcache_h)
Index: gdb/blockframe.c
===================================================================
RCS file: /cvs/src/src/gdb/blockframe.c,v
retrieving revision 1.21
diff -c -r1.21 blockframe.c
*** gdb/blockframe.c	2002/02/27 20:04:29	1.21
--- gdb/blockframe.c	2002/03/28 06:50:32
***************
*** 507,513 ****
     in a specified stack frame.  The frame address is assumed valid.  */
  
  struct block *
! get_frame_block (struct frame_info *frame)
  {
    CORE_ADDR pc;
  
--- 507,513 ----
     in a specified stack frame.  The frame address is assumed valid.  */
  
  struct block *
! get_frame_block (struct frame_info *frame, CORE_ADDR *pc_in_block)
  {
    CORE_ADDR pc;
  
***************
*** 520,532 ****
         after the call insn, we probably want to make frame->pc point after
         the call insn anyway.  */
      --pc;
    return block_for_pc (pc);
  }
  
  struct block *
! get_current_block (void)
  {
!   return block_for_pc (read_pc ());
  }
  
  CORE_ADDR
--- 520,541 ----
         after the call insn, we probably want to make frame->pc point after
         the call insn anyway.  */
      --pc;
+ 
+   if (pc_in_block)
+     *pc_in_block = pc;
+ 
    return block_for_pc (pc);
  }
  
  struct block *
! get_current_block (CORE_ADDR *pc_in_block)
  {
!   CORE_ADDR pc = read_pc ();
! 
!   if (pc_in_block)
!     *pc_in_block = pc;
! 
!   return block_for_pc (pc);
  }
  
  CORE_ADDR
***************
*** 559,565 ****
  struct symbol *
  get_frame_function (struct frame_info *frame)
  {
!   register struct block *bl = get_frame_block (frame);
    if (bl == 0)
      return 0;
    return block_function (bl);
--- 568,574 ----
  struct symbol *
  get_frame_function (struct frame_info *frame)
  {
!   register struct block *bl = get_frame_block (frame, 0);
    if (bl == 0)
      return 0;
    return block_function (bl);
Index: gdb/breakpoint.c
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.67
diff -c -r1.67 breakpoint.c
*** gdb/breakpoint.c	2002/03/06 06:28:33	1.67
--- gdb/breakpoint.c	2002/03/28 06:50:36
***************
*** 5621,5627 ****
       but it's better than a core dump.  */
    if (selected_frame == NULL)
      error ("No selected frame.");
!   block = get_frame_block (selected_frame);
    pc = selected_frame->pc;
  
    sals.nelts = 0;
--- 5621,5627 ----
       but it's better than a core dump.  */
    if (selected_frame == NULL)
      error ("No selected frame.");
!   block = get_frame_block (selected_frame, 0);
    pc = selected_frame->pc;
  
    sals.nelts = 0;
Index: gdb/buildsym.c
===================================================================
RCS file: /cvs/src/src/gdb/buildsym.c,v
retrieving revision 1.14
diff -c -r1.14 buildsym.c
*** gdb/buildsym.c	2002/01/20 19:42:04	1.14
--- gdb/buildsym.c	2002/03/28 06:50:36
***************
*** 39,44 ****
--- 39,45 ----
  #include "language.h"		/* For "longest_local_hex_string_custom" */
  #include "bcache.h"
  #include "filenames.h"		/* For DOSish file names */
+ #include "macrotab.h"
  /* Ask buildsym.h to define the vars it normally declares `extern'.  */
  #define	EXTERN
  /**/
***************
*** 192,197 ****
--- 193,201 ----
        xfree ((void *) next);
      }
    global_symbols = NULL;
+ 
+   if (pending_macros)
+     free_macro_table (pending_macros);
  }
  
  /* This function is called to discard any pending blocks. */
***************
*** 883,889 ****
    if (pending_blocks == NULL
        && file_symbols == NULL
        && global_symbols == NULL
!       && have_line_numbers == 0)
      {
        /* Ignore symtabs that have no functions with real debugging
           info.  */
--- 887,894 ----
    if (pending_blocks == NULL
        && file_symbols == NULL
        && global_symbols == NULL
!       && have_line_numbers == 0
!       && pending_macros == NULL)
      {
        /* Ignore symtabs that have no functions with real debugging
           info.  */
***************
*** 944,949 ****
--- 949,955 ----
  
  	  /* Fill in its components.  */
  	  symtab->blockvector = blockvector;
+           symtab->macro_table = pending_macros;
  	  if (subfile->line_vector)
  	    {
  	      /* Reallocate the line table on the symbol obstack */
***************
*** 1022,1027 ****
--- 1028,1034 ----
  
    last_source_file = NULL;
    current_subfile = NULL;
+   pending_macros = NULL;
  
    return symtab;
  }
***************
*** 1112,1117 ****
--- 1119,1125 ----
    file_symbols = NULL;
    global_symbols = NULL;
    pending_blocks = NULL;
+   pending_macros = NULL;
  }
  
  /* Initialize anything that needs initializing when a completely new
Index: gdb/buildsym.h
===================================================================
RCS file: /cvs/src/src/gdb/buildsym.h,v
retrieving revision 1.3
diff -c -r1.3 buildsym.h
*** gdb/buildsym.h	2001/03/06 08:21:06	1.3
--- gdb/buildsym.h	2002/03/28 06:50:37
***************
*** 296,301 ****
--- 296,305 ----
  extern void merge_symbol_lists (struct pending **srclist,
  				struct pending **targetlist);
  
+ /* The macro table for the compilation unit whose symbols we're
+    currently reading.  All the symtabs for this CU will point to this.  */
+ EXTERN struct macro_table *pending_macros;
+ 
  #undef EXTERN
  
  #endif /* defined (BUILDSYM_H) */
Index: gdb/c-exp.y
===================================================================
RCS file: /cvs/src/src/gdb/c-exp.y,v
retrieving revision 1.7
diff -c -r1.7 c-exp.y
*** gdb/c-exp.y	2001/11/15 01:55:59	1.7
--- gdb/c-exp.y	2002/03/28 06:50:37
***************
*** 1218,1223 ****
--- 1218,1234 ----
     
   retry:
  
+   /* Check if this is a macro invocation that we need to expand.  */
+   if (! scanning_macro_expansion ())
+     {
+       char *expanded = macro_expand_next (&lexptr,
+                                           expression_macro_lookup_func,
+                                           expression_macro_lookup_baton);
+ 
+       if (expanded)
+         scan_macro_expansion (expanded);
+     }
+ 
    unquoted_expr = 1;
  
    tokstart = lexptr;
***************
*** 1242,1248 ****
    switch (c = *tokstart)
      {
      case 0:
!       return 0;
  
      case ' ':
      case '\t':
--- 1253,1269 ----
    switch (c = *tokstart)
      {
      case 0:
!       /* If we were just scanning the result of a macro expansion,
!          then we need to resume scanning the original text.
!          Otherwise, we were already scanning the original text, and
!          we're really done.  */
!       if (scanning_macro_expansion ())
!         {
!           finished_macro_expansion ();
!           goto retry;
!         }
!       else
!         return 0;
  
      case ' ':
      case '\t':
***************
*** 1295,1301 ****
        return c;
  
      case ',':
!       if (comma_terminates && paren_depth == 0)
  	return 0;
        lexptr++;
        return c;
--- 1316,1324 ----
        return c;
  
      case ',':
!       if (comma_terminates
!           && paren_depth == 0
!           && ! scanning_macro_expansion ())
  	return 0;
        lexptr++;
        return c;
***************
*** 1474,1482 ****
        c = tokstart[++namelen];
      }
  
!   /* The token "if" terminates the expression and is NOT 
!      removed from the input stream.  */
!   if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
      {
        return 0;
      }
--- 1497,1509 ----
        c = tokstart[++namelen];
      }
  
!   /* The token "if" terminates the expression and is NOT removed from
!      the input stream.  It doesn't count if it appears in the
!      expansion of a macro.  */
!   if (namelen == 2
!       && tokstart[0] == 'i'
!       && tokstart[1] == 'f'
!       && ! scanning_macro_expansion ())
      {
        return 0;
      }
Index: gdb/c-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/c-lang.c,v
retrieving revision 1.11
diff -c -r1.11 c-lang.c
*** gdb/c-lang.c	2002/03/21 00:53:44	1.11
--- gdb/c-lang.c	2002/03/28 06:50:38
***************
*** 27,32 ****
--- 27,34 ----
  #include "language.h"
  #include "c-lang.h"
  #include "valprint.h"
+ #include "macroscope.h"
+ #include "gdb_assert.h"
  
  extern void _initialize_c_language (void);
  static void c_emit_char (int c, struct ui_file * stream, int quoter);
***************
*** 371,377 ****
--- 373,484 ----
    return (type);
  }
  
+ /* Preprocessing and parsing C and C++ expressions.  */
  
+ 
+ /* When we find that lexptr (the global var defined in parse.c) is
+    pointing at a macro invocation, we expand the invocation, and call
+    scan_macro_expansion to save the old lexptr here and point lexptr
+    into the expanded text.  When we reach the end of that, we call
+    end_macro_expansion to pop back to the value we saved here.  The
+    macro expansion code promises to return only fully-expanded text,
+    so we don't need to "push" more than one level.
+ 
+    This is disgusting, of course.  It would be cleaner to do all macro
+    expansion beforehand, and then hand that to lexptr.  But we don't
+    really know where the expression ends.  Remember, in a command like
+ 
+      (gdb) break *ADDRESS if CONDITION
+ 
+    we evaluate ADDRESS in the scope of the current frame, but we
+    evaluate CONDITION in the scope of the breakpoint's location.  So
+    it's simply wrong to try to macro-expand the whole thing at once.  */
+ static char *macro_original_text;
+ static char *macro_expanded_text;
+ 
+ 
+ void
+ scan_macro_expansion (char *expansion)
+ {
+   /* We'd better not be trying to push the stack twice.  */
+   gdb_assert (! macro_original_text);
+   gdb_assert (! macro_expanded_text);
+ 
+   /* Save the old lexptr value, so we can return to it when we're done
+      parsing the expanded text.  */
+   macro_original_text = lexptr;
+   lexptr = expansion;
+ 
+   /* Save the expanded text, so we can free it when we're finished.  */
+   macro_expanded_text = expansion;
+ }
+ 
+ 
+ int
+ scanning_macro_expansion ()
+ {
+   return macro_original_text != 0;
+ }
+ 
+ 
+ void 
+ finished_macro_expansion ()
+ {
+   /* There'd better be something to pop back to, and we better have
+      saved a pointer to the start of the expanded text.  */
+   gdb_assert (macro_original_text);
+   gdb_assert (macro_expanded_text);
+ 
+   /* Pop back to the original text.  */
+   lexptr = macro_original_text;
+   macro_original_text = 0;
+ 
+   /* Free the expanded text.  */
+   xfree (macro_expanded_text);
+   macro_expanded_text = 0;
+ }
+ 
+ 
+ static void
+ scan_macro_cleanup (void *dummy)
+ {
+   if (macro_original_text)
+     finished_macro_expansion ();
+ }
+ 
+ 
+ /* We set these global variables before calling c_parse, to tell it
+    how it to find macro definitions for the expression at hand.  */
+ macro_lookup_ftype *expression_macro_lookup_func;
+ void *expression_macro_lookup_baton;
+ 
+ static int
+ c_preprocess_and_parse ()
+ {
+   /* Set up a lookup function for the macro expander.  */
+   struct macro_scope *scope = 0;
+   struct cleanup *back_to = make_cleanup (free_current_contents, &scope);
+ 
+   if (expression_context_block)
+     scope = sal_macro_scope (find_pc_line (expression_context_pc, 0));
+   else
+     scope = default_macro_scope ();
+ 
+   expression_macro_lookup_func = standard_macro_lookup;
+   expression_macro_lookup_baton = (void *) scope;
+ 
+   gdb_assert (! macro_original_text);
+   make_cleanup (scan_macro_cleanup, 0);
+ 
+   {
+     int result = c_parse ();
+     do_cleanups (back_to);
+     return result;
+   }
+ }
+ 
+ 
+ 
  /* Table mapping opcodes into strings for printing operators
     and precedences of the operators.  */
  
***************
*** 439,445 ****
    range_check_off,
    type_check_off,
    case_sensitive_on,
!   c_parse,
    c_error,
    evaluate_subexp_standard,
    c_printchar,			/* Print a character constant */
--- 546,552 ----
    range_check_off,
    type_check_off,
    case_sensitive_on,
!   c_preprocess_and_parse,
    c_error,
    evaluate_subexp_standard,
    c_printchar,			/* Print a character constant */
***************
*** 491,497 ****
    range_check_off,
    type_check_off,
    case_sensitive_on,
!   c_parse,
    c_error,
    evaluate_subexp_standard,
    c_printchar,			/* Print a character constant */
--- 598,604 ----
    range_check_off,
    type_check_off,
    case_sensitive_on,
!   c_preprocess_and_parse,
    c_error,
    evaluate_subexp_standard,
    c_printchar,			/* Print a character constant */
***************
*** 520,526 ****
    range_check_off,
    type_check_off,
    case_sensitive_on,
!   c_parse,
    c_error,
    evaluate_subexp_standard,
    c_printchar,			/* Print a character constant */
--- 627,633 ----
    range_check_off,
    type_check_off,
    case_sensitive_on,
!   c_preprocess_and_parse,
    c_error,
    evaluate_subexp_standard,
    c_printchar,			/* Print a character constant */
Index: gdb/c-lang.h
===================================================================
RCS file: /cvs/src/src/gdb/c-lang.h,v
retrieving revision 1.4
diff -c -r1.4 c-lang.h
*** gdb/c-lang.h	2002/02/13 18:49:29	1.4
--- gdb/c-lang.h	2002/03/28 06:50:38
***************
*** 24,29 ****
--- 24,30 ----
  #define C_LANG_H 1
  
  #include "value.h"
+ #include "macroexp.h"
  
  
  extern int c_parse (void);	/* Defined in c-exp.y */
***************
*** 48,53 ****
--- 49,61 ----
  extern void c_printstr (struct ui_file * stream, char *string,
  			unsigned int length, int width,
  			int force_ellipses);
+ 
+ extern void scan_macro_expansion (char *expansion);
+ extern int scanning_macro_expansion (void);
+ extern void finished_macro_expansion (void);
+ 
+ extern macro_lookup_ftype *expression_macro_lookup_func;
+ extern void *expression_macro_lookup_baton;
  
  extern struct type *c_create_fundamental_type (struct objfile *, int);
  
Index: gdb/configure.in
===================================================================
RCS file: /cvs/src/src/gdb/configure.in,v
retrieving revision 1.84
diff -c -r1.84 configure.in
*** gdb/configure.in	2002/03/15 00:44:49	1.84
--- gdb/configure.in	2002/03/28 06:50:39
***************
*** 130,135 ****
--- 130,136 ----
  AC_HEADER_STAT
  
  AC_C_CONST
+ AC_C_INLINE
  
  AC_CHECK_FUNCS(bcopy btowc bzero canonicalize_file_name isascii poll \
  	realpath sbrk setpgid setpgrp sigaction sigprocmask sigsetmask )
Index: gdb/dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.51
diff -c -r1.51 dwarf2read.c
*** gdb/dwarf2read.c	2002/03/21 00:53:44	1.51
--- gdb/dwarf2read.c	2002/03/28 06:50:41
***************
*** 37,42 ****
--- 37,43 ----
  #include "demangle.h"
  #include "expression.h"
  #include "filenames.h"	/* for DOSish file names */
+ #include "macrotab.h"
  
  #include "language.h"
  #include "complaints.h"
***************
*** 175,193 ****
                                           4 or 12 */
    };
  
! /* The data in the .debug_line statement prologue looks like this.  */
! struct line_head
    {
!     unsigned int total_length;
!     unsigned short version;
!     unsigned int prologue_length;
!     unsigned char minimum_instruction_length;
!     unsigned char default_is_stmt;
!     int line_base;
!     unsigned char line_range;
!     unsigned char opcode_base;
!     unsigned char *standard_opcode_lengths;
!   };
  
  /* When we construct a partial symbol table entry we only
     need this much information. */
--- 176,225 ----
                                           4 or 12 */
    };
  
! /* The line number information for a compilation unit (found in the
!    .debug_line section) begins with a "statement program prologue",
!    which contains the following information.  */
! struct line_prologue
! {
!   unsigned int total_length;
!   unsigned short version;
!   unsigned int prologue_length;
!   unsigned char minimum_instruction_length;
!   unsigned char default_is_stmt;
!   int line_base;
!   unsigned char line_range;
!   unsigned char opcode_base;
! 
!   /* standard_opcode_lengths[i] is the number of operands for the
!      standard opcode whose value is i.  This means that
!      standard_opcode_lengths[0] is unused, and the last meaningful
!      element is standard_opcode_lengths[opcode_base - 1].  */
!   unsigned char *standard_opcode_lengths;
! 
!   /* The include_directories table.  NOTE!  These strings are not
!      allocated with xmalloc; instead, they are pointers into
!      debug_line_buffer.  If you try to free them, `free' will get
!      indigestion.  */
!   unsigned int num_include_dirs, include_dirs_size;
!   char **include_dirs;
! 
!   /* The file_names table.  NOTE!  These strings are not allocated
!      with xmalloc; instead, they are pointers into debug_line_buffer.
!      Don't try to free them directly.  */
!   unsigned int num_file_names, file_names_size;
!   struct file_entry
    {
!     char *name;
!     unsigned int dir_index;
!     unsigned int mod_time;
!     unsigned int length;
!   } *file_names;
! 
!   /* The start and end of the statement program following this
!      prologue.  These point into dwarf_line_buffer.  */
!   char *statement_program_start, *statement_program_end;
! };
! 
  
  /* When we construct a partial symbol table entry we only
     need this much information. */
***************
*** 310,315 ****
--- 342,348 ----
  static char *dwarf_abbrev_buffer;
  static char *dwarf_line_buffer;
  static char *dwarf_str_buffer;
+ static char *dwarf_macinfo_buffer;
  
  /* A zeroed version of a partial die for initialization purposes.  */
  static struct partial_die_info zeroed_partial_die;
***************
*** 399,404 ****
--- 432,446 ----
      /* Size of dwarf string section for the objfile.  */
  
      unsigned int dwarf_str_size;
+ 
+     /* Pointer to start of dwarf macro buffer for the objfile.  */
+ 
+     char *dwarf_macinfo_buffer;
+ 
+     /* Size of dwarf macinfo section for the objfile.  */
+     
+     unsigned int dwarf_macinfo_size;
+ 
    };
  
  #define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private)
***************
*** 409,414 ****
--- 451,458 ----
  #define DWARF_LINE_BUFFER(p) (PST_PRIVATE(p)->dwarf_line_buffer)
  #define DWARF_STR_BUFFER(p)  (PST_PRIVATE(p)->dwarf_str_buffer)
  #define DWARF_STR_SIZE(p)    (PST_PRIVATE(p)->dwarf_str_size)
+ #define DWARF_MACINFO_BUFFER(p) (PST_PRIVATE(p)->dwarf_macinfo_buffer)
+ #define DWARF_MACINFO_SIZE(p)   (PST_PRIVATE(p)->dwarf_macinfo_size)
  
  /* Maintain an array of referenced fundamental types for the current
     compilation unit being read.  For DWARF version 1, we have to construct
***************
*** 492,497 ****
--- 536,545 ----
  {
    "missing .debug_line section", 0, 0
  };
+ static struct complaint dwarf2_statement_list_fits_in_line_number_section =
+ {
+   "statement list doesn't fit in .debug_line section", 0, 0
+ };
  static struct complaint dwarf2_mangled_line_number_section =
  {
    "mangled .debug_line section", 0, 0
***************
*** 560,565 ****
--- 608,645 ----
  {
    "unsupported const value attribute form: '%s'", 0, 0
  };
+ static struct complaint dwarf2_line_prologue_too_long =
+ {
+   "line number info prologue doesn't fit in `.debug_line' section", 0, 0
+ };
+ static struct complaint dwarf2_missing_macinfo_section =
+ {
+   "missing .debug_macinfo section", 0, 0
+ };
+ static struct complaint dwarf2_macros_too_long =
+ {
+   "macro info runs off end of `.debug_macinfo' section", 0, 0
+ };
+ static struct complaint dwarf2_macros_not_terminated =
+ {
+   "no terminating 0-type entry for macros in `.debug_macinfo' section", 0, 0
+ };
+ static struct complaint dwarf2_macro_outside_file =
+ {
+   "debug info gives macro %s outside of any file: %s", 0, 0
+ };
+ static struct complaint dwarf2_macro_unmatched_end_file =
+ {
+   "macro debug info has an unmatched `close_file' directive", 0, 0
+ };
+ static struct complaint dwarf2_macro_malformed_definition =
+ {
+   "macro debug info contains a malformed macro definition:\n`%s'", 0, 0
+ };
+ static struct complaint dwarf2_macro_spaces_in_definition =
+ {
+   "macro definition contains spaces in formal argument list:\n`%s'", 0, 0
+ };
  
  /* local function prototypes */
  
***************
*** 639,645 ****
  
  static int die_is_declaration (struct die_info *);
  
! static void dwarf_decode_lines (unsigned int, char *, bfd *,
  				const struct comp_unit_head *);
  
  static void dwarf2_start_subfile (char *, char *);
--- 719,732 ----
  
  static int die_is_declaration (struct die_info *);
  
! static void free_line_prologue (struct line_prologue *lp);
! 
! static struct line_prologue *(dwarf_decode_line_prologue
!                               (unsigned int offset,
!                                bfd *abfd,
!                                const struct comp_unit_head *cu_header));
! 
! static void dwarf_decode_lines (struct line_prologue *, char *, bfd *,
  				const struct comp_unit_head *);
  
  static void dwarf2_start_subfile (char *, char *);
***************
*** 794,808 ****
  
  static struct die_info *dwarf_alloc_die (void);
  
  /* Try to locate the sections we need for DWARF 2 debugging
     information and return true if we have enough to do something.  */
  
  int
  dwarf2_has_info (bfd *abfd)
  {
!   dwarf_info_offset = dwarf_abbrev_offset = dwarf_line_offset = 0;
    dwarf_str_offset = 0;
!   dwarf_frame_offset = dwarf_eh_frame_offset = 0;
    bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL);
    if (dwarf_info_offset && dwarf_abbrev_offset)
      {
--- 881,903 ----
  
  static struct die_info *dwarf_alloc_die (void);
  
+ static void dwarf_decode_macros (struct line_prologue *, unsigned int,
+                                  char *, bfd *, const struct comp_unit_head *,
+                                  struct objfile *);
+ 
  /* Try to locate the sections we need for DWARF 2 debugging
     information and return true if we have enough to do something.  */
  
  int
  dwarf2_has_info (bfd *abfd)
  {
!   dwarf_info_offset = 0;
!   dwarf_abbrev_offset = 0;
!   dwarf_line_offset = 0;
    dwarf_str_offset = 0;
!   dwarf_macinfo_offset = 0;
!   dwarf_frame_offset = 0;
!   dwarf_eh_frame_offset = 0;
    bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL);
    if (dwarf_info_offset && dwarf_abbrev_offset)
      {
***************
*** 890,902 ****
    dwarf_line_buffer = dwarf2_read_section (objfile,
  					   dwarf_line_offset,
  					   dwarf_line_size);
- 
    if (dwarf_str_offset)
      dwarf_str_buffer = dwarf2_read_section (objfile,
  					    dwarf_str_offset,
  					    dwarf_str_size);
    else
      dwarf_str_buffer = NULL;
  
    if (mainline
        || (objfile->global_psymbols.size == 0
--- 985,1002 ----
    dwarf_line_buffer = dwarf2_read_section (objfile,
  					   dwarf_line_offset,
  					   dwarf_line_size);
    if (dwarf_str_offset)
      dwarf_str_buffer = dwarf2_read_section (objfile,
  					    dwarf_str_offset,
  					    dwarf_str_size);
    else
      dwarf_str_buffer = NULL;
+   if (dwarf_macinfo_offset)
+     dwarf_macinfo_buffer = dwarf2_read_section (objfile,
+                                                 dwarf_macinfo_offset,
+                                                 dwarf_macinfo_size);
+   else
+     dwarf_macinfo_buffer = NULL;
  
    if (mainline
        || (objfile->global_psymbols.size == 0
***************
*** 1105,1110 ****
--- 1205,1212 ----
        DWARF_LINE_BUFFER (pst) = dwarf_line_buffer;
        DWARF_STR_BUFFER (pst) = dwarf_str_buffer;
        DWARF_STR_SIZE (pst) = dwarf_str_size;
+       DWARF_MACINFO_BUFFER (pst) = dwarf_macinfo_buffer;
+       DWARF_MACINFO_SIZE (pst) = dwarf_macinfo_size;
        baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
  
        /* Store the function that reads in the rest of the symbol table */
***************
*** 1406,1411 ****
--- 1508,1515 ----
    dwarf_line_buffer = DWARF_LINE_BUFFER (pst);
    dwarf_str_buffer = DWARF_STR_BUFFER (pst);
    dwarf_str_size = DWARF_STR_SIZE (pst);
+   dwarf_macinfo_buffer = DWARF_MACINFO_BUFFER (pst);
+   dwarf_macinfo_size = DWARF_MACINFO_SIZE (pst);
    baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile));
    cu_header_offset = offset;
    info_ptr = dwarf_info_buffer + offset;
***************
*** 1541,1551 ****
      }
  }
  
  static void
  read_file_scope (struct die_info *die, struct objfile *objfile,
  		 const struct comp_unit_head *cu_header)
  {
-   unsigned int line_offset = 0;
    CORE_ADDR lowpc = ((CORE_ADDR) -1);
    CORE_ADDR highpc = ((CORE_ADDR) 0);
    struct attribute *attr;
--- 1645,1655 ----
      }
  }
  
+ 
  static void
  read_file_scope (struct die_info *die, struct objfile *objfile,
  		 const struct comp_unit_head *cu_header)
  {
    CORE_ADDR lowpc = ((CORE_ADDR) -1);
    CORE_ADDR highpc = ((CORE_ADDR) 0);
    struct attribute *attr;
***************
*** 1553,1558 ****
--- 1657,1663 ----
    char *comp_dir = NULL;
    struct die_info *child_die;
    bfd *abfd = objfile->obfd;
+   struct line_prologue *line_prologue = 0;
  
    if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
      {
***************
*** 1637,1646 ****
    attr = dwarf_attr (die, DW_AT_stmt_list);
    if (attr)
      {
!       line_offset = DW_UNSND (attr);
!       dwarf_decode_lines (line_offset, comp_dir, abfd, cu_header);
      }
  
    /* Process all dies in compilation unit.  */
    if (die->has_children)
      {
--- 1742,1778 ----
    attr = dwarf_attr (die, DW_AT_stmt_list);
    if (attr)
      {
!       unsigned int line_offset = DW_UNSND (attr);
!       line_prologue = dwarf_decode_line_prologue (line_offset,
!                                                   abfd, cu_header);
!       if (line_prologue)
!         {
!           make_cleanup ((make_cleanup_ftype *) free_line_prologue,
!                         (void *) line_prologue);
!           dwarf_decode_lines (line_prologue, comp_dir, abfd, cu_header);
!         }
      }
  
+ 
+   /* Decode macro information, if present.  Dwarf 2 macro information
+      refers to information in the line number info statement program
+      prologue, so we can only read it if we've read the prologue
+      successfully.  */
+ #if 1
+   attr = dwarf_attr (die, DW_AT_macro_info);
+   if (attr)
+     {
+       unsigned int macro_offset = DW_UNSND (attr);
+       dwarf_decode_macros (line_prologue, macro_offset,
+                            comp_dir, abfd, cu_header, objfile);
+     }
+ #else
+   /* A hack for testing.  */
+   if (dwarf_macinfo_buffer
+       && dwarf_macinfo_size > 0)
+     dwarf_decode_macros (line_prologue, 0, comp_dir, abfd, cu_header, objfile);
+ #endif
+ 
    /* Process all dies in compilation unit.  */
    if (die->has_children)
      {
***************
*** 3885,3971 ****
  	  && ! dwarf_attr (die, DW_AT_specification));
  }
  
! /* Decode the line number information for the compilation unit whose
!    line number info is at OFFSET in the .debug_line section.
!    The compilation directory of the file is passed in COMP_DIR.  */
  
! struct filenames
  {
!   unsigned int num_files;
!   struct fileinfo
      {
!       char *name;
!       unsigned int dir;
!       unsigned int time;
!       unsigned int size;
      }
!    *files;
! };
  
! struct directories
!   {
!     unsigned int num_dirs;
!     char **dirs;
!   };
  
  static void
! dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd,
! 		    const struct comp_unit_head *cu_header)
  {
!   char *line_ptr;
!   char *line_end;
!   struct line_head lh;
!   struct cleanup *back_to;
!   unsigned int i, bytes_read;
!   char *cur_file, *cur_dir;
!   unsigned char op_code, extended_op, adj_opcode;
  
! #define FILE_ALLOC_CHUNK 5
! #define DIR_ALLOC_CHUNK 5
  
!   struct filenames files;
!   struct directories dirs;
  
    if (dwarf_line_buffer == NULL)
      {
        complain (&dwarf2_missing_line_number_section);
!       return;
      }
  
!   files.num_files = 0;
!   files.files = NULL;
  
!   dirs.num_dirs = 0;
!   dirs.dirs = NULL;
  
    line_ptr = dwarf_line_buffer + offset;
  
    /* read in the prologue */
!   lh.total_length = read_initial_length (abfd, line_ptr, NULL, &bytes_read);
    line_ptr += bytes_read;
!   line_end = line_ptr + lh.total_length;
!   lh.version = read_2_bytes (abfd, line_ptr);
    line_ptr += 2;
!   lh.prologue_length = read_offset (abfd, line_ptr, cu_header, &bytes_read);
    line_ptr += bytes_read;
!   lh.minimum_instruction_length = read_1_byte (abfd, line_ptr);
    line_ptr += 1;
!   lh.default_is_stmt = read_1_byte (abfd, line_ptr);
    line_ptr += 1;
!   lh.line_base = read_1_signed_byte (abfd, line_ptr);
    line_ptr += 1;
!   lh.line_range = read_1_byte (abfd, line_ptr);
    line_ptr += 1;
!   lh.opcode_base = read_1_byte (abfd, line_ptr);
    line_ptr += 1;
!   lh.standard_opcode_lengths = (unsigned char *)
!     xmalloc (lh.opcode_base * sizeof (unsigned char));
!   back_to = make_cleanup (free_current_contents, &lh.standard_opcode_lengths);
  
!   lh.standard_opcode_lengths[0] = 1;
!   for (i = 1; i < lh.opcode_base; ++i)
      {
!       lh.standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);
        line_ptr += 1;
      }
  
--- 4017,4169 ----
  	  && ! dwarf_attr (die, DW_AT_specification));
  }
  
! 
! /* Free the line_prologue structure *LP, and any arrays and strings it
!    refers to.  */
! static void
! free_line_prologue (struct line_prologue *lp)
! {
!   if (lp->standard_opcode_lengths)
!     free (lp->standard_opcode_lengths);
  
!   /* Remember that all the lp->file_names[i].name pointers are
!      pointers into debug_line_buffer, and don't need to be freed.  */
!   if (lp->file_names)
!     free (lp->file_names);
! 
!   /* Similarly for the include directory names.  */
!   if (lp->include_dirs)
!     free (lp->include_dirs);
! 
!   free (lp);
! }
! 
! 
! /* Add an entry to LP's include directory table.  */
! static void
! add_include_dir (struct line_prologue *lp, char *include_dir)
  {
!   /* Grow the array if necessary.  */
!   if (lp->include_dirs_size == 0)
      {
!       lp->include_dirs_size = 1; /* for testing */
!       lp->include_dirs = xmalloc (lp->include_dirs_size
!                                   * sizeof (*lp->include_dirs));
      }
!   else if (lp->num_include_dirs >= lp->include_dirs_size)
!     {
!       lp->include_dirs_size *= 2;
!       lp->include_dirs = xrealloc (lp->include_dirs,
!                                    (lp->include_dirs_size
!                                     * sizeof (*lp->include_dirs)));
!     }
  
!   lp->include_dirs[lp->num_include_dirs++] = include_dir;
! }
!  
  
+ /* Add an entry to LP's file name table.  */
  static void
! add_file_name (struct line_prologue *lp,
!                char *name,
!                unsigned int dir_index,
!                unsigned int mod_time,
!                unsigned int length)
  {
!   struct file_entry *fe;
! 
!   /* Grow the array if necessary.  */
!   if (lp->file_names_size == 0)
!     {
!       lp->file_names_size = 1; /* for testing */
!       lp->file_names = xmalloc (lp->file_names_size
!                                 * sizeof (*lp->file_names));
!     }
!   else if (lp->num_file_names >= lp->file_names_size)
!     {
!       lp->file_names_size *= 2;
!       lp->file_names = xrealloc (lp->file_names,
!                                  (lp->file_names_size
!                                   * sizeof (*lp->file_names)));
!     }
  
!   fe = &lp->file_names[lp->num_file_names++];
!   fe->name = name;
!   fe->dir_index = dir_index;
!   fe->mod_time = mod_time;
!   fe->length = length;
! }
!  
  
! /* Read the statement program prologue starting at OFFSET in
!    dwarf_line_buffer, according to the endianness of ABFD.  Return a
!    pointer to a struct line_prologue, allocated using xmalloc.
! 
!    NOTE: the strings in the include directory and file name tables of
!    the returned object point into debug_line_buffer, and must not be
!    freed.  */
! static struct line_prologue *
! dwarf_decode_line_prologue (unsigned int offset, bfd *abfd,
!                             const struct comp_unit_head *cu_header)
! {
!   struct cleanup *back_to;
!   struct line_prologue *lp;
!   char *line_ptr;
!   int bytes_read;
!   int i;
!   char *cur_dir, *cur_file;
  
    if (dwarf_line_buffer == NULL)
      {
        complain (&dwarf2_missing_line_number_section);
!       return 0;
      }
  
!   /* Make sure that at least there's room for the total_length field.  That
!      could be 12 bytes long, but we're just going to fudge that.  */
!   if (offset + 4 >= dwarf_line_size)
!     {
!       complain (&dwarf2_statement_list_fits_in_line_number_section);
!       return 0;
!     }
  
!   lp = xmalloc (sizeof (*lp));
!   memset (lp, 0, sizeof (*lp));
!   back_to = make_cleanup ((make_cleanup_ftype *) free_line_prologue,
!                           (void *) lp);
  
    line_ptr = dwarf_line_buffer + offset;
  
    /* read in the prologue */
!   lp->total_length = read_initial_length (abfd, line_ptr, NULL, &bytes_read);
    line_ptr += bytes_read;
!   if (line_ptr + lp->total_length > dwarf_line_buffer + dwarf_line_size)
!     {
!       complain (&dwarf2_statement_list_fits_in_line_number_section);
!       return 0;
!     }
!   lp->statement_program_end = line_ptr + lp->total_length;
!   lp->version = read_2_bytes (abfd, line_ptr);
    line_ptr += 2;
!   lp->prologue_length = read_offset (abfd, line_ptr, cu_header, &bytes_read);
    line_ptr += bytes_read;
!   lp->minimum_instruction_length = read_1_byte (abfd, line_ptr);
    line_ptr += 1;
!   lp->default_is_stmt = read_1_byte (abfd, line_ptr);
    line_ptr += 1;
!   lp->line_base = read_1_signed_byte (abfd, line_ptr);
    line_ptr += 1;
!   lp->line_range = read_1_byte (abfd, line_ptr);
    line_ptr += 1;
!   lp->opcode_base = read_1_byte (abfd, line_ptr);
    line_ptr += 1;
!   lp->standard_opcode_lengths
!     = (unsigned char *) xmalloc (lp->opcode_base * sizeof (unsigned char));
  
!   lp->standard_opcode_lengths[0] = 1;  /* This should never be used anyway.  */
!   for (i = 1; i < lp->opcode_base; ++i)
      {
!       lp->standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);
        line_ptr += 1;
      }
  
***************
*** 3973,4017 ****
    while ((cur_dir = read_string (abfd, line_ptr, &bytes_read)) != NULL)
      {
        line_ptr += bytes_read;
!       if ((dirs.num_dirs % DIR_ALLOC_CHUNK) == 0)
! 	{
! 	  dirs.dirs = (char **)
! 	    xrealloc (dirs.dirs,
! 		      (dirs.num_dirs + DIR_ALLOC_CHUNK) * sizeof (char *));
! 	  if (dirs.num_dirs == 0)
! 	    make_cleanup (free_current_contents, &dirs.dirs);
! 	}
!       dirs.dirs[dirs.num_dirs++] = cur_dir;
      }
    line_ptr += bytes_read;
  
    /* Read file name table */
    while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL)
      {
        line_ptr += bytes_read;
!       if ((files.num_files % FILE_ALLOC_CHUNK) == 0)
! 	{
! 	  files.files = (struct fileinfo *)
! 	    xrealloc (files.files,
! 		      (files.num_files + FILE_ALLOC_CHUNK)
! 		      * sizeof (struct fileinfo));
! 	  if (files.num_files == 0)
! 	    make_cleanup (free_current_contents, &files.files);
! 	}
!       files.files[files.num_files].name = cur_file;
!       files.files[files.num_files].dir =
! 	read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
        line_ptr += bytes_read;
!       files.files[files.num_files].time =
! 	read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
        line_ptr += bytes_read;
!       files.files[files.num_files].size =
! 	read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
        line_ptr += bytes_read;
!       files.num_files++;
      }
    line_ptr += bytes_read;
  
    /* Read the statement sequences until there's nothing left.  */
    while (line_ptr < line_end)
      {
--- 4171,4223 ----
    while ((cur_dir = read_string (abfd, line_ptr, &bytes_read)) != NULL)
      {
        line_ptr += bytes_read;
!       add_include_dir (lp, cur_dir);
      }
    line_ptr += bytes_read;
  
    /* Read file name table */
    while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL)
      {
+       unsigned int dir_index, mod_time, length;
+ 
        line_ptr += bytes_read;
!       dir_index = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
        line_ptr += bytes_read;
!       mod_time = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
        line_ptr += bytes_read;
!       length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
        line_ptr += bytes_read;
! 
!       add_file_name (lp, cur_file, dir_index, mod_time, length);
      }
    line_ptr += bytes_read;
+   lp->statement_program_start = line_ptr; 
  
+   if (line_ptr > dwarf_line_buffer + dwarf_line_size)
+     complain (&dwarf2_line_prologue_too_long);
+ 
+   discard_cleanups (back_to);
+   return lp;
+ }
+ 
+ 
+ /* Decode the line number information for the compilation unit whose
+    line number info is at OFFSET in the .debug_line section.
+    The compilation directory of the file is passed in COMP_DIR.  */
+ 
+ static void
+ dwarf_decode_lines (struct line_prologue *lp, char *comp_dir, bfd *abfd,
+ 		    const struct comp_unit_head *cu_header)
+ {
+   char *line_ptr;
+   char *line_end;
+   unsigned int i, bytes_read;
+   char *cur_dir;
+   unsigned char op_code, extended_op, adj_opcode;
+ 
+   line_ptr = lp->statement_program_start;
+   line_end = lp->statement_program_end;
+ 
    /* Read the statement sequences until there's nothing left.  */
    while (line_ptr < line_end)
      {
***************
*** 4020,4038 ****
        unsigned int file = 1;
        unsigned int line = 1;
        unsigned int column = 0;
!       int is_stmt = lh.default_is_stmt;
        int basic_block = 0;
        int end_sequence = 0;
  
        /* Start a subfile for the current file of the state machine.  */
!       if (files.num_files >= file)
  	{
! 	  /* The file and directory tables are 0 based, the references
! 	     are 1 based.  */
! 	  dwarf2_start_subfile (files.files[file - 1].name,
! 				(files.files[file - 1].dir
! 				 ? dirs.dirs[files.files[file - 1].dir - 1]
! 				 : comp_dir));
  	}
  
        /* Decode the table. */
--- 4226,4248 ----
        unsigned int file = 1;
        unsigned int line = 1;
        unsigned int column = 0;
!       int is_stmt = lp->default_is_stmt;
        int basic_block = 0;
        int end_sequence = 0;
  
        /* Start a subfile for the current file of the state machine.  */
!       if (lp->num_file_names >= file)
  	{
! 	  /* lp->include_dirs and lp->file_names are 0-based, but the
! 	     directory and file name numbers in the statement program
! 	     are 1-based.  */
!           struct file_entry *fe = &lp->file_names[file - 1];
!           char *dir;
!           if (fe->dir_index)
!             dir = lp->include_dirs[fe->dir_index - 1];
!           else
!             dir = comp_dir;
! 	  dwarf2_start_subfile (fe->name, dir);
  	}
  
        /* Decode the table. */
***************
*** 4041,4052 ****
  	  op_code = read_1_byte (abfd, line_ptr);
  	  line_ptr += 1;
  
! 	  if (op_code >= lh.opcode_base)
  	    {		/* Special operand.  */
! 	      adj_opcode = op_code - lh.opcode_base;
! 	      address += (adj_opcode / lh.line_range)
! 		* lh.minimum_instruction_length;
! 	      line += lh.line_base + (adj_opcode % lh.line_range);
  	      /* append row to matrix using current values */
  	      record_line (current_subfile, line, address);
  	      basic_block = 1;
--- 4251,4262 ----
  	  op_code = read_1_byte (abfd, line_ptr);
  	  line_ptr += 1;
  
! 	  if (op_code >= lp->opcode_base)
  	    {		/* Special operand.  */
! 	      adj_opcode = op_code - lp->opcode_base;
! 	      address += (adj_opcode / lp->line_range)
! 		* lp->minimum_instruction_length;
! 	      line += lp->line_base + (adj_opcode % lp->line_range);
  	      /* append row to matrix using current values */
  	      record_line (current_subfile, line, address);
  	      basic_block = 1;
***************
*** 4074,4105 ****
  		  address += baseaddr;
  		  break;
  		case DW_LNE_define_file:
! 		  cur_file = read_string (abfd, line_ptr, &bytes_read);
! 		  line_ptr += bytes_read;
! 		  if ((files.num_files % FILE_ALLOC_CHUNK) == 0)
! 		    {
! 		      files.files = (struct fileinfo *)
! 			xrealloc (files.files,
! 				  (files.num_files + FILE_ALLOC_CHUNK)
! 				  * sizeof (struct fileinfo));
! 		      if (files.num_files == 0)
! 			make_cleanup (free_current_contents, &files.files);
! 		    }
! 		  files.files[files.num_files].name = cur_file;
! 		  files.files[files.num_files].dir =
! 		    read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
! 		  line_ptr += bytes_read;
! 		  files.files[files.num_files].time =
! 		    read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
! 		  line_ptr += bytes_read;
! 		  files.files[files.num_files].size =
! 		    read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
! 		  line_ptr += bytes_read;
! 		  files.num_files++;
  		  break;
  		default:
  		  complain (&dwarf2_mangled_line_number_section);
! 		  goto done;
  		}
  	      break;
  	    case DW_LNS_copy:
--- 4284,4310 ----
  		  address += baseaddr;
  		  break;
  		case DW_LNE_define_file:
!                   {
!                     char *cur_file;
!                     unsigned int dir_index, mod_time, length;
!                     
!                     cur_file = read_string (abfd, line_ptr, &bytes_read);
!                     line_ptr += bytes_read;
!                     dir_index =
!                       read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
!                     line_ptr += bytes_read;
!                     mod_time =
!                       read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
!                     line_ptr += bytes_read;
!                     length =
!                       read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
!                     line_ptr += bytes_read;
!                     add_file_name (lp, cur_file, dir_index, mod_time, length);
!                   }
  		  break;
  		default:
  		  complain (&dwarf2_mangled_line_number_section);
! 		  return;
  		}
  	      break;
  	    case DW_LNS_copy:
***************
*** 4107,4113 ****
  	      basic_block = 0;
  	      break;
  	    case DW_LNS_advance_pc:
! 	      address += lh.minimum_instruction_length
  		* read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
  	      line_ptr += bytes_read;
  	      break;
--- 4312,4318 ----
  	      basic_block = 0;
  	      break;
  	    case DW_LNS_advance_pc:
! 	      address += lp->minimum_instruction_length
  		* read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
  	      line_ptr += bytes_read;
  	      break;
***************
*** 4116,4130 ****
  	      line_ptr += bytes_read;
  	      break;
  	    case DW_LNS_set_file:
! 	      /* The file and directory tables are 0 based, the references
! 	         are 1 based.  */
! 	      file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
! 	      line_ptr += bytes_read;
! 	      dwarf2_start_subfile
! 		(files.files[file - 1].name,
! 		 (files.files[file - 1].dir
! 		  ? dirs.dirs[files.files[file - 1].dir - 1]
! 		  : comp_dir));
  	      break;
  	    case DW_LNS_set_column:
  	      column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
--- 4321,4341 ----
  	      line_ptr += bytes_read;
  	      break;
  	    case DW_LNS_set_file:
!               {
!                 /* lp->include_dirs and lp->file_names are 0-based,
!                    but the directory and file name numbers in the
!                    statement program are 1-based.  */
!                 struct file_entry *fe;
!                 char *dir;
!                 file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
!                 line_ptr += bytes_read;
!                 fe = &lp->file_names[file - 1];
!                 if (fe->dir_index)
!                   dir = lp->include_dirs[fe->dir_index - 1];
!                 else
!                   dir = comp_dir;
!                 dwarf2_start_subfile (fe->name, dir);
!               }
  	      break;
  	    case DW_LNS_set_column:
  	      column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
***************
*** 4142,4149 ****
  	       length since special opcode 255 would have scaled the
  	       the increment.  */
  	    case DW_LNS_const_add_pc:
! 	      address += (lh.minimum_instruction_length
! 			  * ((255 - lh.opcode_base) / lh.line_range));
  	      break;
  	    case DW_LNS_fixed_advance_pc:
  	      address += read_2_bytes (abfd, line_ptr);
--- 4353,4360 ----
  	       length since special opcode 255 would have scaled the
  	       the increment.  */
  	    case DW_LNS_const_add_pc:
! 	      address += (lp->minimum_instruction_length
! 			  * ((255 - lp->opcode_base) / lp->line_range));
  	      break;
  	    case DW_LNS_fixed_advance_pc:
  	      address += read_2_bytes (abfd, line_ptr);
***************
*** 4152,4158 ****
  	    default:
  	      {  /* Unknown standard opcode, ignore it.  */
  		int i;
! 		for (i = 0; i < lh.standard_opcode_lengths[op_code]; i++)
  		  {
  		    (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
  		    line_ptr += bytes_read;
--- 4363,4369 ----
  	    default:
  	      {  /* Unknown standard opcode, ignore it.  */
  		int i;
! 		for (i = 0; i < lp->standard_opcode_lengths[op_code]; i++)
  		  {
  		    (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
  		    line_ptr += bytes_read;
***************
*** 4161,4170 ****
  	    }
  	}
      }
- done:
-   do_cleanups (back_to);
  }
  
  /* Start a subfile for DWARF.  FILENAME is the name of the file and
     DIRNAME the name of the source directory which contains FILENAME
     or NULL if not known.
--- 4372,4380 ----
  	    }
  	}
      }
  }
  
+ 
  /* Start a subfile for DWARF.  FILENAME is the name of the file and
     DIRNAME the name of the source directory which contains FILENAME
     or NULL if not known.
***************
*** 6126,6129 ****
--- 6336,6710 ----
    die = (struct die_info *) xmalloc (sizeof (struct die_info));
    memset (die, 0, sizeof (struct die_info));
    return (die);
+ }
+ 
+ 
+ /* Macro support.  */
+ 
+ 
+ /* Return the full name of file number I in *LP's file name table.
+    Use COMP_DIR as the name of the current directory of the
+    compilation.  The result is allocated using xmalloc; the caller is
+    responsible for freeing it.  */
+ static char *
+ file_full_name (int file, struct line_prologue *lp, const char *comp_dir)
+ {
+   struct file_entry *fe = &lp->file_names[file - 1];
+   
+   if (IS_ABSOLUTE_PATH (fe->name))
+     return xstrdup (fe->name);
+   else
+     {
+       const char *dir;
+       int dir_len;
+       char *full_name;
+ 
+       if (fe->dir_index)
+         dir = lp->include_dirs[fe->dir_index - 1];
+       else
+         dir = comp_dir;
+ 
+       if (dir)
+         {
+           dir_len = strlen (dir);
+           full_name = xmalloc (dir_len + 1 + strlen (fe->name) + 1);
+           strcpy (full_name, dir);
+           full_name[dir_len] = '/';
+           strcpy (full_name + dir_len + 1, fe->name);
+           return full_name;
+         }
+       else
+         return xstrdup (fe->name);
+     }
+ }
+ 
+ 
+ static struct macro_source_file *
+ macro_start_file (int file, int line,
+                   struct macro_source_file *current_file,
+                   const char *comp_dir,
+                   struct line_prologue *lp, struct objfile *objfile)
+ {
+   /* The full name of this source file.  */
+   char *full_name = file_full_name (file, lp, comp_dir);
+ 
+   /* We don't create a macro table for this compilation unit
+      at all until we actually get a filename.  */
+   if (! pending_macros)
+     pending_macros = new_macro_table (&objfile->symbol_obstack,
+                                       &objfile->macro_cache);
+ 
+   if (! current_file)
+     /* If we have no current file, then this must be the start_file
+        directive for the compilation unit's main source file.  */
+     current_file = macro_set_main (pending_macros, full_name);
+   else
+     current_file = macro_include (current_file, line, full_name);
+ 
+   xfree (full_name);
+               
+   return current_file;
+ }
+ 
+ 
+ /* Copy the LEN characters at BUF to a xmalloc'ed block of memory,
+    followed by a null byte.  */
+ static char *
+ copy_string (const char *buf, int len)
+ {
+   char *s = xmalloc (len + 1);
+   memcpy (s, buf, len);
+   s[len] = '\0';
+ 
+   return s;
+ }
+ 
+ 
+ static void
+ consume_improper_spaces (const char **p, const char *body)
+ {
+   if (**p == ' ')
+     {
+       complain (&dwarf2_macro_spaces_in_definition, body);
+ 
+       while (**p == ' ')
+         (*p)++;
+     }
+ }
+ 
+ 
+ static void
+ parse_macro_definition (struct macro_source_file *file, int line,
+                         const char *body)
+ {
+   const char *p;
+ 
+   /* The body string takes one of two forms.  For object-like macro
+      definitions, it should be:
+ 
+         <macro name> " " <definition>
+ 
+      For function-like macro definitions, it should be:
+ 
+         <macro name> "() " <definition>
+      or
+         <macro name> "(" <arg name> ( "," <arg name> ) * ") " <definition>
+ 
+      Spaces may appear only where explicitly indicated, and in the
+      <definition>.
+ 
+      The Dwarf 2 spec says that an object-like macro's name is always
+      followed by a space, but versions of GCC around March 2002 omit
+      the space when the macro's definition is the empty string. 
+ 
+      The Dwarf 2 spec says that there should be no spaces between the
+      formal arguments in a function-like macro's formal argument list,
+      but versions of GCC around March 2002 include spaces after the
+      commas.  */
+ 
+ 
+   /* Find the extent of the macro name.  The macro name is terminated
+      by either a space or null character (for an object-like macro) or
+      an opening paren (for a function-like macro).  */
+   for (p = body; *p; p++)
+     if (*p == ' ' || *p == '(')
+       break;
+ 
+   if (*p == ' ' || *p == '\0')
+     {
+       /* It's an object-like macro.  */
+       int name_len = p - body;
+       char *name = copy_string (body, name_len);
+       const char *replacement;
+ 
+       if (*p == ' ')
+         replacement = body + name_len + 1;
+       else
+         {
+           complain (&dwarf2_macro_malformed_definition, body);
+           replacement = body + name_len;
+         }
+       
+       macro_define_object (file, line, name, replacement);
+ 
+       xfree (name);
+     }
+   else if (*p == '(')
+     {
+       /* It's a function-like macro.  */
+       char *name = copy_string (body, p - body);
+       int argc = 0;
+       int argv_size = 1;
+       char **argv = xmalloc (argv_size * sizeof (*argv));
+ 
+       p++;
+ 
+       consume_improper_spaces (&p, body);
+ 
+       /* Parse the formal argument list.  */
+       while (*p && *p != ')')
+         {
+           /* Find the extent of the current argument name.  */
+           const char *arg_start = p;
+ 
+           while (*p && *p != ',' && *p != ')' && *p != ' ')
+             p++;
+ 
+           if (! *p || p == arg_start)
+             complain (&dwarf2_macro_malformed_definition,
+                       body);
+           else
+             {
+               /* Make sure argv has room for the new argument.  */
+               if (argc >= argv_size)
+                 {
+                   argv_size *= 2;
+                   argv = xrealloc (argv, argv_size * sizeof (*argv));
+                 }
+ 
+               argv[argc++] = copy_string (arg_start, p - arg_start);
+             }
+ 
+           consume_improper_spaces (&p, body);
+ 
+           /* Consume the comma, if present.  */
+           if (*p == ',')
+             {
+               p++;
+ 
+               consume_improper_spaces (&p, body);
+             }
+         }
+ 
+       if (*p == ')')
+         {
+           p++;
+ 
+           if (*p == ' ')
+             /* Perfectly formed definition, no complaints.  */
+             macro_define_function (file, line, name,
+                                    argc, (const char **) argv, 
+                                    p + 1);
+           else if (*p == '\0')
+             {
+               /* Complain, but do define it.  */
+               complain (&dwarf2_macro_malformed_definition, body);
+               macro_define_function (file, line, name,
+                                      argc, (const char **) argv, 
+                                      p);
+             }
+           else
+             /* Just complain.  */
+             complain (&dwarf2_macro_malformed_definition, body);
+         }
+       else
+         /* Just complain.  */
+         complain (&dwarf2_macro_malformed_definition, body);
+ 
+       xfree (name);
+       {
+         int i;
+ 
+         for (i = 0; i < argc; i++)
+           xfree (argv[i]);
+       }
+       xfree (argv);
+     }
+   else
+     complain (&dwarf2_macro_malformed_definition, body);
+ }
+ 
+ 
+ static void
+ dwarf_decode_macros (struct line_prologue *lp, unsigned int offset,
+                      char *comp_dir, bfd *abfd,
+                      const struct comp_unit_head *cu_header,
+                      struct objfile *objfile)
+ {
+   char *mac_ptr, *mac_end;
+   struct macro_source_file *current_file = 0;
+ 
+   if (dwarf_macinfo_buffer == NULL)
+     {
+       complain (&dwarf2_missing_macinfo_section);
+       return;
+     }
+ 
+   mac_ptr = dwarf_macinfo_buffer + offset;
+   mac_end = dwarf_macinfo_buffer + dwarf_macinfo_size;
+ 
+   for (;;)
+     {
+       enum dwarf_macinfo_record_type macinfo_type;
+ 
+       /* Do we at least have room for a macinfo type byte?  */
+       if (mac_ptr >= mac_end)
+         {
+           complain (&dwarf2_macros_too_long);
+           return;
+         }
+ 
+       macinfo_type = read_1_byte (abfd, mac_ptr);
+       mac_ptr++;
+ 
+       switch (macinfo_type)
+         {
+           /* A zero macinfo type indicates the end of the macro
+              information.  */
+         case 0:
+           return;
+ 
+         case DW_MACINFO_define:
+         case DW_MACINFO_undef:
+           {
+             int bytes_read;
+             int line;
+             char *body;
+ 
+             line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+             mac_ptr += bytes_read;
+             body = read_string (abfd, mac_ptr, &bytes_read);
+             mac_ptr += bytes_read;
+ 
+             if (! current_file)
+               complain (&dwarf2_macro_outside_file,
+                         macinfo_type == DW_MACINFO_define ? "definition" :
+                         macinfo_type == DW_MACINFO_undef ? "undefinition" :
+                         "something-or-other",
+                         body);
+             else
+               {
+                 if (macinfo_type == DW_MACINFO_define)
+                   parse_macro_definition (current_file, line, body);
+                 else if (macinfo_type == DW_MACINFO_undef)
+                   macro_undef (current_file, line, body);
+               }
+           }
+           break;
+ 
+         case DW_MACINFO_start_file:
+           {
+             int bytes_read;
+             int line, file;
+ 
+             line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+             mac_ptr += bytes_read;
+             file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+             mac_ptr += bytes_read;
+ 
+             current_file = macro_start_file (file, line,
+                                              current_file, comp_dir,
+                                              lp, objfile);
+           }
+           break;
+ 
+         case DW_MACINFO_end_file:
+           if (! current_file)
+             complain (&dwarf2_macro_unmatched_end_file);
+           else
+             {
+               current_file = current_file->included_by;
+               if (! current_file)
+                 {
+                   enum dwarf_macinfo_record_type next_type;
+ 
+                   /* GCC circa March 2002 doesn't produce the zero
+                      type byte marking the end of the compilation
+                      unit.  Complain if it's not there, but exit no
+                      matter what.  */
+ 
+                   /* Do we at least have room for a macinfo type byte?  */
+                   if (mac_ptr >= mac_end)
+                     {
+                       complain (&dwarf2_macros_too_long);
+                       return;
+                     }
+ 
+                   /* We don't increment mac_ptr here, so this is just
+                      a look-ahead.  */
+                   next_type = read_1_byte (abfd, mac_ptr);
+                   if (next_type != 0)
+                     complain (&dwarf2_macros_not_terminated);
+ 
+                   return;
+                 }
+             }
+           break;
+ 
+         case DW_MACINFO_vendor_ext:
+           {
+             int bytes_read;
+             int constant;
+             char *string;
+ 
+             constant = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+             mac_ptr += bytes_read;
+             string = read_string (abfd, mac_ptr, &bytes_read);
+             mac_ptr += bytes_read;
+ 
+             /* We don't recognize any vendor extensions.  */
+           }
+           break;
+         }
+     }
  }
Index: gdb/findvar.c
===================================================================
RCS file: /cvs/src/src/gdb/findvar.c,v
retrieving revision 1.29
diff -c -r1.29 findvar.c
*** gdb/findvar.c	2002/03/16 02:57:42	1.29
--- gdb/findvar.c	2002/03/28 06:50:42
***************
*** 551,557 ****
  
  	if (frame == NULL)
  	  return 0;
! 	b = get_frame_block (frame);
  
  	if (SYMBOL_CLASS (var) == LOC_REGPARM_ADDR)
  	  {
--- 551,557 ----
  
  	if (frame == NULL)
  	  return 0;
! 	b = get_frame_block (frame, 0);
  
  	if (SYMBOL_CLASS (var) == LOC_REGPARM_ADDR)
  	  {
Index: gdb/frame.h
===================================================================
RCS file: /cvs/src/src/gdb/frame.h,v
retrieving revision 1.9
diff -c -r1.9 frame.h
*** gdb/frame.h	2002/02/18 15:59:13	1.9
--- gdb/frame.h	2002/03/28 06:50:42
***************
*** 196,206 ****
  
  extern struct frame_info *get_next_frame (struct frame_info *);
  
! extern struct block *get_frame_block (struct frame_info *);
  
! extern struct block *get_current_block (void);
  
! extern struct block *get_selected_block (void);
  
  extern struct symbol *get_frame_function (struct frame_info *);
  
--- 196,207 ----
  
  extern struct frame_info *get_next_frame (struct frame_info *);
  
! extern struct block *get_frame_block (struct frame_info *,
!                                       CORE_ADDR *pc_in_block);
  
! extern struct block *get_current_block (CORE_ADDR *pc_in_block);
  
! extern struct block *get_selected_block (CORE_ADDR *pc_in_block);
  
  extern struct symbol *get_frame_function (struct frame_info *);
  
Index: gdb/linespec.c
===================================================================
RCS file: /cvs/src/src/gdb/linespec.c,v
retrieving revision 1.17
diff -c -r1.17 linespec.c
*** gdb/linespec.c	2002/03/22 18:57:07	1.17
--- gdb/linespec.c	2002/03/28 06:50:43
***************
*** 1187,1193 ****
  
    sym = lookup_symbol (copy,
  		       (s ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK)
! 			: get_selected_block ()),
  		       VAR_NAMESPACE, 0, &sym_symtab);
  
  symbol_found:			/* We also jump here from inside the C++ class/namespace 
--- 1187,1193 ----
  
    sym = lookup_symbol (copy,
  		       (s ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK)
! 			: get_selected_block (0)),
  		       VAR_NAMESPACE, 0, &sym_symtab);
  
  symbol_found:			/* We also jump here from inside the C++ class/namespace 
Index: gdb/macrocmd.c
===================================================================
RCS file: macrocmd.c
diff -N macrocmd.c
*** gdb/macrocmd.c	Tue May  5 13:32:27 1998
--- gdb/macrocmd.c	Wed Mar 27 22:50:43 2002
***************
*** 0 ****
--- 1,287 ----
+ /* C preprocessor macro expansion commands for GDB.
+    Copyright 2002 Free Software Foundation, Inc.
+    Contributed by Red Hat, Inc.
+ 
+    This file is part of GDB.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.  */
+ 
+ 
+ #include "defs.h"
+ #include "macrotab.h"
+ #include "macroexp.h"
+ #include "macroscope.h"
+ #include "command.h"
+ #include "gdbcmd.h"
+ 
+ 
+ /* The `macro' prefix command.  */
+ 
+ static struct cmd_list_element *macrolist;
+ 
+ static void
+ macro_command (char *arg, int from_tty)
+ {
+   printf_unfiltered
+     ("\"macro\" must be followed by the name of a macro command.\n");
+   help_list (macrolist, "macro ", -1, gdb_stdout);
+ }
+ 
+ 
+ 
+ /* Macro expansion commands.  */
+ 
+ 
+ static void
+ macro_expand_command (char *exp, int from_tty)
+ {
+   struct macro_scope *ms = 0;
+   char *expanded = 0;
+   struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms);
+   make_cleanup (free_current_contents, &expanded);
+ 
+   /* You know, when the user doesn't specify any expression, it would be
+      really cool if this defaulted to the last expression evaluated.
+      Then it would be easy to ask, "Hey, what did I just evaluate?"  But
+      at the moment, the `print' commands don't save the last expression
+      evaluated, just its value.  */
+   if (! exp || ! *exp)
+     error ("You must follow the `macro expand' command with the"
+            " expression you\n"
+            "want to expand.");
+ 
+   ms = default_macro_scope ();
+   if (ms)
+     {
+       expanded = macro_expand (exp, standard_macro_lookup, ms);
+       fputs_filtered ("expands to: ", gdb_stdout);
+       fputs_filtered (expanded, gdb_stdout);
+       fputs_filtered ("\n", gdb_stdout);
+     }
+   else
+     fputs_filtered ("GDB has no preprocessor macro information for "
+                     "that code.\n",
+                     gdb_stdout);
+ 
+   do_cleanups (cleanup_chain);
+   return;
+ }
+ 
+ 
+ static void
+ macro_expand_once_command (char *exp, int from_tty)
+ {
+   struct macro_scope *ms = 0;
+   char *expanded = 0;
+   struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms);
+   make_cleanup (free_current_contents, &expanded);
+ 
+   /* You know, when the user doesn't specify any expression, it would be
+      really cool if this defaulted to the last expression evaluated.
+      And it should set the once-expanded text as the new `last
+      expression'.  That way, you could just hit return over and over and
+      see the expression expanded one level at a time.  */
+   if (! exp || ! *exp)
+     error ("You must follow the `macro expand-once' command with"
+            " the expression\n"
+            "you want to expand.");
+ 
+   ms = default_macro_scope ();
+   if (ms)
+     {
+       expanded = macro_expand_once (exp, standard_macro_lookup, ms);
+       fputs_filtered ("expands to: ", gdb_stdout);
+       fputs_filtered (expanded, gdb_stdout);
+       fputs_filtered ("\n", gdb_stdout);
+     }
+   else
+     fputs_filtered ("GDB has no preprocessor macro information for "
+                     "that code.\n",
+                     gdb_stdout);
+ 
+   do_cleanups (cleanup_chain);
+   return;
+ }
+ 
+ 
+ static void
+ show_pp_source_pos (struct ui_file *stream,
+                     struct macro_source_file *file,
+                     int line)
+ {
+   fprintf_filtered (stream, "%s:%d\n", file->filename, line);
+ 
+   while (file->included_by)
+     {
+       fprintf_filtered (gdb_stdout, "  included at %s:%d\n",
+                         file->included_by->filename,
+                         file->included_at_line);
+       file = file->included_by;
+     }
+ }
+ 
+ 
+ static void
+ show_macro_command (char *name, int from_tty)
+ {
+   struct macro_scope *ms = 0;
+   struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms);
+   struct macro_definition *d;
+   
+   if (! name || ! *name)
+     error ("You must follow the `show macro' command with the name"
+            " of the macro\n"
+            "whose definition you want to see.");
+ 
+   ms = default_macro_scope ();
+   if (! ms)
+     error ("GDB has no preprocessor macro information for that code.\n");
+ 
+   d = macro_lookup_definition (ms->file, ms->line, name);
+   if (d)
+     {
+       int line;
+       struct macro_source_file *file
+         = macro_definition_location (ms->file, ms->line, name, &line);
+ 
+       fprintf_filtered (gdb_stdout, "Defined at ");
+       show_pp_source_pos (gdb_stdout, file, line);
+       fprintf_filtered (gdb_stdout, "#define %s", name);
+       if (d->kind == macro_function_like)
+         {
+           int i;
+ 
+           fputs_filtered ("(", gdb_stdout);
+           for (i = 0; i < d->argc; i++)
+             {
+               fputs_filtered (d->argv[i], gdb_stdout);
+               if (i + 1 < d->argc)
+                 fputs_filtered (", ", gdb_stdout);
+             }
+           fputs_filtered (")", gdb_stdout);
+         }
+       fprintf_filtered (gdb_stdout, " %s\n", d->replacement);
+     }
+   else
+     {
+       fprintf_filtered (gdb_stdout,
+                         "The symbol `%s' has no definition as a C/C++"
+                         " preprocessor macro\n"
+                         "at ", name);
+       show_pp_source_pos (gdb_stdout, ms->file, ms->line);
+     }
+ 
+   do_cleanups (cleanup_chain);
+ }
+ 
+ 
+ 
+ /* User-defined macros.  */
+ 
+ /* A table of user-defined macros.  Unlike the macro tables used for
+    symtabs, this one uses xmalloc for all its allocation, not an
+    obstack, and it doesn't bcache anything; it just xmallocs things.  So
+    it's perfectly possible to remove things from this, or redefine
+    things.  */
+ static struct macro_table *user_macros;
+ 
+ static void
+ macro_define_command (char *exp, int from_tty)
+ {
+   error ("Command not implemented yet.");
+ }
+ 
+ 
+ static void
+ macro_undef_command (char *exp, int from_tty)
+ {
+   error ("Command not implemented yet.");
+ }
+ 
+ 
+ static void
+ macro_list_command (char *exp, int from_tty)
+ {
+   error ("Command not implemented yet.");
+ }
+ 
+ 
+ 
+ /* Initializing the `macrocmd' module.  */
+ 
+ void
+ _initialize_macrocmd (void)
+ {
+   struct cmd_list_element *c;
+ 
+   /* We introduce a new command prefix, `macro', under which we'll put
+      the various commands for working with preprocessor macros.  */
+   add_prefix_cmd
+     ("macro", class_info, macro_command,
+      "Prefix for commands dealing with C preprocessor macros.",
+      &macrolist, "macro ", 0, &cmdlist);
+ 
+   add_cmd
+     ("expand", no_class, macro_expand_command,
+      "Fully expand any C/C++ preprocessor macro invocations in EXPRESSION.\n"
+      "Show the expanded expression.",
+      &macrolist);
+   add_alias_cmd ("exp", "expand", no_class, 1, &macrolist);
+   add_cmd
+     ("expand-once", no_class, macro_expand_once_command,
+      "Expand C/C++ preprocessor macro invocations appearing directly in"
+      " EXPRESSION.\n"
+      "Show the expanded expression.\n"
+      "\n"
+      "This command differs from `macro expand' in that it only expands macro\n"
+      "invocations that appear directly in EXPRESSION; if expanding a macro\n"
+      "introduces further macro invocations, those are left unexpanded.\n"
+      "\n"
+      "`macro expand-once' helps you see how a particular macro expands,\n"
+      "whereas `macro expand' shows you how all the macros involved in an\n"
+      "expression work together to yield a pre-processed expression.",
+      &macrolist);
+   add_alias_cmd ("exp1", "expand-once", no_class, 1, &macrolist);
+ 
+   add_cmd
+     ("macro", no_class, show_macro_command,
+      "Show the definition of MACRO, and its source location.",
+      &showlist);
+ 
+   add_cmd
+     ("define", no_class, macro_define_command,
+      "Define a new C/C++ preprocessor macro.\n"
+      "The GDB command `macro define DEFINITION' is equivalent to placing a\n"
+      "preprocessor directive of the form `#define DEFINITION' such that the\n"
+      "definition is visible in all the inferior's source files.\n"
+      "For example:\n"
+      "  (gdb) macro define PI (3.1415926)\n"
+      "  (gdb) macro define MIN(x,y) ((x) < (y) ? (x) : (y))",
+      &macrolist);
+ 
+   add_cmd
+     ("undef", no_class, macro_undef_command,
+      "Remove the definition of the C/C++ preprocessor macro with the"
+      " given name.",
+      &macrolist);
+ 
+   add_cmd
+     ("list", no_class, macro_list_command,
+      "List all the macros defined using the `macro define' command.",
+      &macrolist);
+ 
+   user_macros = new_macro_table (0, 0);
+ }
Index: gdb/macroexp.c
===================================================================
RCS file: macroexp.c
diff -N macroexp.c
*** gdb/macroexp.c	Tue May  5 13:32:27 1998
--- gdb/macroexp.c	Wed Mar 27 22:50:44 2002
***************
*** 0 ****
--- 1,1169 ----
+ /* C preprocessor macro expansion for GDB.
+    Copyright 2002 Free Software Foundation, Inc.
+    Contributed by Red Hat, Inc.
+ 
+    This file is part of GDB.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.  */
+ 
+ #include "defs.h"
+ #include "obstack.h"
+ #include "bcache.h"
+ #include "macrotab.h"
+ #include "macroexp.h"
+ #include "gdb_assert.h"
+ 
+ 
+ 
+ /* A resizeable, substringable string type.  */
+ 
+ 
+ /* A string type that we can resize, quickly append to, and use to
+    refer to substrings of other strings.  */
+ struct macro_buffer
+ {
+   /* An array of characters.  The first LEN bytes are the real text,
+      but there are SIZE bytes allocated to the array.  If SIZE is
+      zero, then this doesn't point to a malloc'ed block.  If SHARED is
+      non-zero, then this buffer is actually a pointer into some larger
+      string, and we shouldn't append characters to it, etc.  Because
+      of sharing, we can't assume in general that the text is
+      null-terminated.  */
+   char *text;
+ 
+   /* The number of characters in the string.  */
+   int len;
+ 
+   /* The number of characters allocated to the string.  If SHARED is
+      non-zero, this is meaningless; in this case, we set it to zero so
+      that any "do we have room to append something?" tests will fail,
+      so we don't always have to check SHARED before using this field.  */
+   int size;
+ 
+   /* Zero if TEXT can be safely realloc'ed (i.e., it's its own malloc
+      block).  Non-zero if TEXT is actually pointing into the middle of
+      some other block, and we shouldn't reallocate it.  */
+   int shared;
+ 
+   /* For detecting token splicing. 
+ 
+      This is the index in TEXT of the first character of the token
+      that abuts the end of TEXT.  If TEXT contains no tokens, then we
+      set this equal to LEN.  If TEXT ends in whitespace, then there is
+      no token abutting the end of TEXT (it's just whitespace), and
+      again, we set this equal to LEN.  We set this to -1 if we don't
+      know the nature of TEXT.  */
+   int last_token;
+ 
+   /* If this buffer is holding the result from get_token, then this 
+      is non-zero if it is an identifier token, zero otherwise.  */
+   int is_identifier;
+ };
+ 
+ 
+ /* Set the macro buffer *B to the empty string, guessing that its
+    final contents will fit in N bytes.  (It'll get resized if it
+    doesn't, so the guess doesn't have to be right.)  Allocate the
+    initial storage with xmalloc.  */
+ static void
+ init_buffer (struct macro_buffer *b, int n)
+ {
+   /* Small value for initial testing.  */
+   n = 1;
+ 
+   b->size = n;
+   if (n > 0)
+     b->text = (char *) xmalloc (n);
+   else
+     b->text = 0;
+   b->len = 0;
+   b->shared = 0;
+   b->last_token = -1;
+ }
+ 
+ 
+ /* Set the macro buffer *BUF to refer to the LEN bytes at ADDR, as a
+    shared substring.  */
+ static void
+ init_shared_buffer (struct macro_buffer *buf, char *addr, int len)
+ {
+   buf->text = addr;
+   buf->len = len;
+   buf->shared = 1;
+   buf->size = 0;
+   buf->last_token = -1;
+ }
+ 
+ 
+ /* Free the text of the buffer B.  Raise an error if B is shared.  */
+ static void
+ free_buffer (struct macro_buffer *b)
+ {
+   gdb_assert (! b->shared);
+   if (b->size)
+     xfree (b->text);
+ }
+ 
+ 
+ /* A cleanup function for macro buffers.  */
+ static void
+ cleanup_macro_buffer (void *untyped_buf)
+ {
+   free_buffer ((struct macro_buffer *) untyped_buf);
+ }
+ 
+ 
+ /* Resize the buffer B to be at least N bytes long.  Raise an error if
+    B shouldn't be resized.  */
+ static void
+ resize_buffer (struct macro_buffer *b, int n)
+ {
+   /* We shouldn't be trying to resize shared strings.  */
+   gdb_assert (! b->shared);
+   
+   if (b->size == 0)
+     b->size = n;
+   else
+     while (b->size <= n)
+       b->size *= 2;
+ 
+   b->text = xrealloc (b->text, b->size);
+ }
+ 
+ 
+ /* Append the character C to the buffer B.  */
+ static inline void
+ appendc (struct macro_buffer *b, int c)
+ {
+   int new_len = b->len + 1;
+ 
+   if (new_len > b->size)
+     resize_buffer (b, new_len);
+ 
+   b->text[b->len] = c;
+   b->len = new_len;
+ }
+ 
+ 
+ /* Append the LEN bytes at ADDR to the buffer B.  */
+ static inline void
+ appendmem (struct macro_buffer *b, char *addr, int len)
+ {
+   int new_len = b->len + len;
+ 
+   if (new_len > b->size)
+     resize_buffer (b, new_len);
+ 
+   memcpy (b->text + b->len, addr, len);
+   b->len = new_len;
+ }
+ 
+ 
+ 
+ /* Recognizing preprocessor tokens.  */
+ 
+ 
+ static int
+ is_whitespace (int c)
+ {
+   return (c == ' '
+           || c == '\t'
+           || c == '\n'
+           || c == '\v'
+           || c == '\f');
+ }
+ 
+ 
+ static int
+ is_digit (int c)
+ {
+   return ('0' <= c && c <= '9');
+ }
+ 
+ 
+ static int
+ is_identifier_nondigit (int c)
+ {
+   return (c == '_'
+           || ('a' <= c && c <= 'z')
+           || ('A' <= c && c <= 'Z'));
+ }
+ 
+ 
+ static void
+ set_token (struct macro_buffer *tok, char *start, char *end)
+ {
+   init_shared_buffer (tok, start, end - start);
+   tok->last_token = 0;
+ 
+   /* Presumed; get_identifier may overwrite this. */
+   tok->is_identifier = 0;
+ }
+ 
+ 
+ static int
+ get_comment (struct macro_buffer *tok, char *p, char *end)
+ {
+   if (p + 2 > end)
+     return 0;
+   else if (p[0] == '/'
+            && p[1] == '*')
+     {
+       char *tok_start = p;
+ 
+       p += 2;
+ 
+       for (; p < end; p++)
+         if (p + 2 <= end
+             && p[0] == '*'
+             && p[1] == '/')
+           {
+             p += 2;
+             set_token (tok, tok_start, p);
+             return 1;
+           }
+ 
+       error ("Unterminated comment in macro expansion.");
+     }
+   else if (p[0] == '/'
+            && p[1] == '/')
+     {
+       char *tok_start = p;
+ 
+       p += 2;
+       for (; p < end; p++)
+         if (*p == '\n')
+           break;
+ 
+       set_token (tok, tok_start, p);
+       return 1;
+     }
+   else
+     return 0;
+ }
+ 
+ 
+ static int
+ get_identifier (struct macro_buffer *tok, char *p, char *end)
+ {
+   if (p < end
+       && is_identifier_nondigit (*p))
+     {
+       char *tok_start = p;
+ 
+       while (p < end
+              && (is_identifier_nondigit (*p)
+                  || is_digit (*p)))
+         p++;
+ 
+       set_token (tok, tok_start, p);
+       tok->is_identifier = 1;
+       return 1;
+     }
+   else
+     return 0;
+ }
+ 
+ 
+ static int
+ get_pp_number (struct macro_buffer *tok, char *p, char *end)
+ {
+   if (p < end
+       && (is_digit (*p)
+           || *p == '.'))
+     {
+       char *tok_start = p;
+ 
+       while (p < end)
+         {
+           if (is_digit (*p)
+               || is_identifier_nondigit (*p)
+               || *p == '.')
+             p++;
+           else if (p + 2 <= end
+                    && strchr ("eEpP.", *p)
+                    && (p[1] == '+' || p[1] == '-'))
+             p += 2;
+           else
+             break;
+         }
+ 
+       set_token (tok, tok_start, p);
+       return 1;
+     }
+   else
+     return 0;
+ }
+ 
+ 
+ 
+ /* If the text starting at P going up to (but not including) END
+    starts with a character constant, set *TOK to point to that
+    character constant, and return 1.  Otherwise, return zero.
+    Signal an error if it contains a malformed or incomplete character
+    constant.  */
+ static int
+ get_character_constant (struct macro_buffer *tok, char *p, char *end)
+ {
+   /* ISO/IEC 9899:1999 (E)  Section 6.4.4.4  paragraph 1 
+      But of course, what really matters is that we handle it the same
+      way GDB's C/C++ lexer does.  So we call parse_escape in utils.c
+      to handle escape sequences.  */
+   if ((p + 1 <= end && *p == '\'')
+       || (p + 2 <= end && p[0] == 'L' && p[1] == '\''))
+     {
+       char *tok_start = p;
+       char *body_start;
+ 
+       if (*p == '\'')
+         p++;
+       else if (*p == 'L')
+         p += 2;
+       else
+         gdb_assert (0);
+ 
+       body_start = p;
+       for (;;)
+         {
+           if (p >= end)
+             error ("Unmatched single quote.");
+           else if (*p == '\'')
+             {
+               if (p == body_start)
+                 error ("A character constant must contain at least one "
+                        "character.");
+               p++;
+               break;
+             }
+           else if (*p == '\\')
+             {
+               p++;
+               parse_escape (&p);
+             }
+           else
+             p++;
+         }
+ 
+       set_token (tok, tok_start, p);
+       return 1;
+     }
+   else
+     return 0;
+ }
+ 
+ 
+ /* If the text starting at P going up to (but not including) END
+    starts with a string literal, set *TOK to point to that string
+    literal, and return 1.  Otherwise, return zero.  Signal an error if
+    it contains a malformed or incomplete string literal.  */
+ static int
+ get_string_literal (struct macro_buffer *tok, char *p, char *end)
+ {
+   if ((p + 1 <= end
+        && *p == '\"')
+       || (p + 2 <= end
+           && p[0] == 'L'
+           && p[1] == '\"'))
+     {
+       char *tok_start = p;
+ 
+       if (*p == '\"')
+         p++;
+       else if (*p == 'L')
+         p += 2;
+       else
+         gdb_assert (0);
+ 
+       for (;;)
+         {
+           if (p >= end)
+             error ("Unterminated string in expression.");
+           else if (*p == '\"')
+             {
+               p++;
+               break;
+             }
+           else if (*p == '\n')
+             error ("Newline characters may not appear in string "
+                    "constants.");
+           else if (*p == '\\')
+             {
+               p++;
+               parse_escape (&p);
+             }
+           else
+             p++;
+         }
+ 
+       set_token (tok, tok_start, p);
+       return 1;
+     }
+   else
+     return 0;
+ }
+ 
+ 
+ static int
+ get_punctuator (struct macro_buffer *tok, char *p, char *end)
+ {
+   /* Here, speed is much less important than correctness and clarity.  */
+ 
+   /* ISO/IEC 9899:1999 (E)  Section 6.4.6  Paragraph 1  */
+   static const char * const punctuators[] = {
+     "[", "]", "(", ")", "{", "}", ".", "->", 
+     "++", "--", "&", "*", "+", "-", "~", "!",
+     "/", "%", "<<", ">>", "<", ">", "<=", ">=", "==", "!=", 
+     "^", "|", "&&", "||",
+     "?", ":", ";", "...",
+     "=", "*=", "/=", "%=", "+=", "-=", "<<=", ">>=", "&=", "^=", "|=",
+     ",", "#", "##",
+     "<:", ":>", "<%", "%>", "%:", "%:%:",
+     0
+   };
+ 
+   int i;
+ 
+   if (p + 1 <= end)
+     {
+       for (i = 0; punctuators[i]; i++)
+         {
+           const char *punctuator = punctuators[i];
+ 
+           if (p[0] == punctuator[0])
+             {
+               int len = strlen (punctuator);
+ 
+               if (p + len <= end
+                   && ! memcmp (p, punctuator, len))
+                 {
+                   set_token (tok, p, p + len);
+                   return 1;
+                 }
+             }
+         }
+     }
+ 
+   return 0;
+ }
+ 
+ 
+ /* Peel the next preprocessor token off of SRC, and put it in TOK.
+    Mutate TOK to refer to the first token in SRC, and mutate SRC to
+    refer to the text after that token.  SRC must be a shared buffer;
+    the resulting TOK will be shared, pointing into the same string SRC
+    does.  Initialize TOK's last_token field.  Return non-zero if we
+    succeed, or 0 if we didn't find any more tokens in SRC.  */
+ static int
+ get_token (struct macro_buffer *tok,
+            struct macro_buffer *src)
+ {
+   char *p = src->text;
+   char *end = p + src->len;
+ 
+   gdb_assert (src->shared);
+ 
+   /* From the ISO C standard, ISO/IEC 9899:1999 (E), section 6.4:
+ 
+      preprocessing-token: 
+          header-name
+          identifier
+          pp-number
+          character-constant
+          string-literal
+          punctuator
+          each non-white-space character that cannot be one of the above
+ 
+      We don't have to deal with header-name tokens, since those can
+      only occur after a #include, which we will never see.  */
+ 
+   while (p < end)
+     if (is_whitespace (*p))
+       p++;
+     else if (get_comment (tok, p, end))
+       p += tok->len;
+     else if (get_pp_number (tok, p, end)
+              || get_character_constant (tok, p, end)
+              || get_string_literal (tok, p, end)
+              /* Note: the grammar in the standard seems to be
+                 ambiguous: L'x' can be either a wide character
+                 constant, or an identifier followed by a normal
+                 character constant.  By trying `get_identifier' after
+                 we try get_character_constant and get_string_literal,
+                 we give the wide character syntax precedence.  Now,
+                 since GDB doesn't handle wide character constants
+                 anyway, is this the right thing to do?  */
+              || get_identifier (tok, p, end)
+              || get_punctuator (tok, p, end))
+       {
+         /* How many characters did we consume, including whitespace?  */
+         int consumed = p - src->text + tok->len;
+         src->text += consumed;
+         src->len -= consumed;
+         return 1;
+       }
+     else 
+       {
+         /* We have found a "non-whitespace character that cannot be
+            one of the above."  Make a token out of it.  */
+         int consumed;
+ 
+         set_token (tok, p, p + 1);
+         consumed = p - src->text + tok->len;
+         src->text += consumed;
+         src->len -= consumed;
+         return 1;
+       }
+ 
+   return 0;
+ }
+ 
+ 
+ 
+ /* Appending token strings, with and without splicing  */
+ 
+ 
+ /* Append the macro buffer SRC to the end of DEST, and ensure that
+    doing so doesn't splice the token at the end of SRC with the token
+    at the beginning of DEST.  SRC and DEST must have their last_token
+    fields set.  Upon return, DEST's last_token field is set correctly.
+ 
+    For example:
+ 
+    If DEST is "(" and SRC is "y", then we can return with
+    DEST set to "(y" --- we've simply appended the two buffers.
+ 
+    However, if DEST is "x" and SRC is "y", then we must not return
+    with DEST set to "xy" --- that would splice the two tokens "x" and
+    "y" together to make a single token "xy".  However, it would be
+    fine to return with DEST set to "x y".  Similarly, "<" and "<" must
+    yield "< <", not "<<", etc.  */
+ static void
+ append_tokens_without_splicing (struct macro_buffer *dest,
+                                 struct macro_buffer *src)
+ {
+   int original_dest_len = dest->len;
+   struct macro_buffer dest_tail, new_token;
+ 
+   gdb_assert (src->last_token != -1);
+   gdb_assert (dest->last_token != -1);
+   
+   /* First, just try appending the two, and call get_token to see if
+      we got a splice.  */
+   appendmem (dest, src->text, src->len);
+ 
+   /* If DEST originally had no token abutting its end, then we can't
+      have spliced anything, so we're done.  */
+   if (dest->last_token == original_dest_len)
+     {
+       dest->last_token = original_dest_len + src->last_token;
+       return;
+     }
+ 
+   /* Set DEST_TAIL to point to the last token in DEST, followed by
+      all the stuff we just appended.  */
+   init_shared_buffer (&dest_tail,
+                       dest->text + dest->last_token,
+                       dest->len - dest->last_token);
+ 
+   /* Re-parse DEST's last token.  We know that DEST used to contain
+      at least one token, so if it doesn't contain any after the
+      append, then we must have spliced "/" and "*" or "/" and "/" to
+      make a comment start.  (Just for the record, I got this right
+      the first time.  This is not a bug fix.)  */
+   if (get_token (&new_token, &dest_tail)
+       && (new_token.text + new_token.len
+           == dest->text + original_dest_len))
+     {
+       /* No splice, so we're done.  */
+       dest->last_token = original_dest_len + src->last_token;
+       return;
+     }
+ 
+   /* Okay, a simple append caused a splice.  Let's chop dest back to
+      its original length and try again, but separate the texts with a
+      space.  */
+   dest->len = original_dest_len;
+   appendc (dest, ' ');
+   appendmem (dest, src->text, src->len);
+ 
+   init_shared_buffer (&dest_tail,
+                       dest->text + dest->last_token,
+                       dest->len - dest->last_token);
+ 
+   /* Try to re-parse DEST's last token, as above.  */
+   if (get_token (&new_token, &dest_tail)
+       && (new_token.text + new_token.len
+           == dest->text + original_dest_len))
+     {
+       /* No splice, so we're done.  */
+       dest->last_token = original_dest_len + 1 + src->last_token;
+       return;
+     }
+ 
+   /* As far as I know, there's no case where inserting a space isn't
+      enough to prevent a splice.  */
+   internal_error (__FILE__, __LINE__,
+                   "unable to avoid splicing tokens during macro expansion");
+ }
+ 
+ 
+ 
+ /* Expanding macros!  */
+ 
+ 
+ /* A singly-linked list of the names of the macros we are currently 
+    expanding --- for detecting expansion loops.  */
+ struct macro_name_list {
+   const char *name;
+   struct macro_name_list *next;
+ };
+ 
+ 
+ /* Return non-zero if we are currently expanding the macro named NAME,
+    according to LIST; otherwise, return zero.
+ 
+    You know, it would be possible to get rid of all the NO_LOOP
+    arguments to these functions by simply generating a new lookup
+    function and baton which refuses to find the definition for a
+    particular macro, and otherwise delegates the decision to another
+    function/baton pair.  But that makes the linked list of excluded
+    macros chained through untyped baton pointers, which will make it
+    harder to debug.  :( */
+ static int
+ currently_rescanning (struct macro_name_list *list, const char *name)
+ {
+   for (; list; list = list->next)
+     if (! strcmp (name, list->name))
+       return 1;
+ 
+   return 0;
+ }
+ 
+ 
+ /* Gather the arguments to a macro expansion.
+ 
+    NAME is the name of the macro being invoked.  (It's only used for
+    printing error messages.)
+ 
+    Assume that SRC is the text of the macro invocation immediately
+    following the macro name.  For example, if we're processing the
+    text foo(bar, baz), then NAME would be foo and SRC will be (bar,
+    baz).
+ 
+    If SRC doesn't start with an open paren ( token at all, return
+    zero, leave SRC unchanged, and don't set *ARGC_P to anything.
+ 
+    If SRC doesn't contain a properly terminated argument list, then
+    raise an error.
+ 
+    Otherwise, return a pointer to the first element of an array of
+    macro buffers referring to the argument texts, and set *ARGC_P to
+    the number of arguments we found --- the number of elements in the
+    array.  The macro buffers share their text with SRC, and their
+    last_token fields are initialized.  The array is allocated with
+    xmalloc, and the caller is responsible for freeing it.
+ 
+    NOTE WELL: if SRC starts with a open paren ( token followed
+    immediately by a close paren ) token (e.g., the invocation looks
+    like "foo()"), we treat that as one argument, which happens to be
+    the empty list of tokens.  The caller should keep in mind that such
+    a sequence of tokens is a valid way to invoke one-parameter
+    function-like macros, but also a valid way to invoke zero-parameter
+    function-like macros.  Eeew.
+ 
+    Consume the tokens from SRC; after this call, SRC contains the text
+    following the invocation.  */
+ 
+ static struct macro_buffer *
+ gather_arguments (const char *name, struct macro_buffer *src, int *argc_p)
+ {
+   struct macro_buffer tok;
+   int args_len, args_size;
+   struct macro_buffer *args = 0;
+   struct cleanup *back_to = make_cleanup (free_current_contents, &args);
+ 
+   /* Does SRC start with an opening paren token?  Read from a copy of
+      SRC, so SRC itself is unaffected if we don't find an opening
+      paren.  */
+   {
+     struct macro_buffer temp;
+     init_shared_buffer (&temp, src->text, src->len);
+ 
+     if (! get_token (&tok, &temp)
+         || tok.len != 1
+         || tok.text[0] != '(')
+       {
+         discard_cleanups (back_to);
+         return 0;
+       }
+   }
+ 
+   /* Consume SRC's opening paren.  */
+   get_token (&tok, src);
+ 
+   args_len = 0;
+   args_size = 1;                /* small for initial testing */
+   args = (struct macro_buffer *) xmalloc (sizeof (*args) * args_size);
+ 
+   for (;;)
+     {
+       struct macro_buffer *arg;
+       int depth;
+ 
+       /* Make sure we have room for the next argument.  */
+       if (args_len >= args_size)
+         {
+           args_size *= 2;
+           args = xrealloc (args, sizeof (*args) * args_size);
+         }
+ 
+       /* Initialize the next argument.  */
+       arg = &args[args_len++];
+       set_token (arg, src->text, src->text);
+ 
+       /* Gather the argument's tokens.  */
+       depth = 0;
+       for (;;)
+         {
+           char *start = src->text;
+ 
+           if (! get_token (&tok, src))
+             error ("Malformed argument list for macro `%s'.", name);
+       
+           /* Is tok an opening paren?  */
+           if (tok.len == 1 && tok.text[0] == '(')
+             depth++;
+ 
+           /* Is tok is a closing paren?  */
+           else if (tok.len == 1 && tok.text[0] == ')')
+             {
+               /* If it's a closing paren at the top level, then that's
+                  the end of the argument list.  */
+               if (depth == 0)
+                 {
+                   discard_cleanups (back_to);
+                   *argc_p = args_len;
+                   return args;
+                 }
+ 
+               depth--;
+             }
+ 
+           /* If tok is a comma at top level, then that's the end of
+              the current argument.  */
+           else if (tok.len == 1 && tok.text[0] == ',' && depth == 0)
+             break;
+ 
+           /* Extend the current argument to enclose this token.  If
+              this is the current argument's first token, leave out any
+              leading whitespace, just for aesthetics.  */
+           if (arg->len == 0)
+             {
+               arg->text = tok.text;
+               arg->len = tok.len;
+               arg->last_token = 0;
+             }
+           else
+             {
+               arg->len = (tok.text + tok.len) - arg->text;
+               arg->last_token = tok.text - arg->text;
+             }
+         }
+     }
+ }
+ 
+ 
+ /* The `expand' and `substitute_args' functions both invoke `scan'
+    recursively, so we need a forward declaration somewhere.  */
+ static void scan (struct macro_buffer *dest,
+                   struct macro_buffer *src,
+                   struct macro_name_list *no_loop,
+                   macro_lookup_ftype *lookup_func,
+                   void *lookup_baton);
+ 
+ 
+ /* Given the macro definition DEF, being invoked with the actual
+    arguments given by ARGC and ARGV, substitute the arguments into the
+    replacement list, and store the result in DEST.
+ 
+    If it is necessary to expand macro invocations in one of the
+    arguments, use LOOKUP_FUNC and LOOKUP_BATON to find the macro
+    definitions, and don't expand invocations of the macros listed in
+    NO_LOOP.  */
+ static void
+ substitute_args (struct macro_buffer *dest, 
+                  struct macro_definition *def,
+                  int argc, struct macro_buffer *argv,
+                  struct macro_name_list *no_loop,
+                  macro_lookup_ftype *lookup_func,
+                  void *lookup_baton)
+ {
+   /* A macro buffer for the macro's replacement list.  */
+   struct macro_buffer replacement_list;
+ 
+   init_shared_buffer (&replacement_list, (char *) def->replacement,
+                       strlen (def->replacement));
+ 
+   gdb_assert (dest->len == 0);
+   dest->last_token = 0;
+ 
+   for (;;)
+     {
+       struct macro_buffer tok;
+       char *original_rl_start = replacement_list.text;
+       int substituted = 0;
+       
+       /* Find the next token in the replacement list.  */
+       if (! get_token (&tok, &replacement_list))
+         break;
+ 
+       /* Just for aesthetics.  If we skipped some whitespace, copy
+          that to DEST.  */
+       if (tok.text > original_rl_start)
+         {
+           appendmem (dest, original_rl_start, tok.text - original_rl_start);
+           dest->last_token = dest->len;
+         }
+ 
+       /* Is this token the stringification operator?  */
+       if (tok.len == 1
+           && tok.text[0] == '#')
+         error ("Stringification is not implemented yet.");
+ 
+       /* Is this token the splicing operator?  */
+       if (tok.len == 2
+           && tok.text[0] == '#'
+           && tok.text[1] == '#')
+         error ("Token splicing is not implemented yet.");
+ 
+       /* Is this token an identifier?  */
+       if (tok.is_identifier)
+         {
+           int i;
+ 
+           /* Is it the magic varargs parameter?  */
+           if (tok.len == 11
+               && ! memcmp (tok.text, "__VA_ARGS__", 11))
+             error ("Variable-arity macros not implemented yet.");
+ 
+           /* Is it one of the parameters?  */
+           for (i = 0; i < def->argc; i++)
+             if (tok.len == strlen (def->argv[i])
+                 && ! memcmp (tok.text, def->argv[i], tok.len))
+               {
+                 struct macro_buffer arg_src;
+ 
+                 /* Expand any macro invocations in the argument text,
+                    and append the result to dest.  Remember that scan
+                    mutates its source, so we need to scan a new buffer
+                    referring to the argument's text, not the argument
+                    itself.  */
+                 init_shared_buffer (&arg_src, argv[i].text, argv[i].len);
+                 scan (dest, &arg_src, no_loop, lookup_func, lookup_baton);
+                 substituted = 1;
+                 break;
+               }
+         }
+ 
+       /* If it wasn't a parameter, then just copy it across.  */
+       if (! substituted)
+         append_tokens_without_splicing (dest, &tok);
+     }
+ }
+ 
+ 
+ /* Expand a call to a macro named ID, whose definition is DEF.  Append
+    its expansion to DEST.  SRC is the input text following the ID
+    token.  We are currently rescanning the expansions of the macros
+    named in NO_LOOP; don't re-expand them.  Use LOOKUP_FUNC and
+    LOOKUP_BATON to find definitions for any nested macro references.  
+ 
+    Return 1 if we decided to expand it, zero otherwise.  (If it's a
+    function-like macro name that isn't followed by an argument list,
+    we don't expand it.)  If we return zero, leave SRC unchanged.  */
+ static int
+ expand (const char *id,
+         struct macro_definition *def, 
+         struct macro_buffer *dest,
+         struct macro_buffer *src,
+         struct macro_name_list *no_loop,
+         macro_lookup_ftype *lookup_func,
+         void *lookup_baton)
+ {
+   struct macro_name_list new_no_loop;
+ 
+   /* Create a new node to be added to the front of the no-expand list.
+      This list is appropriate for re-scanning replacement lists, but
+      it is *not* appropriate for scanning macro arguments; invocations
+      of the macro whose arguments we are gathering *do* get expanded
+      there.  */
+   new_no_loop.name = id;
+   new_no_loop.next = no_loop;
+ 
+   /* What kind of macro are we expanding?  */
+   if (def->kind == macro_object_like)
+     {
+       struct macro_buffer replacement_list;
+ 
+       init_shared_buffer (&replacement_list, (char *) def->replacement,
+                           strlen (def->replacement));
+ 
+       scan (dest, &replacement_list, &new_no_loop, lookup_func, lookup_baton);
+       return 1;
+     }
+   else if (def->kind == macro_function_like)
+     {
+       struct cleanup *back_to = make_cleanup (null_cleanup, 0);
+       int argc;
+       struct macro_buffer *argv = 0;
+       struct macro_buffer substituted;
+       struct macro_buffer substituted_src;
+ 
+       if (def->argc >= 1
+           && ! strcmp (def->argv[def->argc - 1], "..."))
+         error ("Varargs macros not implemented yet.");
+ 
+       make_cleanup (free_current_contents, &argv);
+       argv = gather_arguments (id, src, &argc);
+ 
+       /* If we couldn't find any argument list, then we don't expand
+          this macro.  */
+       if (! argv)
+         {
+           do_cleanups (back_to);
+           return 0;
+         }
+ 
+       /* Check that we're passing an acceptable number of arguments for
+          this macro.  */
+       if (argc != def->argc)
+         {
+           /* Remember that a sequence of tokens like "foo()" is a
+              valid invocation of a macro expecting either zero or one
+              arguments.  */
+           if (! (argc == 1
+                  && argv[0].len == 0
+                  && def->argc == 0))
+             error ("Wrong number of arguments to macro `%s' "
+                    "(expected %d, got %d).",
+                    id, def->argc, argc);
+         }
+ 
+       /* Note that we don't expand macro invocations in the arguments
+          yet --- we let subst_args take care of that.  Parameters that
+          appear as operands of the stringifying operator "#" or the
+          splicing operator "##" don't get macro references expanded,
+          so we can't really tell whether it's appropriate to macro-
+          expand an argument until we see how it's being used.  */
+       init_buffer (&substituted, 0);
+       make_cleanup (cleanup_macro_buffer, &substituted);
+       substitute_args (&substituted, def, argc, argv, no_loop,
+                        lookup_func, lookup_baton);
+ 
+       /* Now `substituted' is the macro's replacement list, with all
+          argument values substituted into it properly.  Re-scan it for
+          macro references, but don't expand invocations of this macro.
+ 
+          We create a new buffer, `substituted_src', which points into
+          `substituted', and scan that.  We can't scan `substituted'
+          itself, since the tokenization process moves the buffer's
+          text pointer around, and we still need to be able to find
+          `substituted's original text buffer after scanning it so we
+          can free it.  */
+       init_shared_buffer (&substituted_src, substituted.text, substituted.len);
+       scan (dest, &substituted_src, &new_no_loop, lookup_func, lookup_baton);
+ 
+       do_cleanups (back_to);
+ 
+       return 1;
+     }
+   else
+     internal_error (__FILE__, __LINE__, "bad macro definition kind");
+ }
+ 
+ 
+ /* If the single token in SRC_FIRST followed by the tokens in SRC_REST
+    constitute a macro invokation not forbidden in NO_LOOP, append its
+    expansion to DEST and return non-zero.  Otherwise, return zero, and
+    leave DEST unchanged.
+ 
+    SRC_FIRST and SRC_REST must be shared buffers; DEST must not be one.
+    SRC_FIRST must be a string built by get_token.  */
+ static int
+ maybe_expand (struct macro_buffer *dest,
+               struct macro_buffer *src_first,
+               struct macro_buffer *src_rest,
+               struct macro_name_list *no_loop,
+               macro_lookup_ftype *lookup_func,
+               void *lookup_baton)
+ {
+   gdb_assert (src_first->shared);
+   gdb_assert (src_rest->shared);
+   gdb_assert (! dest->shared);
+ 
+   /* Is this token an identifier?  */
+   if (src_first->is_identifier)
+     {
+       /* Make a null-terminated copy of it, since that's what our
+          lookup function expects.  */
+       char *id = xmalloc (src_first->len + 1);
+       struct cleanup *back_to = make_cleanup (xfree, id);
+       memcpy (id, src_first->text, src_first->len);
+       id[src_first->len] = 0;
+           
+       /* If we're currently re-scanning the result of expanding
+          this macro, don't expand it again.  */
+       if (! currently_rescanning (no_loop, id))
+         {
+           /* Does this identifier have a macro definition in scope?  */
+           struct macro_definition *def = lookup_func (id, lookup_baton);
+ 
+           if (def && expand (id, def, dest, src_rest, no_loop,
+                              lookup_func, lookup_baton))
+             {
+               do_cleanups (back_to);
+               return 1;
+             }
+         }
+ 
+       do_cleanups (back_to);
+     }
+ 
+   return 0;
+ }
+ 
+ 
+ /* Expand macro references in SRC, appending the results to DEST.
+    Assume we are re-scanning the result of expanding the macros named
+    in NO_LOOP, and don't try to re-expand references to them.
+ 
+    SRC must be a shared buffer; DEST must not be one.  */
+ static void
+ scan (struct macro_buffer *dest,
+       struct macro_buffer *src,
+       struct macro_name_list *no_loop,
+       macro_lookup_ftype *lookup_func,
+       void *lookup_baton)
+ {
+   gdb_assert (src->shared);
+   gdb_assert (! dest->shared);
+ 
+   for (;;)
+     {
+       struct macro_buffer tok;
+       char *original_src_start = src->text;
+ 
+       /* Find the next token in SRC.  */
+       if (! get_token (&tok, src))
+         break;
+ 
+       /* Just for aesthetics.  If we skipped some whitespace, copy
+          that to DEST.  */
+       if (tok.text > original_src_start)
+         {
+           appendmem (dest, original_src_start, tok.text - original_src_start);
+           dest->last_token = dest->len;
+         }
+ 
+       if (! maybe_expand (dest, &tok, src, no_loop, lookup_func, lookup_baton))
+         /* We didn't end up expanding tok as a macro reference, so
+            simply append it to dest.  */
+         append_tokens_without_splicing (dest, &tok);
+     }
+ 
+   /* Just for aesthetics.  If there was any trailing whitespace in
+      src, copy it to dest.  */
+   if (src->len)
+     {
+       appendmem (dest, src->text, src->len);
+       dest->last_token = dest->len;
+     }
+ }
+ 
+ 
+ char *
+ macro_expand (const char *source,
+               macro_lookup_ftype *lookup_func,
+               void *lookup_func_baton)
+ {
+   struct macro_buffer src, dest;
+   struct cleanup *back_to;
+ 
+   init_shared_buffer (&src, (char *) source, strlen (source));
+ 
+   init_buffer (&dest, 0);
+   dest.last_token = 0;
+   back_to = make_cleanup (cleanup_macro_buffer, &dest);
+ 
+   scan (&dest, &src, 0, lookup_func, lookup_func_baton);
+ 
+   appendc (&dest, '\0');
+ 
+   discard_cleanups (back_to);
+   return dest.text;
+ }
+ 
+ 
+ char *
+ macro_expand_once (const char *source,
+                    macro_lookup_ftype *lookup_func,
+                    void *lookup_func_baton)
+ {
+   error ("Expand-once not implemented yet.");
+ }
+ 
+ 
+ char *
+ macro_expand_next (char **lexptr,
+                    macro_lookup_ftype *lookup_func,
+                    void *lookup_baton)
+ {
+   struct macro_buffer src, dest, tok;
+   struct cleanup *back_to;
+ 
+   /* Set up SRC to refer to the input text, pointed to by *lexptr.  */
+   init_shared_buffer (&src, *lexptr, strlen (*lexptr));
+ 
+   /* Set up DEST to receive the expansion, if there is one.  */
+   init_buffer (&dest, 0);
+   dest.last_token = 0;
+   back_to = make_cleanup (cleanup_macro_buffer, &dest);
+ 
+   /* Get the text's first preprocessing token.  */
+   if (! get_token (&tok, &src))
+     {
+       do_cleanups (back_to);
+       return 0;
+     }
+ 
+   /* If it's a macro invocation, expand it.  */
+   if (maybe_expand (&dest, &tok, &src, 0, lookup_func, lookup_baton))
+     {
+       /* It was a macro invocation!  Package up the expansion as a
+          null-terminated string and return it.  Set *lexptr to the
+          start of the next token in the input.  */
+       appendc (&dest, '\0');
+       discard_cleanups (back_to);
+       *lexptr = src.text;
+       return dest.text;
+     }
+   else
+     {
+       /* It wasn't a macro invocation.  */
+       do_cleanups (back_to);
+       return 0;
+     }
+ }
Index: gdb/macroexp.h
===================================================================
RCS file: macroexp.h
diff -N macroexp.h
*** gdb/macroexp.h	Tue May  5 13:32:27 1998
--- gdb/macroexp.h	Wed Mar 27 22:50:44 2002
***************
*** 0 ****
--- 1,90 ----
+ /* Interface to C preprocessor macro expansion for GDB.
+    Copyright 2002 Free Software Foundation, Inc.
+    Contributed by Red Hat, Inc.
+ 
+    This file is part of GDB.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.  */
+ 
+ 
+ #ifndef MACROEXP_H
+ #define MACROEXP_H
+ 
+ /* A function for looking up preprocessor macro definitions.  Return
+    the preprocessor definition of NAME in scope according to BATON, or
+    zero if NAME is not defined as a preprocessor macro.
+ 
+    The caller must not free or modify the definition returned.  It is
+    probably unwise for the caller to hold pointers to it for very
+    long; it probably lives in some objfile's obstacks.  */
+ typedef struct macro_definition *(macro_lookup_ftype) (const char *name,
+                                                        void *baton);
+ 
+ 
+ /* Expand any preprocessor macros in SOURCE, and return the expanded
+    text.  Use LOOKUP_FUNC and LOOKUP_FUNC_BATON to find identifiers'
+    preprocessor definitions.  SOURCE is a null-terminated string.  The
+    result is a null-terminated string, allocated using xmalloc; it is
+    the caller's responsibility to free it.  */
+ char *macro_expand (const char *source,
+                     macro_lookup_ftype *lookup_func,
+                     void *lookup_func_baton);
+ 
+ 
+ /* Expand all preprocessor macro references that appear explicitly in
+    SOURCE, but do not expand any new macro references introduced by
+    that first level of expansion.  Use LOOKUP_FUNC and
+    LOOKUP_FUNC_BATON to find identifiers' preprocessor definitions.
+    SOURCE is a null-terminated string.  The result is a
+    null-terminated string, allocated using xmalloc; it is the caller's
+    responsibility to free it.  */
+ char *macro_expand_once (const char *source,
+                          macro_lookup_ftype *lookup_func,
+                          void *lookup_func_baton);
+ 
+ 
+ /* If the null-terminated string pointed to by *LEXPTR begins with a
+    macro invocation, return the result of expanding that invocation as
+    a null-terminated string, and set *LEXPTR to the next character
+    after the invocation.  The result is completely expanded; it
+    contains no further macro invocations.
+ 
+    Otherwise, if *LEXPTR does not start with a macro invocation,
+    return zero, and leave *LEXPTR unchanged.
+ 
+    Use LOOKUP_FUNC and LOOKUP_BATON to find macro definitions.
+ 
+    If this function returns a string, the caller is responsible for
+    freeing it, using xfree.
+ 
+    We need this expand-one-token-at-a-time interface in order to
+    accomodate GDB's C expression parser, which may not consume the
+    entire string.  When the user enters a command like
+ 
+       (gdb) break *func+20 if x == 5
+ 
+    the parser is expected to consume `func+20', and then stop when it
+    sees the "if".  But of course, "if" appearing in a character string
+    or as part of a larger identifier doesn't count.  So you pretty
+    much have to do tokenization to find the end of the string that
+    needs to be macro-expanded.  Our C/C++ tokenizer isn't really
+    designed to be called by anything but the yacc parser engine.  */
+ char *macro_expand_next (char **lexptr,
+                          macro_lookup_ftype *lookup_func,
+                          void *lookup_baton);
+ 
+ 
+ #endif /* MACROEXP_H */
Index: gdb/macroscope.c
===================================================================
RCS file: macroscope.c
diff -N macroscope.c
*** gdb/macroscope.c	Tue May  5 13:32:27 1998
--- gdb/macroscope.c	Wed Mar 27 22:50:44 2002
***************
*** 0 ****
--- 1,98 ----
+ /* Functions for deciding which macros are currently in scope.
+    Copyright 2002 Free Software Foundation, Inc.
+    Contributed by Red Hat, Inc.
+ 
+    This file is part of GDB.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.  */
+ 
+ #include "defs.h"
+ 
+ #include "macroscope.h"
+ #include "symtab.h"
+ #include "target.h"
+ #include "frame.h"
+ #include "inferior.h"
+ 
+ 
+ struct macro_scope *
+ sal_macro_scope (struct symtab_and_line sal)
+ {
+   struct macro_source_file *main;
+   struct macro_scope *ms;
+   
+   if (! sal.pc
+       || ! sal.symtab
+       || ! sal.symtab->macro_table)
+     return 0;
+ 
+   ms = (struct macro_scope *) xmalloc (sizeof (*ms));
+ 
+   main = macro_main (sal.symtab->macro_table);
+   ms->file = macro_lookup_inclusion (main, sal.symtab->filename);
+ 
+   if (! ms->file)
+     internal_error
+       (__FILE__, __LINE__,
+        "\n"
+        "the symtab `%s' refers to a preprocessor macro table which doesn't\n"
+        "have any record of processing a file by that name.\n",
+        sal.symtab->filename);
+ 
+   ms->line = sal.line;
+ 
+   return ms;
+ }
+ 
+ 
+ struct macro_scope *
+ default_macro_scope ()
+ {
+   struct symtab_and_line sal;
+   struct macro_source_file *main;
+   struct macro_scope *ms;
+ 
+   /* If there's a selected frame, use its PC.  */ 
+   if (selected_frame)
+     sal = find_pc_line (selected_frame->pc, 0);
+   
+   /* If the target has any registers at all, then use its PC.  Why we
+      would have registers but no stack, I'm not sure.  */
+   else if (target_has_registers)
+     sal = find_pc_line (read_pc (), 0);
+ 
+   /* If all else fails, fall back to the current listing position.  */
+   else
+     {
+       select_source_symtab (0);
+       sal.symtab = current_source_symtab;
+       sal.line = current_source_line;
+     }
+ 
+   return sal_macro_scope (sal);
+ }
+ 
+ 
+ /* Look up the definition of the macro named NAME in scope at the source
+    location given by BATON, which must be a pointer to a `struct
+    macro_scope' structure.  */
+ struct macro_definition *
+ standard_macro_lookup (const char *name, void *baton)
+ {
+   struct macro_scope *ms = (struct macro_scope *) baton;
+ 
+   return macro_lookup_definition (ms->file, ms->line, name);
+ }
Index: gdb/macroscope.h
===================================================================
RCS file: macroscope.h
diff -N macroscope.h
*** gdb/macroscope.h	Tue May  5 13:32:27 1998
--- gdb/macroscope.h	Wed Mar 27 22:50:44 2002
***************
*** 0 ****
--- 1,63 ----
+ /* Interface to functions for deciding which macros are currently in scope.
+    Copyright 2002 Free Software Foundation, Inc.
+    Contributed by Red Hat, Inc.
+ 
+    This file is part of GDB.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.  */
+ 
+ #ifndef MACROSCOPE_H
+ #define MACROSCOPE_H
+ 
+ #include "macrotab.h"
+ #include "symtab.h"
+ 
+ 
+ /* All the information we need to decide which macro definitions are
+    in scope: a source file (either a main source file or an
+    #inclusion), and a line number in that file.  */
+ struct macro_scope {
+   struct macro_source_file *file;
+   int line;
+ };
+ 
+ 
+ /* Return a `struct macro_scope' object corresponding to the symtab
+    and line given in SAL.  If we have no macro information for that
+    location, or if SAL's pc is zero, return zero.  */
+ struct macro_scope *sal_macro_scope (struct symtab_and_line sal);
+ 
+ 
+ /* Return a `struct macro_scope' object describing the scope the `macro
+    expand' and `macro expand-once' commands should use for looking up
+    macros.  If we have a selected frame, this is the source location of
+    its PC; otherwise, this is the last listing position.
+ 
+    If we have no macro information for the current location, return zero.
+ 
+    The object returned is allocated using xmalloc; the caller is
+    responsible for freeing it.  */
+ struct macro_scope *default_macro_scope (void);
+ 
+ 
+ /* Look up the definition of the macro named NAME in scope at the source
+    location given by BATON, which must be a pointer to a `struct
+    macro_scope' structure.  This function is suitable for use as
+    a macro_lookup_ftype function.  */
+ struct macro_definition *standard_macro_lookup (const char *name, void *baton);
+ 
+ 
+ #endif /* MACROSCOPE_H */
Index: gdb/macrotab.c
===================================================================
RCS file: macrotab.c
diff -N macrotab.c
*** gdb/macrotab.c	Tue May  5 13:32:27 1998
--- gdb/macrotab.c	Wed Mar 27 22:50:44 2002
***************
*** 0 ****
--- 1,862 ----
+ /* C preprocessor macro tables for GDB.
+    Copyright 2002 Free Software Foundation, Inc.
+    Contributed by Red Hat, Inc.
+ 
+    This file is part of GDB.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.  */
+ 
+ #include "defs.h"
+ #include "obstack.h"
+ #include "splay-tree.h"
+ #include "symtab.h"
+ #include "symfile.h"
+ #include "objfiles.h"
+ #include "macrotab.h"
+ #include "gdb_assert.h"
+ #include "bcache.h"
+ #include "complaints.h"
+ 
+ 
+ /* The macro table structure.  */
+ 
+ struct macro_table
+ {
+   /* The obstack this table's data should be allocated in, or zero if
+      we should use xmalloc.  */
+   struct obstack *obstack;
+ 
+   /* The bcache we should use to hold macro names, argument names, and
+      definitions, or zero if we should use xmalloc.  */
+   struct bcache *bcache;
+ 
+   /* The main source file for this compilation unit --- the one whose
+      name was given to the compiler.  This is the root of the
+      #inclusion tree; everything else is #included from here.  */
+   struct macro_source_file *main_source;
+ 
+   /* The table of macro definitions.  This is a splay tree (an ordered
+      binary tree that stays balanced, effectively), sorted by macro
+      name.  Where a macro gets defined more than once (presumably with
+      an #undefinition in between), we sort the definitions by the
+      order they would appear in the preprocessor's output.  That is,
+      if `a.c' #includes `m.h' and then #includes `n.h', and both
+      header files #define X (with an #undef somewhere in between),
+      then the definition from `m.h' appears in our splay tree before
+      the one from `n.h'.
+ 
+      The splay tree's keys are `struct macro_key' pointers;
+      the values are `struct macro_definition' pointers.
+ 
+      The splay tree, its nodes, and the keys and values are allocated
+      in obstack, if it's non-zero, or with xmalloc otherwise.  The
+      macro names, argument names, argument name arrays, and definition
+      strings are all allocated in bcache, if non-zero, or with xmalloc
+      otherwise.  */
+   splay_tree definitions;
+ };
+ 
+ 
+ 
+ /* Allocation and freeing functions.  */
+ 
+ /* Allocate SIZE bytes of memory appropriately for the macro table T.
+    This just checks whether T has an obstack, or whether its pieces
+    should be allocated with xmalloc.  */
+ static void *
+ macro_alloc (int size, struct macro_table *t)
+ {
+   if (t->obstack)
+     return obstack_alloc (t->obstack, size);
+   else
+     return xmalloc (size);
+ }
+ 
+ 
+ static void
+ macro_free (void *object, struct macro_table *t)
+ {
+   gdb_assert (! t->obstack);
+   xfree (object);
+ }
+ 
+ 
+ /* If the macro table T has a bcache, then cache the LEN bytes at ADDR
+    there, and return the cached copy.  Otherwise, just xmalloc a copy
+    of the bytes, and return a pointer to that.  */
+ static const void *
+ macro_bcache (struct macro_table *t, const void *addr, int len)
+ {
+   if (t->bcache)
+     return bcache (addr, len, t->bcache);
+   else
+     {
+       void *copy = xmalloc (len);
+       memcpy (copy, addr, len);
+       return copy;
+     }
+ }
+ 
+ 
+ /* If the macro table T has a bcache, cache the null-terminated string
+    S there, and return a pointer to the cached copy.  Otherwise,
+    xmalloc a copy and return that.  */
+ static const char *
+ macro_bcache_str (struct macro_table *t, const char *s)
+ {
+   return (char *) macro_bcache (t, s, strlen (s) + 1);
+ }
+ 
+ 
+ /* Free a possibly bcached object OBJ.  That is, if the macro table T
+    has a bcache, it's an error; otherwise, xfree OBJ.  */
+ void
+ macro_bcache_free (struct macro_table *t, void *obj)
+ {
+   gdb_assert (! t->bcache);
+   xfree (obj);
+ }
+ 
+ 
+ 
+ /* Macro tree keys, w/their comparison, allocation, and freeing functions.  */
+ 
+ /* A key in the splay tree.  */
+ struct macro_key
+ {
+   /* The table we're in.  We only need this in order to free it, since
+      the splay tree library's key and value freeing functions require
+      that the key or value contain all the information needed to free
+      themselves.  */
+   struct macro_table *table;
+ 
+   /* The name of the macro.  This is in the table's bcache, if it has
+      one. */
+   const char *name;
+ 
+   /* The source file and line number where the definition's scope
+      begins.  This is also the line of the definition itself.  */
+   struct macro_source_file *start_file;
+   int start_line;
+ 
+   /* The first source file and line after the definition's scope.
+      (That is, the scope does not include this endpoint.)  If end_file
+      is zero, then the definition extends to the end of the
+      compilation unit.  */
+   struct macro_source_file *end_file;
+   int end_line;
+ };
+ 
+ 
+ /* Return the #inclusion depth of the source file FILE.  This is the
+    number of #inclusions it took to reach this file.  For the main
+    source file, the #inclusion depth is zero; for a file it #includes
+    directly, the depth would be one; and so on.  */
+ static int
+ inclusion_depth (struct macro_source_file *file)
+ {
+   int depth;
+ 
+   for (depth = 0; file->included_by; depth++)
+     file = file->included_by;
+ 
+   return depth;
+ }
+ 
+ 
+ /* Compare two source locations (from the same compilation unit).
+    This is part of the comparison function for the tree of
+    definitions.
+ 
+    LINE1 and LINE2 are line numbers in the source files FILE1 and
+    FILE2.  Return a value:
+    - less than zero if {LINE,FILE}1 comes before {LINE,FILE}2,
+    - greater than zero if {LINE,FILE}1 comes after {LINE,FILE}2, or
+    - zero if they are equal.
+ 
+    When the two locations are in different source files --- perhaps
+    one is in a header, while another is in the main source file --- we
+    order them by where they would appear in the fully pre-processed
+    sources, where all the #included files have been substituted into
+    their places.  */
+ static int
+ compare_locations (struct macro_source_file *file1, int line1, 
+                    struct macro_source_file *file2, int line2)
+ {
+   /* We want to treat positions in an #included file as coming *after*
+      the line containing the #include, but *before* the line after the
+      include.  As we walk up the #inclusion tree toward the main
+      source file, we update fileX and lineX as we go; includedX
+      indicates whether the original position was from the #included
+      file.  */
+   int included1 = 0;
+   int included2 = 0;
+ 
+   /* If a file is zero, that means "end of compilation unit."  Handle
+      that specially.  */
+   if (! file1)
+     {
+       if (! file2)
+         return 0;
+       else
+         return 1;
+     }
+   else if (! file2)
+     return -1;
+ 
+   /* If the two files are not the same, find their common ancestor in
+      the #inclusion tree.  */
+   if (file1 != file2)
+     {
+       /* If one file is deeper than the other, walk up the #inclusion
+          chain until the two files are at least at the same *depth*.
+          Then, walk up both files in synchrony until they're the same
+          file.  That file is the common ancestor.  */
+       int depth1 = inclusion_depth (file1);
+       int depth2 = inclusion_depth (file2);
+ 
+       /* Only one of these while loops will ever execute in any given
+          case.  */
+       while (depth1 > depth2)
+         {
+           line1 = file1->included_at_line;
+           file1 = file1->included_by;
+           included1 = 1;
+           depth1--;
+         }
+       while (depth2 > depth1)
+         {
+           line2 = file2->included_at_line;
+           file2 = file2->included_by;
+           included2 = 1;
+           depth2--;
+         }
+ 
+       /* Now both file1 and file2 are at the same depth.  Walk toward
+          the root of the tree until we find where the branches meet.  */
+       while (file1 != file2)
+         {
+           line1 = file1->included_at_line;
+           file1 = file1->included_by;
+           /* At this point, we know that the case the includedX flags
+              are trying to deal with won't come up, but we'll just
+              maintain them anyway.  */
+           included1 = 1;
+ 
+           line2 = file2->included_at_line;
+           file2 = file2->included_by;
+           included2 = 1;
+ 
+           /* Sanity check.  If file1 and file2 are really from the
+              same compilation unit, then they should both be part of
+              the same tree, and this shouldn't happen.  */
+           gdb_assert (file1 && file2);
+         }
+     }
+ 
+   /* Now we've got two line numbers in the same file.  */
+   if (line1 == line2)
+     {
+       /* They can't both be from #included files.  Then we shouldn't
+          have walked up this far.  */
+       gdb_assert (! included1 || ! included2);
+ 
+       /* Any #included position comes after a non-#included position
+          with the same line number in the #including file.  */
+       if (included1)
+         return 1;
+       else if (included2)
+         return -1;
+       else
+         return 0;
+     }
+   else
+     return line1 - line2;
+ }
+ 
+ 
+ /* Compare a macro key KEY against NAME, the source file FILE, and
+    line number LINE.
+ 
+    Sort definitions by name; for two definitions with the same name,
+    place the one whose definition comes earlier before the one whose
+    definition comes later.
+ 
+    Return -1, 0, or 1 if key comes before, is identical to, or comes
+    after NAME, FILE, and LINE.  */
+ static int
+ key_compare (struct macro_key *key,
+              const char *name, struct macro_source_file *file, int line)
+ {
+   int names = strcmp (key->name, name);
+   if (names)
+     return names;
+ 
+   return compare_locations (key->start_file, key->start_line,
+                             file, line);
+ }
+ 
+ 
+ /* The macro tree comparison function, typed for the splay tree
+    library's happiness.  */
+ static int
+ macro_tree_compare (splay_tree_key untyped_key1,
+                     splay_tree_key untyped_key2)
+ {
+   struct macro_key *key1 = (struct macro_key *) untyped_key1;
+   struct macro_key *key2 = (struct macro_key *) untyped_key2;
+ 
+   return key_compare (key1, key2->name, key2->start_file, key2->start_line);
+ }
+ 
+ 
+ /* Construct a new macro key node for a macro in table T whose name is
+    NAME, and whose scope starts at LINE in FILE; register the name in
+    the bcache.  */
+ static struct macro_key *
+ new_macro_key (struct macro_table *t,
+                const char *name,
+                struct macro_source_file *file,
+                int line)
+ {
+   struct macro_key *k = macro_alloc (sizeof (*k), t);
+ 
+   memset (k, 0, sizeof (*k));
+   k->table = t;
+   k->name = macro_bcache_str (t, name);
+   k->start_file = file;
+   k->start_line = line;
+   k->end_file = 0;
+ 
+   return k;
+ }
+ 
+ 
+ static void
+ macro_tree_delete_key (void *untyped_key)
+ {
+   struct macro_key *key = (struct macro_key *) untyped_key;
+ 
+   macro_bcache_free (key->table, (char *) key->name);
+   macro_free (key, key->table);
+ }
+ 
+ 
+ 
+ /* Building and querying the tree of #included files.  */
+ 
+ 
+ /* Allocate and initialize a new source file structure.  */
+ static struct macro_source_file *
+ new_source_file (struct macro_table *t,
+                  const char *filename)
+ {
+   /* Get space for the source file structure itself.  */
+   struct macro_source_file *f = macro_alloc (sizeof (*f), t);
+ 
+   memset (f, 0, sizeof (*f));
+   f->table = t;
+   f->filename = macro_bcache_str (t, filename);
+   f->includes = 0;
+ 
+   return f;
+ }
+ 
+ 
+ /* Free a source file, and all the source files it #included.  */
+ static void
+ free_macro_source_file (struct macro_source_file *src)
+ {
+   struct macro_source_file *child, *next_child;
+ 
+   /* Free this file's children.  */
+   for (child = src->includes; child; child = next_child)
+     {
+       next_child = child->next_included;
+       free_macro_source_file (child);
+     }
+ 
+   macro_bcache_free (src->table, (char *) src->filename);
+   macro_free (src, src->table);
+ }
+ 
+ 
+ struct macro_source_file *
+ macro_set_main (struct macro_table *t,
+                 const char *filename)
+ {
+   /* You can't change a table's main source file.  What would that do
+      to the tree?  */
+   gdb_assert (! t->main_source);
+ 
+   t->main_source = new_source_file (t, filename);
+ 
+   return t->main_source;
+ }
+ 
+ 
+ struct macro_source_file *
+ macro_main (struct macro_table *t)
+ {
+   gdb_assert (t->main_source);
+ 
+   return t->main_source;
+ }
+ 
+ 
+ struct macro_source_file *
+ macro_include (struct macro_source_file *source,
+                int line,
+                const char *included)
+ {
+   struct macro_source_file *new;
+   struct macro_source_file **link;
+ 
+   /* Find the right position in SOURCE's `includes' list for the new
+      file.  Scan until we find the first file we shouldn't follow ---
+      which is therefore the file we should directly precede --- or
+      reach the end of the list.  */
+   for (link = &source->includes;
+        *link && line < (*link)->included_at_line;
+        link = &(*link)->next_included)
+     ;
+ 
+   /* Did we find another file already #included at the same line as
+      the new one?  */
+   if (*link && line == (*link)->included_at_line)
+     {
+       /* This means the compiler is emitting bogus debug info.  (GCC
+          circa March 2002 did this.)  It also means that the splay
+          tree ordering function, macro_tree_compare, will abort,
+          because it can't tell which #inclusion came first.  But GDB
+          should tolerate bad debug info.  So:
+ 
+          First, squawk.  */
+       static struct complaint bogus_inclusion_line = {
+         "both `%s' and `%s' allegedly #included at %s:%d", 0, 0
+       };
+ 
+       complain (&bogus_inclusion_line, 
+                 included, (*link)->filename, source->filename, line);
+ 
+       /* Now, choose a new, unoccupied line number for this
+          #inclusion, after the alleged #inclusion line.  */
+       while (*link && line == (*link)->included_at_line)
+         {
+           /* This line number is taken, so try the next line.  */
+           line++;
+           link = &(*link)->next_included;
+         }
+     }
+ 
+   /* At this point, we know that LINE is an unused line number, and
+      *LINK points to the entry an #inclusion at that line should
+      precede.  */
+   new = new_source_file (source->table, included);
+   new->included_by = source;
+   new->included_at_line = line;
+   new->next_included = *link;
+   *link = new;
+ 
+   return new;
+ }
+ 
+ 
+ struct macro_source_file *
+ macro_lookup_inclusion (struct macro_source_file *source, const char *name)
+ {
+   /* Is SOURCE itself named NAME?  */
+   if (! strcmp (name, source->filename))
+     return source;
+ 
+   /* The filename in the source structure is probably a full path, but
+      NAME could be just the final component of the name.  */
+   {
+     int name_len = strlen (name);
+     int src_name_len = strlen (source->filename);
+ 
+     /* We do mean < here, and not <=; if the lengths are the same,
+        then the strcmp above should have triggered, and we need to
+        check for a slash here.  */
+     if (name_len < src_name_len
+         && source->filename[src_name_len - name_len - 1] == '/'
+         && ! strcmp (name, source->filename + src_name_len - name_len))
+       return source;
+   }
+ 
+   /* It's not us.  Try all our children, and return the lowest.  */
+   {
+     struct macro_source_file *child;
+     struct macro_source_file *best = 0;
+     int best_depth;
+ 
+     for (child = source->includes; child; child = child->next_included)
+       {
+         struct macro_source_file *result
+           = macro_lookup_inclusion (child, name);
+ 
+         if (result)
+           {
+             int result_depth = inclusion_depth (result);
+ 
+             if (! best || result_depth < best_depth)
+               {
+                 best = result;
+                 best_depth = result_depth;
+               }
+           }
+       }
+ 
+     return best;
+   }
+ }
+ 
+ 
+ 
+ /* Registering and looking up macro definitions.  */
+ 
+ 
+ /* Construct a definition for a macro in table T.  Cache all strings,
+    and the macro_definition structure itself, in T's bcache.  */
+ static struct macro_definition *
+ new_macro_definition (struct macro_table *t,
+                       enum macro_kind kind,
+                       int argc, const char **argv,
+                       const char *replacement)
+ {
+   struct macro_definition *d = macro_alloc (sizeof (*d), t);
+ 
+   memset (d, 0, sizeof (*d));
+   d->table = t;
+   d->kind = kind;
+   d->replacement = macro_bcache_str (t, replacement);
+ 
+   if (kind == macro_function_like)
+     {
+       int i;
+       const char **cached_argv;
+       int cached_argv_size = argc * sizeof (*cached_argv);
+ 
+       /* Bcache all the arguments.  */
+       cached_argv = alloca (cached_argv_size);
+       for (i = 0; i < argc; i++)
+         cached_argv[i] = macro_bcache_str (t, argv[i]);
+ 
+       /* Now bcache the array of argument pointers itself.  */
+       d->argv = macro_bcache (t, cached_argv, cached_argv_size);
+       d->argc = argc;
+     }
+ 
+   /* We don't bcache the entire definition structure because it's got
+      a pointer to the macro table in it; since each compilation unit
+      has its own macro table, you'd only get bcache hits for identical
+      definitions within a compilation unit, which seems unlikely.
+ 
+      "So, why do macro definitions have pointers to their macro tables
+      at all?"  Well, when the splay tree library wants to free a
+      node's value, it calls the value freeing function with nothing
+      but the value itself.  It makes the (apparently reasonable)
+      assumption that the value carries enough information to free
+      itself.  But not all macro tables have bcaches, so not all macro
+      definitions would be bcached.  There's no way to tell whether a
+      given definition is bcached without knowing which table the
+      definition belongs to.  ...  blah.  The thing's only sixteen
+      bytes anyway, and we can still bcache the name, args, and
+      definition, so we just don't bother bcaching the definition
+      structure itself.  */
+   return d;
+ }
+ 
+ 
+ /* Free a macro definition.  */
+ static void
+ macro_tree_delete_value (void *untyped_definition)
+ {
+   struct macro_definition *d = (struct macro_definition *) untyped_definition;
+   struct macro_table *t = d->table;
+ 
+   if (d->kind == macro_function_like)
+     {
+       int i;
+ 
+       for (i = 0; i < d->argc; i++)
+         macro_bcache_free (t, (char *) d->argv[i]);
+       macro_bcache_free (t, (char **) d->argv);
+     }
+   
+   macro_bcache_free (t, (char *) d->replacement);
+   macro_free (d, t);
+ }
+ 
+ 
+ /* Find the splay tree node for the definition of NAME at LINE in
+    SOURCE, or zero if there is none.  */
+ static splay_tree_node
+ find_definition (const char *name,
+                  struct macro_source_file *file,
+                  int line)
+ {
+   struct macro_table *t = file->table;
+   splay_tree_node n;
+ 
+   /* Construct a macro_key object, just for the query.  */
+   struct macro_key query;
+ 
+   query.name = name;
+   query.start_file = file;
+   query.start_line = line;
+   query.end_file = 0;
+ 
+   n = splay_tree_lookup (t->definitions, (splay_tree_key) &query);
+   if (! n)
+     {
+       /* It's okay for us to do two queries like this: the real work
+          of the searching is done when we splay, and splaying the tree
+          a second time at the same key is a constant time operation.
+          If this still bugs you, you could always just extend the
+          splay tree library with a predecessor-or-equal operation, and
+          use that.  */
+       splay_tree_node pred = splay_tree_predecessor (t->definitions,
+                                                      (splay_tree_key) &query);
+      
+       if (pred)
+         {
+           /* Make sure this predecessor actually has the right name.
+              We just want to search within a given name's definitions.  */
+           struct macro_key *found = (struct macro_key *) pred->key;
+ 
+           if (! strcmp (found->name, name))
+             n = pred;
+         }
+     }
+ 
+   if (n)
+     {
+       struct macro_key *found = (struct macro_key *) n->key;
+ 
+       /* Okay, so this definition has the right name, and its scope
+          begins before the given source location.  But does its scope
+          end after the given source location?  */
+       if (compare_locations (file, line, found->end_file, found->end_line) < 0)
+         return n;
+       else
+         return 0;
+     }
+   else
+     return 0;
+ }
+ 
+ 
+ /* If NAME already has a definition in scope at LINE in FILE, and
+    return the key.  Otherwise, return zero.  */
+ static struct macro_key *
+ check_for_redefinition (struct macro_source_file *source, int line,
+                         const char *name)
+ {
+   splay_tree_node n = find_definition (name, source, line);
+ 
+   /* This isn't really right.  There's nothing wrong with redefining a
+      macro if the new replacement list is the same as the old one.  */
+   if (n)
+     {
+       struct macro_key *found_key = (struct macro_key *) n->key;
+       static struct complaint macro_redefined = {
+         "macro `%s' redefined at %s:%d;"
+         "original definition at %s:%d", 0, 0
+       };
+       complain (&macro_redefined, name,
+                 source->filename, line,
+                 found_key->start_file->filename,
+                 found_key->start_line);
+       return found_key;
+     }
+   else
+     return 0;
+ }
+ 
+ 
+ void
+ macro_define_object (struct macro_source_file *source, int line,
+                      const char *name, const char *replacement)
+ {
+   struct macro_table *t = source->table;
+   struct macro_key *k;
+   struct macro_definition *d;
+ 
+   k = check_for_redefinition (source, line, name);
+ 
+   /* If we're redefining a symbol, and the existing key would be
+      identical to our new key, then the splay_tree_insert function
+      will try to delete the old definition.  When the definition is
+      living on an obstack, this isn't a happy thing.
+ 
+      Since this only happens in the presence of questionable debug
+      info, we just ignore all definitions after the first.  The only
+      case I know of where this arises is in GCC's output for
+      predefined macros, and all the definitions are the same in that
+      case.  */
+   if (k && ! key_compare (k, name, source, line))
+     return;
+ 
+   k = new_macro_key (t, name, source, line);
+   d = new_macro_definition (t, macro_object_like, 0, 0, replacement);
+   splay_tree_insert (t->definitions, (splay_tree_key) k, (splay_tree_value) d);
+ }
+ 
+ 
+ void
+ macro_define_function (struct macro_source_file *source, int line,
+                        const char *name, int argc, const char **argv,
+                        const char *replacement)
+ {
+   struct macro_table *t = source->table;
+   struct macro_key *k;
+   struct macro_definition *d;
+ 
+   k = check_for_redefinition (source, line, name);
+ 
+   /* See comments about duplicate keys in macro_define_object.  */
+   if (k && ! key_compare (k, name, source, line))
+     return;
+ 
+   /* We should also check here that all the argument names in ARGV are
+      distinct.  */
+ 
+   k = new_macro_key (t, name, source, line);
+   d = new_macro_definition (t, macro_function_like, argc, argv, replacement);
+   splay_tree_insert (t->definitions, (splay_tree_key) k, (splay_tree_value) d);
+ }
+ 
+ 
+ void
+ macro_undef (struct macro_source_file *source, int line,
+              const char *name)
+ {
+   splay_tree_node n = find_definition (name, source, line);
+ 
+   if (n)
+     {
+       /* This function is the only place a macro's end-of-scope
+          location gets set to anything other than "end of the
+          compilation unit" (i.e., end_file is zero).  So if this macro
+          already has its end-of-scope set, then we're probably seeing
+          a second #undefinition for the same #definition.  */
+       struct macro_key *key = (struct macro_key *) n->key;
+ 
+       if (key->end_file)
+         {
+           static struct complaint double_undef = {
+             "macro '%s' is #undefined twice, at %s:%d and %s:%d",
+             0, 0
+           };
+           complain (&double_undef, name, source->filename, line,
+                     key->end_file->filename, key->end_line);
+         }
+ 
+       /* Whatever the case, wipe out the old ending point, and 
+          make this the ending point.  */
+       key->end_file = source;
+       key->end_line = line;
+     }
+   else
+     {
+       /* According to the ISO C standard, an #undef for a symbol that
+          has no macro definition in scope is ignored.  So we should
+          ignore it too.  */
+ #if 0
+       static struct complaint no_macro_to_undefine = {
+         "no definition for macro `%s' in scope to #undef at %s:%d",
+         0, 0
+       };
+       complain (&no_macro_to_undefine, name, source->filename, line);
+ #endif
+     }
+ }
+ 
+ 
+ struct macro_definition *
+ macro_lookup_definition (struct macro_source_file *source,
+                          int line, const char *name)
+ {
+   splay_tree_node n = find_definition (name, source, line);
+ 
+   if (n)
+     return (struct macro_definition *) n->value;
+   else
+     return 0;
+ }
+ 
+ 
+ struct macro_source_file *
+ macro_definition_location (struct macro_source_file *source,
+                            int line,
+                            const char *name,
+                            int *definition_line)
+ {
+   splay_tree_node n = find_definition (name, source, line);
+ 
+   if (n)
+     {
+       struct macro_key *key = (struct macro_key *) n->key;
+       *definition_line = key->start_line;
+       return key->start_file;
+     }
+   else
+     return 0;
+ }
+ 
+ 
+ 
+ /* Creating and freeing macro tables.  */
+ 
+ 
+ struct macro_table *
+ new_macro_table (struct obstack *obstack,
+                  struct bcache *b)
+ {
+   struct macro_table *t;
+ 
+   /* First, get storage for the `struct macro_table' itself.  */
+   if (obstack)
+     t = obstack_alloc (obstack, sizeof (*t));
+   else
+     t = xmalloc (sizeof (*t));
+ 
+   memset (t, 0, sizeof (*t));
+   t->obstack = obstack;
+   t->bcache = b;
+   t->main_source = 0;
+   t->definitions = (splay_tree_new_with_allocator
+                     (macro_tree_compare,
+                      ((splay_tree_delete_key_fn) macro_tree_delete_key),
+                      ((splay_tree_delete_value_fn) macro_tree_delete_value),
+                      ((splay_tree_allocate_fn) macro_alloc),
+                      ((splay_tree_deallocate_fn) macro_free),
+                      t));
+   
+   return t;
+ }
+ 
+ 
+ void
+ free_macro_table (struct macro_table *table)
+ {
+   /* Free the source file tree.  */
+   free_macro_source_file (table->main_source);
+ 
+   /* Free the table of macro definitions.  */
+   splay_tree_delete (table->definitions);
+ }
Index: gdb/macrotab.h
===================================================================
RCS file: macrotab.h
diff -N macrotab.h
*** gdb/macrotab.h	Tue May  5 13:32:27 1998
--- gdb/macrotab.h	Wed Mar 27 22:50:44 2002
***************
*** 0 ****
--- 1,295 ----
+ /* Interface to C preprocessor macro tables for GDB.
+    Copyright 2002 Free Software Foundation, Inc.
+    Contributed by Red Hat, Inc.
+ 
+    This file is part of GDB.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.  */
+ 
+ #ifndef MACROTAB_H
+ #define MACROTAB_H
+ 
+ #include "obstack.h"
+ #include "bcache.h"
+ 
+ /* How do we represent a source location?  I mean, how should we
+    represent them within GDB; the user wants to use all sorts of
+    ambiguous abbreviations, like "break 32" and "break foo.c:32"
+    ("foo.c" may have been #included into several compilation units),
+    but what do we disambiguate those things to?
+ 
+    - Answer 1: "Filename and line number."  (Or column number, if
+    you're picky.)  That's not quite good enough.  For example, the
+    same source file can be #included into several different
+    compilation units --- which #inclusion do you mean?
+ 
+    - Answer 2: "Compilation unit, filename, and line number."  This is
+    a pretty good answer; GDB's `struct symtab_and_line' basically
+    embodies this representation.  But it's still ambiguous; what if a
+    given compilation unit #includes the same file twice --- how can I
+    set a breakpoint on line 12 of the fifth #inclusion of "foo.c"?
+ 
+    - Answer 3: "Compilation unit, chain of #inclusions, and line
+    number."  This is analogous to the way GCC reports errors in
+    #include files:
+ 
+         $ gcc -c base.c
+         In file included from header2.h:8,
+                          from header1.h:3,
+                          from base.c:5:
+         header3.h:1: parse error before ')' token
+         $
+ 
+    GCC tells you exactly what path of #inclusions led you to the
+    problem.  It gives you complete information, in a way that the
+    following would not:
+ 
+         $ gcc -c base.c
+         header3.h:1: parse error before ')' token
+         $
+ 
+    Converting all of GDB to use this is a big task, and I'm not really
+    suggesting it should be a priority.  But this module's whole
+    purpose is to maintain structures describing the macro expansion
+    process, so I think it's appropriate for us to take a little care
+    to do that in a complete fashion.
+ 
+    In this interface, the first line of a file is numbered 1, not 0.
+    This is the same convention the rest of GDB uses.  */
+ 
+ 
+ /* A table of all the macro definitions for a given compilation unit.  */
+ struct macro_table;
+ 
+ 
+ /* A source file that participated in a compilation unit --- either a
+    main file, or an #included file.  If a file is #included more than
+    once, the presence of the `included_from' and `included_at_line'
+    members means that we need to make one instance of this structure
+    for each #inclusion.  Taken as a group, these structures form a
+    tree mapping the #inclusions that contributed to the compilation
+    unit, with the main source file as its root.
+ 
+    It's worth noting that libcpp has a simpler way of representing all
+    this, which we should consider switching to.  It might even be
+    suitable for ordinary non-macro line number info.
+ 
+    Suppose you take your main source file, and after each line
+    containing an #include directive you insert the text of the
+    #included file.  The result is a big file that pretty much
+    corresponds to the full text the compiler's going to see.  There's
+    a one-to-one correspondence between lines in the big file and
+    per-inclusion lines in the source files.  (Obviously, #include
+    directives that are #if'd out don't count.  And you'll need to
+    append a newline to any file that doesn't end in one, to avoid
+    splicing the last #included line with the next line of the
+    #including file.)
+ 
+    Libcpp calls line numbers in this big imaginary file "logical line
+    numbers", and has a data structure called a "line map" that can map
+    logical line numbers onto actual source filenames and line numbers,
+    and also tell you the chain of #inclusions responsible for any
+    particular logical line number.  Basically, this means you can pass
+    around a single line number and some kind of "compilation unit"
+    object and you get nice, unambiguous source code locations that
+    distinguish between multiple #inclusions of the same file, etc.
+ 
+    Pretty neat, huh?  */
+ 
+ struct macro_source_file
+ {
+ 
+   /* The macro table for the compilation unit this source location is
+      a part of.  */
+   struct macro_table *table;
+ 
+   /* A source file --- possibly a header file.  */
+   const char *filename;
+ 
+   /* The location we were #included from, or zero if we are the
+      compilation unit's main source file.  */
+   struct macro_source_file *included_by;
+ 
+   /* If `included_from' is non-zero, the line number in that source
+      file at which we were included.  */
+   int included_at_line;
+ 
+   /* Head of a linked list of the source files #included by this file;
+      our children in the #inclusion tree.  This list is sorted by its
+      elements' `included_at_line' values, which are unique.  (The
+      macro splay tree's ordering function needs this property.)  */
+   struct macro_source_file *includes;
+ 
+   /* The next file #included by our `included_from' file; our sibling
+      in the #inclusion tree.  */
+   struct macro_source_file *next_included;
+ };
+ 
+ 
+ /* Create a new, empty macro table.  Allocate it in OBSTACK, or use
+    xmalloc if OBSTACK is zero.  Use BCACHE to store all macro names,
+    arguments, definitions, and anything else that might be the same
+    amongst compilation units in an executable file; if BCACHE is zero,
+    don't cache these things.
+ 
+    Note that, if either OBSTACK or BCACHE are non-zero, then you
+    should only ever add information the macro table --- you should
+    never remove things from it.  You'll get an error if you try.  At
+    the moment, since we only provide obstacks and bcaches for macro
+    tables for symtabs, this restriction makes a nice sanity check.
+    Obstacks and bcaches are pretty much grow-only structures anyway.
+    However, if we find that it's occasionally useful to delete things
+    even from the symtab's tables, and the storage leak isn't a
+    problem, this restriction could be lifted.  */
+ struct macro_table *new_macro_table (struct obstack *obstack,
+                                      struct bcache *bcache);
+ 
+ 
+ /* Free TABLE, and any macro definitions, source file structures,
+    etc. it owns.  This will raise an internal error if TABLE was
+    allocated on an obstack, or if it uses a bcache.  */
+ void free_macro_table (struct macro_table *table);
+ 
+ 
+ /* Set FILENAME as the main source file of TABLE.  Return a source
+    file structure describing that file; if we record the #definition
+    of macros, or the #inclusion of other files into FILENAME, we'll
+    use that source file structure to indicate the context.
+ 
+    The "main source file" is the one that was given to the compiler;
+    all other source files that contributed to the compilation unit are
+    #included, directly or indirectly, from this one.
+ 
+    The macro table makes its own copy of FILENAME; the caller is
+    responsible for freeing FILENAME when it is no longer needed.  */
+ struct macro_source_file *macro_set_main (struct macro_table *table,
+                                           const char *filename);
+ 
+ 
+ /* Return the main source file of the macro table TABLE.  */
+ struct macro_source_file *macro_main (struct macro_table *table);
+ 
+ 
+ /* Record a #inclusion.
+    Record in SOURCE's macro table that, at line number LINE in SOURCE,
+    we #included the file INCLUDED.  Return a source file structure we
+    can use for symbols #defined or files #included into that.  If we've
+    already created a source file structure for this #inclusion, return
+    the same structure we created last time.
+ 
+    The first line of the source file has a line number of 1, not 0.
+ 
+    The macro table makes its own copy of INCLUDED; the caller is
+    responsible for freeing INCLUDED when it is no longer needed.  */
+ struct macro_source_file *macro_include (struct macro_source_file *source,
+                                          int line,
+                                          const char *included);
+ 
+ 
+ /* Find any source file structure for a file named NAME, either
+    included into SOURCE, or SOURCE itself.  Return zero if we have
+    none.  NAME is only the final portion of the filename, not the full
+    path.  e.g., `stdio.h', not `/usr/include/stdio.h'.  If NAME
+    appears more than once in the inclusion tree, return the
+    least-nested inclusion --- the one closest to the main source file.  */
+ struct macro_source_file *(macro_lookup_inclusion
+                            (struct macro_source_file *source,
+                             const char *name));
+ 
+ 
+ /* Record an object-like #definition (i.e., one with no parameter list).
+    Record in SOURCE's macro table that, at line number LINE in SOURCE,
+    we #defined a preprocessor symbol named NAME, whose replacement
+    string is REPLACEMENT.  This function makes copies of NAME and
+    REPLACEMENT; the caller is responsible for freeing them.  */
+ void macro_define_object (struct macro_source_file *source, int line,
+                           const char *name, const char *replacement);
+ 
+ 
+ /* Record an function-like #definition (i.e., one with a parameter list).
+ 
+    Record in SOURCE's macro table that, at line number LINE in SOURCE,
+    we #defined a preprocessor symbol named NAME, with ARGC arguments
+    whose names are given in ARGV, whose replacement string is REPLACEMENT.  If
+    the macro takes a variable number of arguments, then ARGC should be
+    one greater than the number of named arguments, and ARGV[ARGC-1]
+    should be the string "...".  This function makes its own copies of
+    NAME, ARGV, and REPLACEMENT; the caller is responsible for freeing
+    them.  */
+ void macro_define_function (struct macro_source_file *source, int line,
+                             const char *name, int argc, const char **argv,
+                             const char *replacement);
+ 
+ 
+ /* Record an #undefinition.
+    Record in SOURCE's macro table that, at line number LINE in SOURCE,
+    we removed the definition for the preprocessor symbol named NAME.  */
+ void macro_undef (struct macro_source_file *source, int line,
+                   const char *name);
+ 
+ 
+ /* Different kinds of macro definitions.  */
+ enum macro_kind
+ {
+   macro_object_like,
+   macro_function_like
+ };
+ 
+ 
+ /* A preprocessor symbol definition.  */
+ struct macro_definition
+ {
+   /* The table this definition lives in.  */
+   struct macro_table *table;
+ 
+   /* What kind of macro it is.  */
+   enum macro_kind kind;
+ 
+   /* If `kind' is `macro_function_like', the number of arguments it
+      takes, and their names.  The names, and the array of pointers to
+      them, are in the table's bcache, if it has one.  */
+   int argc;
+   const char * const *argv;
+ 
+   /* The replacement string (body) of the macro.  This is in the
+      table's bcache, if it has one.  */
+   const char *replacement;
+ };
+ 
+ 
+ /* Return a pointer to the macro definition for NAME in scope at line
+    number LINE of SOURCE.  If LINE is -1, return the definition in
+    effect at the end of the file.  The macro table owns the structure;
+    the caller need not free it.  Return zero if NAME is not #defined
+    at that point.  */
+ struct macro_definition *(macro_lookup_definition
+                           (struct macro_source_file *source,
+                            int line, const char *name));
+ 
+ 
+ /* Return the source location of the definition for NAME in scope at
+    line number LINE of SOURCE.  Set *DEFINITION_LINE to the line
+    number of the definition, and return a source file structure for
+    the file.  Return zero if NAME has no definition in scope at that
+    point, and leave *DEFINITION_LINE unchanged.  */
+ struct macro_source_file *(macro_definition_location
+                            (struct macro_source_file *source,
+                             int line,
+                             const char *name,
+                             int *definition_line));
+ 
+ 
+ #endif /* MACROTAB_H */
Index: gdb/objfiles.c
===================================================================
RCS file: /cvs/src/src/gdb/objfiles.c,v
retrieving revision 1.19
diff -c -r1.19 objfiles.c
*** gdb/objfiles.c	2001/12/06 20:59:11	1.19
--- gdb/objfiles.c	2002/03/28 06:50:45
***************
*** 190,195 ****
--- 190,197 ----
  	      /* Update pointers to functions to *our* copies */
  	      obstack_chunkfun (&objfile->psymbol_cache.cache, xmmalloc);
  	      obstack_freefun (&objfile->psymbol_cache.cache, xmfree);
+ 	      obstack_chunkfun (&objfile->macro_cache.cache, xmmalloc);
+ 	      obstack_freefun (&objfile->macro_cache.cache, xmfree);
  	      obstack_chunkfun (&objfile->psymbol_obstack, xmmalloc);
  	      obstack_freefun (&objfile->psymbol_obstack, xmfree);
  	      obstack_chunkfun (&objfile->symbol_obstack, xmmalloc);
***************
*** 220,225 ****
--- 222,230 ----
  	      obstack_specify_allocation_with_arg (&objfile->psymbol_cache.cache,
  						   0, 0, xmmalloc, xmfree,
  						   objfile->md);
+ 	      obstack_specify_allocation_with_arg (&objfile->macro_cache.cache,
+ 						   0, 0, xmmalloc, xmfree,
+ 						   objfile->md);
  	      obstack_specify_allocation_with_arg (&objfile->psymbol_obstack,
  						   0, 0, xmmalloc, xmfree,
  						   objfile->md);
***************
*** 266,271 ****
--- 271,278 ----
        objfile->md = NULL;
        obstack_specify_allocation (&objfile->psymbol_cache.cache, 0, 0,
  				  xmalloc, xfree);
+       obstack_specify_allocation (&objfile->macro_cache.cache, 0, 0,
+ 				  xmalloc, xfree);
        obstack_specify_allocation (&objfile->psymbol_obstack, 0, 0, xmalloc,
  				  xfree);
        obstack_specify_allocation (&objfile->symbol_obstack, 0, 0, xmalloc,
***************
*** 477,482 ****
--- 484,490 ----
  	xmfree (objfile->md, objfile->static_psymbols.list);
        /* Free the obstacks for non-reusable objfiles */
        free_bcache (&objfile->psymbol_cache);
+       free_bcache (&objfile->macro_cache);
        obstack_free (&objfile->psymbol_obstack, 0);
        obstack_free (&objfile->symbol_obstack, 0);
        obstack_free (&objfile->type_obstack, 0);
Index: gdb/objfiles.h
===================================================================
RCS file: /cvs/src/src/gdb/objfiles.h,v
retrieving revision 1.9
diff -c -r1.9 objfiles.h
*** gdb/objfiles.h	2001/10/12 19:07:07	1.9
--- gdb/objfiles.h	2002/03/28 06:50:46
***************
*** 277,282 ****
--- 277,283 ----
         will not change. */
  
      struct bcache psymbol_cache;	/* Byte cache for partial syms */
+     struct bcache macro_cache;          /* Byte cache for macros */
  
      /* Vectors of all partial symbols read in from file.  The actual data
         is stored in the psymbol_obstack. */
Index: gdb/parse.c
===================================================================
RCS file: /cvs/src/src/gdb/parse.c,v
retrieving revision 1.19
diff -c -r1.19 parse.c
*** gdb/parse.c	2002/01/31 02:13:56	1.19
--- gdb/parse.c	2002/03/28 06:50:46
***************
*** 69,74 ****
--- 69,75 ----
  int expout_size;
  int expout_ptr;
  struct block *expression_context_block;
+ CORE_ADDR expression_context_pc;
  struct block *innermost_block;
  int arglist_len;
  union type_stack_elt *type_stack;
***************
*** 1134,1140 ****
    old_chain = make_cleanup (free_funcalls, 0 /*ignore*/);
    funcall_chain = 0;
  
!   expression_context_block = block ? block : get_selected_block ();
  
    namecopy = (char *) alloca (strlen (lexptr) + 1);
    expout_size = 10;
--- 1135,1147 ----
    old_chain = make_cleanup (free_funcalls, 0 /*ignore*/);
    funcall_chain = 0;
  
!   if (block)
!     {
!       expression_context_block = block;
!       expression_context_pc = block->startaddr;
!     }
!   else
!     expression_context_block = get_selected_block (&expression_context_pc);
  
    namecopy = (char *) alloca (strlen (lexptr) + 1);
    expout_size = 10;
Index: gdb/parser-defs.h
===================================================================
RCS file: /cvs/src/src/gdb/parser-defs.h,v
retrieving revision 1.6
diff -c -r1.6 parser-defs.h
*** gdb/parser-defs.h	2001/11/15 01:55:59	1.6
--- gdb/parser-defs.h	2002/03/28 06:50:47
***************
*** 44,49 ****
--- 44,55 ----
  
  extern struct block *expression_context_block;
  
+ /* If expression_context_block is non-zero, then this is the PC within
+    the block that we want to evaluate expressions at.  When debugging
+    C or C++ code, we use this to find the exact line we're at, and
+    then look up the macro definitions active at that point.  */
+ CORE_ADDR expression_context_pc;
+ 
  /* The innermost context required by the stack and register variables
     we've encountered so far. */
  extern struct block *innermost_block;
Index: gdb/printcmd.c
===================================================================
RCS file: /cvs/src/src/gdb/printcmd.c,v
retrieving revision 1.37
diff -c -r1.37 printcmd.c
*** gdb/printcmd.c	2002/03/06 06:28:33	1.37
--- gdb/printcmd.c	2002/03/28 06:50:48
***************
*** 1113,1119 ****
    if (exp == 0)
      error ("Argument required.");
  
!   sym = lookup_symbol (exp, get_selected_block (), VAR_NAMESPACE,
  		       &is_a_field_of_this, (struct symtab **) NULL);
    if (sym == NULL)
      {
--- 1113,1119 ----
    if (exp == 0)
      error ("Argument required.");
  
!   sym = lookup_symbol (exp, get_selected_block (0), VAR_NAMESPACE,
  		       &is_a_field_of_this, (struct symtab **) NULL);
    if (sym == NULL)
      {
***************
*** 1549,1555 ****
      return;
  
    if (d->block)
!     within_current_scope = contained_in (get_selected_block (), d->block);
    else
      within_current_scope = 1;
    if (!within_current_scope)
--- 1549,1555 ----
      return;
  
    if (d->block)
!     within_current_scope = contained_in (get_selected_block (0), d->block);
    else
      within_current_scope = 1;
    if (!within_current_scope)
***************
*** 1683,1689 ****
        else if (d->format.format)
  	printf_filtered ("/%c ", d->format.format);
        print_expression (d->exp, gdb_stdout);
!       if (d->block && !contained_in (get_selected_block (), d->block))
  	printf_filtered (" (cannot be evaluated in the current context)");
        printf_filtered ("\n");
        gdb_flush (gdb_stdout);
--- 1683,1689 ----
        else if (d->format.format)
  	printf_filtered ("/%c ", d->format.format);
        print_expression (d->exp, gdb_stdout);
!       if (d->block && !contained_in (get_selected_block (0), d->block))
  	printf_filtered (" (cannot be evaluated in the current context)");
        printf_filtered ("\n");
        gdb_flush (gdb_stdout);
Index: gdb/solib-sunos.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-sunos.c,v
retrieving revision 1.3
diff -c -r1.3 solib-sunos.c
*** gdb/solib-sunos.c	2002/01/23 06:24:20	1.3
--- gdb/solib-sunos.c	2002/03/28 06:50:48
***************
*** 137,142 ****
--- 137,144 ----
    objfile->md = NULL;
    obstack_specify_allocation (&objfile->psymbol_cache.cache, 0, 0,
  			      xmalloc, xfree);
+   obstack_specify_allocation (&objfile->macro_cache.cache, 0, 0,
+ 			      xmalloc, xfree);
    obstack_specify_allocation (&objfile->psymbol_obstack, 0, 0, xmalloc,
  			      xfree);
    obstack_specify_allocation (&objfile->symbol_obstack, 0, 0, xmalloc,
Index: gdb/stack.c
===================================================================
RCS file: /cvs/src/src/gdb/stack.c,v
retrieving revision 1.30
diff -c -r1.30 stack.c
*** gdb/stack.c	2002/03/23 17:38:13	1.30
--- gdb/stack.c	2002/03/28 06:50:50
***************
*** 1238,1244 ****
  print_frame_local_vars (register struct frame_info *fi, register int num_tabs,
  			register struct ui_file *stream)
  {
!   register struct block *block = get_frame_block (fi);
    register int values_printed = 0;
  
    if (block == 0)
--- 1238,1244 ----
  print_frame_local_vars (register struct frame_info *fi, register int num_tabs,
  			register struct ui_file *stream)
  {
!   register struct block *block = get_frame_block (fi, 0);
    register int values_printed = 0;
  
    if (block == 0)
***************
*** 1272,1278 ****
  			register struct ui_file *stream)
  {
    register struct blockvector *bl;
!   register struct block *block = get_frame_block (fi);
    register int values_printed = 0;
    int index, have_default = 0;
    char *blocks_printed;
--- 1272,1278 ----
  			register struct ui_file *stream)
  {
    register struct blockvector *bl;
!   register struct block *block = get_frame_block (fi, 0);
    register int values_printed = 0;
    int index, have_default = 0;
    char *blocks_printed;
***************
*** 1501,1517 ****
  }
  
  /* Return the symbol-block in which the selected frame is executing.
!    Can return zero under various legitimate circumstances.  */
  
  struct block *
! get_selected_block (void)
  {
    if (!target_has_stack)
      return 0;
  
    if (!selected_frame)
!     return get_current_block ();
!   return get_frame_block (selected_frame);
  }
  
  /* Find a frame a certain number of levels away from FRAME.
--- 1501,1521 ----
  }
  
  /* Return the symbol-block in which the selected frame is executing.
!    Can return zero under various legitimate circumstances.
  
+    If PC_IN_BLOCK is non-zero, set *PC_IN_BLOCK to the relevant PC
+    value within the block returned.  We use this to decide which
+    macros are in scope.  */
+ 
  struct block *
! get_selected_block (CORE_ADDR *pc_in_block)
  {
    if (!target_has_stack)
      return 0;
  
    if (!selected_frame)
!     return get_current_block (pc_in_block);
!   return get_frame_block (selected_frame, pc_in_block);
  }
  
  /* Find a frame a certain number of levels away from FRAME.
Index: gdb/symfile.c
===================================================================
RCS file: /cvs/src/src/gdb/symfile.c,v
retrieving revision 1.56
diff -c -r1.56 symfile.c
*** gdb/symfile.c	2002/03/19 03:51:06	1.56
--- gdb/symfile.c	2002/03/28 06:50:51
***************
*** 1699,1704 ****
--- 1699,1705 ----
  
  	      /* Free the obstacks for non-reusable objfiles */
  	      free_bcache (&objfile->psymbol_cache);
+ 	      free_bcache (&objfile->macro_cache);
  	      obstack_free (&objfile->psymbol_obstack, 0);
  	      obstack_free (&objfile->symbol_obstack, 0);
  	      obstack_free (&objfile->type_obstack, 0);
***************
*** 1723,1728 ****
--- 1724,1731 ----
  	      /* obstack_specify_allocation also initializes the obstack so
  	         it is empty.  */
  	      obstack_specify_allocation (&objfile->psymbol_cache.cache, 0, 0,
+ 					  xmalloc, xfree);
+ 	      obstack_specify_allocation (&objfile->macro_cache.cache, 0, 0,
  					  xmalloc, xfree);
  	      obstack_specify_allocation (&objfile->psymbol_obstack, 0, 0,
  					  xmalloc, xfree);
Index: gdb/symmisc.c
===================================================================
RCS file: /cvs/src/src/gdb/symmisc.c,v
retrieving revision 1.8
diff -c -r1.8 symmisc.c
*** gdb/symmisc.c	2002/03/22 18:57:08	1.8
--- gdb/symmisc.c	2002/03/28 06:50:52
***************
*** 197,202 ****
--- 197,204 ----
  		     obstack_memory_used (&objfile->psymbol_obstack));
      printf_filtered ("  Total memory used for psymbol cache: %d\n",
  		     obstack_memory_used (&objfile->psymbol_cache.cache));
+     printf_filtered ("  Total memory used for macro cache: %d\n",
+ 		     obstack_memory_used (&objfile->macro_cache.cache));
      printf_filtered ("  Total memory used for symbol obstack: %d\n",
  		     obstack_memory_used (&objfile->symbol_obstack));
      printf_filtered ("  Total memory used for type obstack: %d\n",
Index: gdb/symtab.c
===================================================================
RCS file: /cvs/src/src/gdb/symtab.c,v
retrieving revision 1.59
diff -c -r1.59 symtab.c
*** gdb/symtab.c	2002/03/27 23:10:23	1.59
--- gdb/symtab.c	2002/03/28 06:50:54
***************
*** 3279,3285 ****
    /* Search upwards from currently selected frame (so that we can
       complete on local vars.  */
  
!   for (b = get_selected_block (); b != NULL; b = BLOCK_SUPERBLOCK (b))
      {
        if (!BLOCK_SUPERBLOCK (b))
  	{
--- 3279,3285 ----
    /* Search upwards from currently selected frame (so that we can
       complete on local vars.  */
  
!   for (b = get_selected_block (0); b != NULL; b = BLOCK_SUPERBLOCK (b))
      {
        if (!BLOCK_SUPERBLOCK (b))
  	{
***************
*** 3812,3818 ****
    /* Search upwards from currently selected frame (so that we can
       complete on local vars.  */
  
!   for (b = get_selected_block (); b != NULL; b = BLOCK_SUPERBLOCK (b))
      {
        if (!BLOCK_SUPERBLOCK (b))
  	{
--- 3812,3818 ----
    /* Search upwards from currently selected frame (so that we can
       complete on local vars.  */
  
!   for (b = get_selected_block (0); b != NULL; b = BLOCK_SUPERBLOCK (b))
      {
        if (!BLOCK_SUPERBLOCK (b))
  	{
Index: gdb/symtab.h
===================================================================
RCS file: /cvs/src/src/gdb/symtab.h,v
retrieving revision 1.29
diff -c -r1.29 symtab.h
*** gdb/symtab.h	2002/03/27 23:10:24	1.29
--- gdb/symtab.h	2002/03/28 06:50:55
***************
*** 820,825 ****
--- 820,830 ----
  
      int primary;
  
+     /* The macro table for this symtab.  Like the blockvector, this
+        may be shared between different symtabs --- and normally is for
+        all the symtabs in a given compilation unit.  */
+     struct macro_table *macro_table;
+ 
      /* Name of this source file.  */
  
      char *filename;
Index: gdb/varobj.c
===================================================================
RCS file: /cvs/src/src/gdb/varobj.c,v
retrieving revision 1.26
diff -c -r1.26 varobj.c
*** gdb/varobj.c	2002/01/13 20:17:55	1.26
--- gdb/varobj.c	2002/03/28 06:50:56
***************
*** 426,432 ****
  
        block = NULL;
        if (fi != NULL)
! 	block = get_frame_block (fi);
  
        p = expression;
        innermost_block = NULL;
--- 426,432 ----
  
        block = NULL;
        if (fi != NULL)
! 	block = get_frame_block (fi, 0);
  
        p = expression;
        innermost_block = NULL;
Index: gdb/mi/mi-cmd-stack.c
===================================================================
RCS file: /cvs/src/src/gdb/mi/mi-cmd-stack.c,v
retrieving revision 1.10
diff -c -r1.10 mi-cmd-stack.c
*** gdb/mi/mi-cmd-stack.c	2002/02/05 19:28:36	1.10
--- gdb/mi/mi-cmd-stack.c	2002/03/28 06:50:57
***************
*** 218,224 ****
  
    stb = ui_out_stream_new (uiout);
  
!   block = get_frame_block (fi);
  
    ui_out_list_begin (uiout, locals ? "locals" : "args");
  
--- 218,224 ----
  
    stb = ui_out_stream_new (uiout);
  
!   block = get_frame_block (fi, 0);
  
    ui_out_list_begin (uiout, locals ? "locals" : "args");
  


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