From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 32061 invoked by alias); 28 Mar 2002 07:05:30 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 32012 invoked from network); 28 Mar 2002 07:05:06 -0000 Received: from unknown (HELO zwingli.cygnus.com) (208.245.165.35) by sources.redhat.com with SMTP; 28 Mar 2002 07:05:06 -0000 Received: by zwingli.cygnus.com (Postfix, from userid 442) id 24F455EA11; Thu, 28 Mar 2002 02:05:04 -0500 (EST) From: Jim Blandy To: gdb-patches@sources.redhat.com Subject: RFC: preprocessor macro support (should actually work now) Message-Id: <20020328070504.24F455EA11@zwingli.cygnus.com> Date: Wed, 27 Mar 2002 23:05:00 -0000 X-SW-Source: 2002-03/txt/msg00576.txt.bz2 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: + + " " + + For function-like macro definitions, it should be: + + "() " + or + "(" ( "," ) * ") " + + Spaces may appear only where explicitly indicated, and in the + . + + 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.", + ¯olist, "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.", + ¯olist); + add_alias_cmd ("exp", "expand", no_class, 1, ¯olist); + 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.", + ¯olist); + add_alias_cmd ("exp1", "expand-once", no_class, 1, ¯olist); + + 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))", + ¯olist); + + add_cmd + ("undef", no_class, macro_undef_command, + "Remove the definition of the C/C++ preprocessor macro with the" + " given name.", + ¯olist); + + add_cmd + ("list", no_class, macro_list_command, + "List all the macros defined using the `macro define' command.", + ¯olist); + + 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 (¯o_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");