From: Andrew Burgess Date: Fri, 4 Oct 2019 16:59:51 +0000 (+0100) Subject: gdb/mi: Add -symbol-info-module-{variables,functions} X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=293b38d60f15422cf7e3d3ba06fdbc5cc90aee67;p=binutils-gdb.git gdb/mi: Add -symbol-info-module-{variables,functions} Two new MI command -symbol-info-module-variables and -symbol-info-module-functions, which are the equivalent of the CLI command 'info module variables' and 'info module functions'. These return information about functions and variables within Fortran modules. gdb/ChangeLog: * mi/mi-cmds.c (mi_cmds): Add -symbol-info-module-functions and -symbol-info-module-variables entries. * mi/mi-cmds.h (mi_cmd_symbol_info_module_functions): Declare. (mi_cmd_symbol_info_module_variables): Declare. * mi/mi-symbol-cmds.c (module_symbol_search_iterator): New typedef. (output_module_symbols_in_single_module_and_file): New function. (output_module_symbols_in_single_module): New function. (mi_info_module_functions_or_variables): New function. (mi_cmd_symbol_info_module_functions): New function. (mi_cmd_symbol_info_module_variables): New function. * NEWS: Mention new MI command. gdb/doc/ChangeLog: * doc/gdb.texinfo (GDB/MI Symbol Query): Document new MI command -symbol-info-module-functions and -symbol-info-module-variables. gdb/testsuite/ChangeLog: * gdb.mi/mi-fortran-modules.exp: Add additional tests for -symbol-info-module-functions and -symbol-info-module-variables. Change-Id: Ic96f12dd14bd7e34774c3cde008fec30a4055bfe --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index d12bd1c5a57..85607bbad43 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,18 @@ +2019-12-04 Andrew Burgess + + * mi/mi-cmds.c (mi_cmds): Add -symbol-info-module-functions and + -symbol-info-module-variables entries. + * mi/mi-cmds.h (mi_cmd_symbol_info_module_functions): Declare. + (mi_cmd_symbol_info_module_variables): Declare. + * mi/mi-symbol-cmds.c + (module_symbol_search_iterator): New typedef. + (output_module_symbols_in_single_module_and_file): New function. + (output_module_symbols_in_single_module): New function. + (mi_info_module_functions_or_variables): New function. + (mi_cmd_symbol_info_module_functions): New function. + (mi_cmd_symbol_info_module_variables): New function. + * NEWS: Mention new MI command. + 2019-12-03 Christian Biesinger * bcache.c (hash): Remove. diff --git a/gdb/NEWS b/gdb/NEWS index 0a04146894b..372a83aa17e 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -402,6 +402,10 @@ focus, winheight, +, -, >, < -symbol-info-modules, this is the MI equivalent of the CLI 'info modules' command. +-symbol-info-module-functions and -symbol-info-module-variables. + These commands are the MI equivalent of the CLI commands 'info + module functions' and 'info module variables'. + * Other MI changes ** The default version of the MI interpreter is now 3 (-i=mi3). diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 6b6f28ea56e..5b3eab7d732 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2019-12-04 Andrew Burgess + + * doc/gdb.texinfo (GDB/MI Symbol Query): Document new MI command + -symbol-info-module-functions and -symbol-info-module-variables. + 2019-12-01 Tom Tromey * gdb.texinfo (TUI Configuration): Mention TUI border styles. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 198862a55ec..6fb7e8ab7ea 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -34058,6 +34058,148 @@ The corresponding @value{GDBN} command is @samp{info functions}. @end group @end smallexample +@subheading The @code{-symbol-info-module-functions} Command +@findex -symbol-info-module-functions +@anchor{-symbol-info-module-functions} + +@subsubheading Synopsis + +@smallexample + -symbol-info-module-functions [--module @var{module_regexp}] + [--name @var{name_regexp}] + [--type @var{type_regexp}] +@end smallexample + +@noindent +Return a list containing the names of all known functions within all +know Fortran modules. The functions are grouped by source file and +containing module, and shown with the line number on which each +function is defined. + +The option @code{--module} only returns results for modules matching +@var{module_regexp}. The option @code{--name} only returns functions +whose name matches @var{name_regexp}, and @code{--type} only returns +functions whose type matches @var{type_regexp}. + +@subsubheading @value{GDBN} Command + +The corresponding @value{GDBN} command is @samp{info module functions}. + +@subsubheading Example + +@smallexample +@group +(gdb) +-symbol-info-module-functions +^done,symbols= + [@{module="mod1", + files=[@{filename="/project/gdb/testsuite/gdb.mi/mi-fortran-modules-2.f90", + fullname="/project/gdb/testsuite/gdb.mi/mi-fortran-modules-2.f90", + symbols=[@{line="21",name="mod1::check_all",type="void (void)", + description="void mod1::check_all(void);"@}]@}]@}, + @{module="mod2", + files=[@{filename="/project/gdb/testsuite/gdb.mi/mi-fortran-modules-2.f90", + fullname="/project/gdb/testsuite/gdb.mi/mi-fortran-modules-2.f90", + symbols=[@{line="30",name="mod2::check_var_i",type="void (void)", + description="void mod2::check_var_i(void);"@}]@}]@}, + @{module="mod3", + files=[@{filename="/projec/gdb/testsuite/gdb.mi/mi-fortran-modules.f90", + fullname="/projec/gdb/testsuite/gdb.mi/mi-fortran-modules.f90", + symbols=[@{line="21",name="mod3::check_all",type="void (void)", + description="void mod3::check_all(void);"@}, + @{line="27",name="mod3::check_mod2",type="void (void)", + description="void mod3::check_mod2(void);"@}]@}]@}, + @{module="modmany", + files=[@{filename="/project/gdb/testsuite/gdb.mi/mi-fortran-modules.f90", + fullname="/project/gdb/testsuite/gdb.mi/mi-fortran-modules.f90", + symbols=[@{line="35",name="modmany::check_some",type="void (void)", + description="void modmany::check_some(void);"@}]@}]@}, + @{module="moduse", + files=[@{filename="/project/gdb/testsuite/gdb.mi/mi-fortran-modules.f90", + fullname="/project/gdb/testsuite/gdb.mi/mi-fortran-modules.f90", + symbols=[@{line="44",name="moduse::check_all",type="void (void)", + description="void moduse::check_all(void);"@}, + @{line="49",name="moduse::check_var_x",type="void (void)", + description="void moduse::check_var_x(void);"@}]@}]@}] +@end group +@end smallexample + +@subheading The @code{-symbol-info-module-variables} Command +@findex -symbol-info-module-variables +@anchor{-symbol-info-module-variables} + +@subsubheading Synopsis + +@smallexample + -symbol-info-module-variables [--module @var{module_regexp}] + [--name @var{name_regexp}] + [--type @var{type_regexp}] +@end smallexample + +@noindent +Return a list containing the names of all known variables within all +know Fortran modules. The variables are grouped by source file and +containing module, and shown with the line number on which each +variable is defined. + +The option @code{--module} only returns results for modules matching +@var{module_regexp}. The option @code{--name} only returns variables +whose name matches @var{name_regexp}, and @code{--type} only returns +variables whose type matches @var{type_regexp}. + +@subsubheading @value{GDBN} Command + +The corresponding @value{GDBN} command is @samp{info module variables}. + +@subsubheading Example + +@smallexample +@group +(gdb) +-symbol-info-module-variables +^done,symbols= + [@{module="mod1", + files=[@{filename="/project/gdb/testsuite/gdb.mi/mi-fortran-modules-2.f90", + fullname="/project/gdb/testsuite/gdb.mi/mi-fortran-modules-2.f90", + symbols=[@{line="18",name="mod1::var_const",type="integer(kind=4)", + description="integer(kind=4) mod1::var_const;"@}, + @{line="17",name="mod1::var_i",type="integer(kind=4)", + description="integer(kind=4) mod1::var_i;"@}]@}]@}, + @{module="mod2", + files=[@{filename="/project/gdb/testsuite/gdb.mi/mi-fortran-modules-2.f90", + fullname="/project/gdb/testsuite/gdb.mi/mi-fortran-modules-2.f90", + symbols=[@{line="28",name="mod2::var_i",type="integer(kind=4)", + description="integer(kind=4) mod2::var_i;"@}]@}]@}, + @{module="mod3", + files=[@{filename="/project/gdb/testsuite/gdb.mi/mi-fortran-modules.f90", + fullname="/project/gdb/testsuite/gdb.mi/mi-fortran-modules.f90", + symbols=[@{line="18",name="mod3::mod1",type="integer(kind=4)", + description="integer(kind=4) mod3::mod1;"@}, + @{line="17",name="mod3::mod2",type="integer(kind=4)", + description="integer(kind=4) mod3::mod2;"@}, + @{line="19",name="mod3::var_i",type="integer(kind=4)", + description="integer(kind=4) mod3::var_i;"@}]@}]@}, + @{module="modmany", + files=[@{filename="/project/gdb/testsuite/gdb.mi/mi-fortran-modules.f90", + fullname="/project/gdb/testsuite/gdb.mi/mi-fortran-modules.f90", + symbols=[@{line="33",name="modmany::var_a",type="integer(kind=4)", + description="integer(kind=4) modmany::var_a;"@}, + @{line="33",name="modmany::var_b",type="integer(kind=4)", + description="integer(kind=4) modmany::var_b;"@}, + @{line="33",name="modmany::var_c",type="integer(kind=4)", + description="integer(kind=4) modmany::var_c;"@}, + @{line="33",name="modmany::var_i",type="integer(kind=4)", + description="integer(kind=4) modmany::var_i;"@}]@}]@}, + @{module="moduse", + files=[@{filename="/project/gdb/testsuite/gdb.mi/mi-fortran-modules.f90", + fullname="/project/gdb/testsuite/gdb.mi/mi-fortran-modules.f90", + symbols=[@{line="42",name="moduse::var_x",type="integer(kind=4)", + description="integer(kind=4) moduse::var_x;"@}, + @{line="42",name="moduse::var_y",type="integer(kind=4)", + description="integer(kind=4) moduse::var_y;"@}]@}]@}] +@end group +@end smallexample + @subheading The @code{-symbol-info-modules} Command @findex -symbol-info-modules @anchor{-symbol-info-modules} diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c index 85c15ec5357..991fb4b9c20 100644 --- a/gdb/mi/mi-cmds.c +++ b/gdb/mi/mi-cmds.c @@ -155,6 +155,10 @@ static struct mi_cmd mi_cmds[] = DEF_MI_CMD_MI ("symbol-info-variables", mi_cmd_symbol_info_variables), DEF_MI_CMD_MI ("symbol-info-types", mi_cmd_symbol_info_types), DEF_MI_CMD_MI ("symbol-info-modules", mi_cmd_symbol_info_modules), + DEF_MI_CMD_MI ("symbol-info-module-functions", + mi_cmd_symbol_info_module_functions), + DEF_MI_CMD_MI ("symbol-info-module-variables", + mi_cmd_symbol_info_module_variables), DEF_MI_CMD_CLI ("target-attach", "attach", 1), DEF_MI_CMD_MI ("target-detach", mi_cmd_target_detach), DEF_MI_CMD_CLI ("target-disconnect", "disconnect", 0), diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h index 30de780286b..faeb36b40ee 100644 --- a/gdb/mi/mi-cmds.h +++ b/gdb/mi/mi-cmds.h @@ -95,6 +95,8 @@ extern mi_cmd_argv_ftype mi_cmd_stack_list_variables; extern mi_cmd_argv_ftype mi_cmd_stack_select_frame; extern mi_cmd_argv_ftype mi_cmd_symbol_list_lines; extern mi_cmd_argv_ftype mi_cmd_symbol_info_functions; +extern mi_cmd_argv_ftype mi_cmd_symbol_info_module_functions; +extern mi_cmd_argv_ftype mi_cmd_symbol_info_module_variables; extern mi_cmd_argv_ftype mi_cmd_symbol_info_modules; extern mi_cmd_argv_ftype mi_cmd_symbol_info_types; extern mi_cmd_argv_ftype mi_cmd_symbol_info_variables; diff --git a/gdb/mi/mi-symbol-cmds.c b/gdb/mi/mi-symbol-cmds.c index 10dd273f338..2bebd11f799 100644 --- a/gdb/mi/mi-symbol-cmds.c +++ b/gdb/mi/mi-symbol-cmds.c @@ -216,6 +216,143 @@ mi_info_functions_or_variables (enum search_domain kind, char **argv, int argc) mi_symbol_info (kind, regexp, t_regexp, exclude_minsyms); } +/* Type for an iterator over a vector of module_symbol_search results. */ +typedef std::vector::const_iterator + module_symbol_search_iterator; + +/* Helper for mi_info_module_functions_or_variables. Display the results + from ITER up to END or until we find a symbol that is in a different + module, or in a different symtab than the first symbol we print. Update + and return the new value for ITER. */ +static module_symbol_search_iterator +output_module_symbols_in_single_module_and_file + (struct ui_out *uiout, module_symbol_search_iterator iter, + const module_symbol_search_iterator end, enum search_domain kind) +{ + /* The symbol for the module in which the first result resides. */ + const symbol *first_module_symbol = iter->first.symbol; + + /* The symbol for the first result, and the symtab in which it resides. */ + const symbol *first_result_symbol = iter->second.symbol; + symtab *first_symbtab = symbol_symtab (first_result_symbol); + + /* Formatted output. */ + ui_out_emit_tuple current_file (uiout, nullptr); + uiout->field_string ("filename", + symtab_to_filename_for_display (first_symbtab)); + uiout->field_string ("fullname", symtab_to_fullname (first_symbtab)); + ui_out_emit_list item_list (uiout, "symbols"); + + /* Repeatedly output result symbols until either we run out of symbols, + we change module, or we change symtab. */ + for (; (iter != end + && first_module_symbol == iter->first.symbol + && first_symbtab == symbol_symtab (iter->second.symbol)); + ++iter) + output_debug_symbol (uiout, kind, iter->second.symbol, + iter->second.block); + + return iter; +} + +/* Helper for mi_info_module_functions_or_variables. Display the results + from ITER up to END or until we find a symbol that is in a different + module than the first symbol we print. Update and return the new value + for ITER. */ +static module_symbol_search_iterator +output_module_symbols_in_single_module + (struct ui_out *uiout, module_symbol_search_iterator iter, + const module_symbol_search_iterator end, enum search_domain kind) +{ + gdb_assert (iter->first.symbol != nullptr); + gdb_assert (iter->second.symbol != nullptr); + + /* The symbol for the module in which the first result resides. */ + const symbol *first_module_symbol = iter->first.symbol; + + /* Create output formatting. */ + ui_out_emit_tuple module_tuple (uiout, nullptr); + uiout->field_string ("module", first_module_symbol->print_name ()); + ui_out_emit_list files_list (uiout, "files"); + + /* The results are sorted so that symbols within the same file are next + to each other in the list. Calling the output function once will + print all results within a single file. We keep calling the output + function until we change module. */ + while (iter != end && first_module_symbol == iter->first.symbol) + iter = output_module_symbols_in_single_module_and_file (uiout, iter, + end, kind); + return iter; +} + +/* Core of -symbol-info-module-functions and -symbol-info-module-variables. + KIND indicates what we are searching for, and ARGV and ARGC are the + command line options passed to the MI command. */ + +static void +mi_info_module_functions_or_variables (enum search_domain kind, + char **argv, int argc) +{ + const char *module_regexp = nullptr; + const char *regexp = nullptr; + const char *type_regexp = nullptr; + + /* Process the command line options. */ + + enum opt + { + MODULE_REGEXP_OPT, TYPE_REGEXP_OPT, NAME_REGEXP_OPT + }; + static const struct mi_opt opts[] = + { + {"-module", MODULE_REGEXP_OPT, 1}, + {"-type", TYPE_REGEXP_OPT, 1}, + {"-name", NAME_REGEXP_OPT, 1}, + { 0, 0, 0 } + }; + + int oind = 0; + char *oarg = nullptr; + + while (1) + { + const char *cmd_string + = ((kind == FUNCTIONS_DOMAIN) + ? "-symbol-info-module-functions" + : "-symbol-info-module-variables"); + int opt = mi_getopt (cmd_string, argc, argv, opts, &oind, &oarg); + if (opt < 0) + break; + switch ((enum opt) opt) + { + case MODULE_REGEXP_OPT: + module_regexp = oarg; + break; + case TYPE_REGEXP_OPT: + type_regexp = oarg; + break; + case NAME_REGEXP_OPT: + regexp = oarg; + break; + } + } + + std::vector module_symbols + = search_module_symbols (module_regexp, regexp, type_regexp, kind); + + struct ui_out *uiout = current_uiout; + ui_out_emit_list all_matching_symbols (uiout, "symbols"); + + /* The results in the module_symbols list are ordered so symbols in the + same module are next to each other. Repeatedly call the output + function to print sequences of symbols that are in the same module + until we have no symbols left to print. */ + module_symbol_search_iterator iter = module_symbols.begin (); + const module_symbol_search_iterator end = module_symbols.end (); + while (iter != end) + iter = output_module_symbols_in_single_module (uiout, iter, end, kind); +} + /* Implement -symbol-info-functions command. */ void @@ -224,6 +361,24 @@ mi_cmd_symbol_info_functions (const char *command, char **argv, int argc) mi_info_functions_or_variables (FUNCTIONS_DOMAIN, argv, argc); } +/* Implement -symbol-info-module-functions command. */ + +void +mi_cmd_symbol_info_module_functions (const char *command, char **argv, + int argc) +{ + mi_info_module_functions_or_variables (FUNCTIONS_DOMAIN, argv, argc); +} + +/* Implement -symbol-info-module-variables command. */ + +void +mi_cmd_symbol_info_module_variables (const char *command, char **argv, + int argc) +{ + mi_info_module_functions_or_variables (VARIABLES_DOMAIN, argv, argc); +} + /* Implement -symbol-inf-modules command. */ void diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index a4d2556c90a..9ed64d1d4c3 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-12-04 Andrew Burgess + + * gdb.mi/mi-fortran-modules.exp: Add additional tests for + -symbol-info-module-functions and -symbol-info-module-variables. + 2019-12-01 Andrew Burgess * gdb.fortran/array-slices.exp: Add test for dynamic strings. diff --git a/gdb/testsuite/gdb.mi/mi-fortran-modules.exp b/gdb/testsuite/gdb.mi/mi-fortran-modules.exp index 640bb12642d..12a81a68695 100644 --- a/gdb/testsuite/gdb.mi/mi-fortran-modules.exp +++ b/gdb/testsuite/gdb.mi/mi-fortran-modules.exp @@ -45,7 +45,30 @@ mi_gdb_test "103-symbol-info-modules --name moduse" \ "103\\^done,symbols=\{debug=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"41\",name=\"moduse\"\}\\\]\}\\\]\}" \ "-symbol-info-modules --name moduse" - +mi_gdb_test "104-symbol-info-module-functions" \ + [join \ + [list \ + "104\\^done,symbols=\\\[\{module=\"mod1\",files=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"21\",name=\"mod1::check_all\",type=\"void \\(void\\)\",description=\"void mod1::check_all\\(void\\);\"\}\\\]\}\\\]\},\{module=\"mod2\",files=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"30\",name=\"mod2::check_var_i\",type=\"void \\(void\\)\",description=\"void mod2::check_var_i\\(void\\);\"\}\\\]\}\\\]\},\{module=\"mod3\",files=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"21\",name=\"mod3::check_all\",type=\"void \\(void\\)\",description=\"void mod3::check_all\\(void\\);\"\},\{line=\"27\",name=\"mod3::check_mod2\",type=\"void \\(void\\)\",description=\"void mod3::check_mod2\\(void\\);\"\}\\\]\}\\\]\}," \ + "\{module=\"modmany\",files=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"35\",name=\"modmany::check_some\",type=\"void \\(void\\)\",description=\"void modmany::check_some\\(void\\);\"\}\\\]\}\\\]\},\{module=\"moduse\",files=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"44\",name=\"moduse::check_all\",type=\"void \\(void\\)\",description=\"void moduse::check_all\\(void\\);\"\},\{line=\"49\",name=\"moduse::check_var_x\",type=\"void \\(void\\)\",description=\"void moduse::check_var_x\\(void\\);\"\}\\\]\}\\\]\}\\\]" ] "" ] \ + "-symbol-info-module-functions" + +mi_gdb_test "105-symbol-info-module-functions --name _all" \ + "105\\^done,symbols=\\\[\{module=\"mod1\",files=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"21\",name=\"mod1::check_all\",type=\"void \\(void\\)\",description=\"void mod1::check_all\\(void\\);\"\}\\\]\}\\\]\},\{module=\"mod3\",files=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"21\",name=\"mod3::check_all\",type=\"void \\(void\\)\",description=\"void mod3::check_all\\(void\\);\"\}\\\]\}\\\]\},\{module=\"moduse\",files=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"44\",name=\"moduse::check_all\",type=\"void \\(void\\)\",description=\"void moduse::check_all\\(void\\);\"\}\\\]\}\\\]\}\\\]" \ + "-symbol-info-module-functions --name _all" + +mi_gdb_test "106-symbol-info-module-functions --module mod\[123\]" \ + "106\\^done,symbols=\\\[\{module=\"mod1\",files=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"21\",name=\"mod1::check_all\",type=\"void \\(void\\)\",description=\"void mod1::check_all\\(void\\);\"\}\\\]\}\\\]\},\{module=\"mod2\",files=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"30\",name=\"mod2::check_var_i\",type=\"void \\(void\\)\",description=\"void mod2::check_var_i\\(void\\);\"\}\\\]\}\\\]\},\{module=\"mod3\",files=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"21\",name=\"mod3::check_all\",type=\"void \\(void\\)\",description=\"void mod3::check_all\\(void\\);\"\},\{line=\"27\",name=\"mod3::check_mod2\",type=\"void \\(void\\)\",description=\"void mod3::check_mod2\\(void\\);\"\}\\\]\}\\\]\}\\\]" \ + "-symbol-info-module-functions --module mod\[123\]" + +set int4 [fortran_int4] + +mi_gdb_test "107-symbol-info-module-variables" \ + [join \ + [list \ + "107\\^done,symbols=\\\[\{module=\"mod1\",files=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"18\",name=\"mod1::var_const\",type=\"$int4\",description=\"$int4 mod1::var_const;\"\},\{line=\"17\",name=\"mod1::var_i\",type=\"$int4\",description=\"$int4 mod1::var_i;\"\}\\\]\}\\\]\},\{module=\"mod2\",files=\\\[\{filename=\"\[^\"\]+$srcfile2\",fullname=\"\[^\"\]+$srcfile2\",symbols=\\\[\{line=\"28\",name=\"mod2::var_i\",type=\"$int4\",description=\"$int4 mod2::var_i;\"\}\\\]\}\\\]\}," \ + "\{module=\"mod3\",files=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"18\",name=\"mod3::mod1\",type=\"$int4\",description=\"$int4 mod3::mod1;\"\},\{line=\"17\",name=\"mod3::mod2\",type=\"$int4\",description=\"$int4 mod3::mod2;\"\},\{line=\"19\",name=\"mod3::var_i\",type=\"$int4\",description=\"$int4 mod3::var_i;\"\}\\\]\}\\\]\},\{module=\"modmany\",files=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"33\",name=\"modmany::var_a\",type=\"$int4\",description=\"$int4 modmany::var_a;\"\}," \ + "\{line=\"33\",name=\"modmany::var_b\",type=\"$int4\",description=\"$int4 modmany::var_b;\"\},\{line=\"33\",name=\"modmany::var_c\",type=\"$int4\",description=\"$int4 modmany::var_c;\"\},\{line=\"33\",name=\"modmany::var_i\",type=\"$int4\",description=\"$int4 modmany::var_i;\"\}\\\]\}\\\]\},\{module=\"moduse\",files=\\\[\{filename=\"\[^\"\]+$srcfile\",fullname=\"\[^\"\]+$srcfile\",symbols=\\\[\{line=\"42\",name=\"moduse::var_x\",type=\"$int4\",description=\"$int4 moduse::var_x;\"\},\{line=\"42\",name=\"moduse::var_y\",type=\"$int4\",description=\"$int4 moduse::var_y;\"\}\\\]\}\\\]\}\\\]" ] "" ] \ + "-symbol-info-module-variables"