diff --git a/regression/cbmc/filter_list_symbol_table/main.c b/regression/cbmc/filter_list_symbol_table/main.c new file mode 100644 index 00000000000..939ce6c1beb --- /dev/null +++ b/regression/cbmc/filter_list_symbol_table/main.c @@ -0,0 +1,7 @@ +int static_var = 15; + +int main() +{ + int b = 5 + static_var; + return 0; +} diff --git a/regression/cbmc/filter_list_symbol_table/test.desc b/regression/cbmc/filter_list_symbol_table/test.desc new file mode 100644 index 00000000000..d6cbfc8474b --- /dev/null +++ b/regression/cbmc/filter_list_symbol_table/test.desc @@ -0,0 +1,8 @@ +CORE +main.c +--list-symbol-table --filter-symbol-table static_lifetime,file_local +main::1::b signed int +return' signed int +static_var signed int +-- +main signed int () diff --git a/regression/cbmc/filter_list_symbols/main.c b/regression/cbmc/filter_list_symbols/main.c new file mode 100644 index 00000000000..939ce6c1beb --- /dev/null +++ b/regression/cbmc/filter_list_symbols/main.c @@ -0,0 +1,7 @@ +int static_var = 15; + +int main() +{ + int b = 5 + static_var; + return 0; +} diff --git a/regression/cbmc/filter_list_symbols/test.desc b/regression/cbmc/filter_list_symbols/test.desc new file mode 100644 index 00000000000..5ac17ec5c3c --- /dev/null +++ b/regression/cbmc/filter_list_symbols/test.desc @@ -0,0 +1,8 @@ +CORE +main.c +--list-symbols --filter-symbol-table static_lifetime +static_var signed int +-- +main signed int () +main::1::b signed int +return' signed int diff --git a/regression/cbmc/filter_show_symbol_table/main.c b/regression/cbmc/filter_show_symbol_table/main.c new file mode 100644 index 00000000000..939ce6c1beb --- /dev/null +++ b/regression/cbmc/filter_show_symbol_table/main.c @@ -0,0 +1,7 @@ +int static_var = 15; + +int main() +{ + int b = 5 + static_var; + return 0; +} diff --git a/regression/cbmc/filter_show_symbol_table/test.desc b/regression/cbmc/filter_show_symbol_table/test.desc new file mode 100644 index 00000000000..df2a0bd6d8c --- /dev/null +++ b/regression/cbmc/filter_show_symbol_table/test.desc @@ -0,0 +1,18 @@ +CORE +main.c +--show-symbol-table --filter-symbol-table static_lifetime +Symbol......: static_var +Pretty name.: static_var +Module......: main +Base name...: static_var +Mode........: C +Type........: signed int +Value.......: 15 +Flags.......: lvalue static_lifetime +Location....: file main.c line 1 +^EXIT=0$ +^SIGNAL=0$ +-- +Symbol......: main +Symbol......: main::1::b +Symbol......: return' diff --git a/regression/goto-instrument/filter_list_symbol_table/main.c b/regression/goto-instrument/filter_list_symbol_table/main.c new file mode 100644 index 00000000000..939ce6c1beb --- /dev/null +++ b/regression/goto-instrument/filter_list_symbol_table/main.c @@ -0,0 +1,7 @@ +int static_var = 15; + +int main() +{ + int b = 5 + static_var; + return 0; +} diff --git a/regression/goto-instrument/filter_list_symbol_table/test.desc b/regression/goto-instrument/filter_list_symbol_table/test.desc new file mode 100644 index 00000000000..6976d322695 --- /dev/null +++ b/regression/goto-instrument/filter_list_symbol_table/test.desc @@ -0,0 +1,8 @@ +CORE +main.c +--list-symbol-table --filter-symbol-table static_lifetime +static_var signed int +-- +main signed int () +main::1::b signed int +return' signed int diff --git a/regression/goto-instrument/filter_show_symbol_table/main.c b/regression/goto-instrument/filter_show_symbol_table/main.c new file mode 100644 index 00000000000..939ce6c1beb --- /dev/null +++ b/regression/goto-instrument/filter_show_symbol_table/main.c @@ -0,0 +1,7 @@ +int static_var = 15; + +int main() +{ + int b = 5 + static_var; + return 0; +} diff --git a/regression/goto-instrument/filter_show_symbol_table/test.desc b/regression/goto-instrument/filter_show_symbol_table/test.desc new file mode 100644 index 00000000000..df2a0bd6d8c --- /dev/null +++ b/regression/goto-instrument/filter_show_symbol_table/test.desc @@ -0,0 +1,18 @@ +CORE +main.c +--show-symbol-table --filter-symbol-table static_lifetime +Symbol......: static_var +Pretty name.: static_var +Module......: main +Base name...: static_var +Mode........: C +Type........: signed int +Value.......: 15 +Flags.......: lvalue static_lifetime +Location....: file main.c line 1 +^EXIT=0$ +^SIGNAL=0$ +-- +Symbol......: main +Symbol......: main::1::b +Symbol......: return' diff --git a/src/cbmc/cbmc_parse_options.cpp b/src/cbmc/cbmc_parse_options.cpp index f5074b6b543..31164f4ee18 100644 --- a/src/cbmc/cbmc_parse_options.cpp +++ b/src/cbmc/cbmc_parse_options.cpp @@ -588,10 +588,14 @@ int cbmc_parse_optionst::get_goto_program( { goto_model = initialize_goto_model(cmdline, ui_message_handler); - if(cmdline.isset("show-symbol-table")) + int commandline_check_return_value; + if(!check_commandline_for_show_symbol_flags( + commandline_check_return_value, + cmdline, + goto_model, + ui_message_handler.get_ui())) { - show_symbol_table(goto_model, ui_message_handler.get_ui()); - return CPROVER_EXIT_SUCCESS; + return commandline_check_return_value; } if(cbmc_parse_optionst::process_goto_program(goto_model, options, log)) @@ -931,7 +935,7 @@ void cbmc_parse_optionst::help() "\n" "Program representations:\n" " --show-parse-tree show parse tree\n" - " --show-symbol-table show loaded symbol table\n" + HELP_SHOW_SYMBOL_TABLE HELP_SHOW_GOTO_FUNCTIONS " --drop-unused-functions drop functions trivially unreachable from main function\n" // NOLINT(*) "\n" diff --git a/src/cbmc/cbmc_parse_options.h b/src/cbmc/cbmc_parse_options.h index 5c9cd1c4633..02748445fc4 100644 --- a/src/cbmc/cbmc_parse_options.h +++ b/src/cbmc/cbmc_parse_options.h @@ -56,7 +56,8 @@ class optionst; "(little-endian)(big-endian)" \ OPT_SHOW_GOTO_FUNCTIONS \ OPT_SHOW_PROPERTIES \ - "(show-symbol-table)(show-parse-tree)" \ + OPT_SHOW_SYMBOL_TABLE \ + "(show-parse-tree)" \ "(drop-unused-functions)" \ "(property):(stop-on-fail)(trace)" \ "(error-label):(verbosity):(no-library)" \ diff --git a/src/goto-instrument/goto_instrument_parse_options.cpp b/src/goto-instrument/goto_instrument_parse_options.cpp index 4582509df7d..ecba5821eda 100644 --- a/src/goto-instrument/goto_instrument_parse_options.cpp +++ b/src/goto-instrument/goto_instrument_parse_options.cpp @@ -462,10 +462,11 @@ int goto_instrument_parse_optionst::doit() return CPROVER_EXIT_SUCCESS; } - if(cmdline.isset("show-symbol-table")) + int commandline_check_return_value; + if(!check_commandline_for_show_symbol_flags( + commandline_check_return_value, cmdline, goto_model, get_ui())) { - ::show_symbol_table(goto_model, get_ui()); - return CPROVER_EXIT_SUCCESS; + return commandline_check_return_value; } if(cmdline.isset("show-reaching-definitions")) @@ -517,12 +518,6 @@ int goto_instrument_parse_optionst::doit() return CPROVER_EXIT_SUCCESS; } - if(cmdline.isset("list-symbols")) - { - show_symbol_table_brief(goto_model, get_ui()); - return CPROVER_EXIT_SUCCESS; - } - if(cmdline.isset("show-uninitialized")) { show_uninitialized(goto_model, std::cout); @@ -1527,8 +1522,7 @@ void goto_instrument_parse_optionst::help() "Diagnosis:\n" " --show-loops show the loops in the program\n" HELP_SHOW_PROPERTIES - " --show-symbol-table show loaded symbol table\n" - " --list-symbols list symbols with type information\n" + HELP_SHOW_SYMBOL_TABLE HELP_SHOW_GOTO_FUNCTIONS HELP_GOTO_PROGRAM_STATS " --drop-unused-functions drop functions trivially unreachable from main function\n" // NOLINT(*) diff --git a/src/goto-instrument/goto_instrument_parse_options.h b/src/goto-instrument/goto_instrument_parse_options.h index 706083df63e..843d42359bc 100644 --- a/src/goto-instrument/goto_instrument_parse_options.h +++ b/src/goto-instrument/goto_instrument_parse_options.h @@ -22,6 +22,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include +#include #include @@ -61,6 +62,7 @@ Author: Daniel Kroening, kroening@kroening.com "(function-enter):(function-exit):(branch):" \ OPT_SHOW_GOTO_FUNCTIONS \ OPT_SHOW_PROPERTIES \ + OPT_SHOW_SYMBOL_TABLE \ "(drop-unused-functions)" \ "(show-value-sets)" \ "(show-global-may-alias)" \ @@ -75,7 +77,7 @@ Author: Daniel Kroening, kroening@kroening.com "(print-internal-representation)" \ "(remove-function-pointers)" \ "(show-claims)(property):" \ - "(show-symbol-table)(show-points-to)(show-rw-set)" \ + "(show-points-to)(show-rw-set)" \ "(cav11)" \ OPT_TIMESTAMP \ "(show-natural-loops)(accelerate)(havoc-loops)" \ diff --git a/src/goto-programs/show_symbol_table.cpp b/src/goto-programs/show_symbol_table.cpp index 771bc88da00..5b65715a57d 100644 --- a/src/goto-programs/show_symbol_table.cpp +++ b/src/goto-programs/show_symbol_table.cpp @@ -16,15 +16,170 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include +#include +#include #include "goto_model.h" +symbol_table_filtert::symbol_table_filtert() + : filter_lvalue(false), + filter_static_lifetime(false), + filter_thread_local(false), + filter_file_local(false), + filter_type(false), + filter_extern(false), + filter_input(false), + filter_output(false), + filter_macro(false), + filter_parameter(false), + filter_auxilary(false), + filter_weak(false), + filter_property(false), + filter_state_var(false), + filter_exported(false), + filter_volatile(false), + default_pass(true) +{ +} + +bool symbol_table_filtert::set_filter_flag( + const std::string &flag) +{ + if(flag == "lvalue") + filter_lvalue = true; + else if(flag == "static_lifetime") + filter_static_lifetime = true; + else if(flag == "thread_local") + filter_thread_local = true; + else if(flag == "file_local") + filter_file_local = true; + else if(flag == "type") + filter_type = true; + else if(flag == "extern") + filter_extern = true; + else if(flag == "input") + filter_input = true; + else if(flag == "output") + filter_output = true; + else if(flag == "macro") + filter_macro = true; + else if(flag == "parameter") + filter_parameter = true; + else if(flag == "auxiliary") + filter_auxilary = true; + else if(flag == "weak") + filter_weak = true; + else if(flag == "property") + filter_property = true; + else if(flag == "state_var") + filter_state_var = true; + else if(flag == "exported") + filter_exported = true; + else if(flag == "volatile") + filter_volatile = true; + else + { + std::cout << "Don't recognize the following flag: " + flag + "\n\n" + << "Only the following flags are valid:\n" + << " lvalue, static_lifetime, thread_local, file_local,\n" + << " type, extern, input, output, macro, parameter,\n" + << " auxiliary, weak, property, state_var, exported, volatile\n"; + return true; + } + return false; +} + +bool symbol_table_filtert::is_selected(const symbolt &symbol) const +{ + return default_pass || + ((symbol.is_lvalue && filter_lvalue) || + (symbol.is_static_lifetime && filter_static_lifetime) || + (symbol.is_thread_local && filter_thread_local) || + (symbol.is_file_local && filter_file_local) || + (symbol.is_type && filter_type) || + (symbol.is_extern && filter_extern) || + (symbol.is_input && filter_input) || + (symbol.is_output && filter_output) || + (symbol.is_macro && filter_macro) || + (symbol.is_parameter && filter_parameter) || + (symbol.is_auxiliary && filter_auxilary) || + (symbol.is_weak && filter_weak) || + (symbol.is_property && filter_property) || + (symbol.is_state_var && filter_state_var) || + (symbol.is_exported && filter_exported) || + (symbol.is_volatile && filter_volatile)); +} + +bool symbol_table_filtert::setup(const std::string &flags) +{ + default_pass = false; + std::vector flags_splitted; + split_string(flags, ',', flags_splitted, true, true); + for(auto const &flag : flags_splitted) + { + if(set_filter_flag(flag)) + { + return true; + } + } + return false; +} + +bool check_commandline_for_show_symbol_flags( + int &return_value, + const cmdlinet &cmdline, + const goto_modelt &goto_model, + ui_message_handlert::uit ui) +{ + if(cmdline.isset("show-symbol-table")) + { + if(cmdline.isset("filter-symbol-table")) + { + symbol_table_filtert filter; + if(filter.setup(cmdline.get_value("filter-symbol-table"))) + { + return_value = CPROVER_EXIT_USAGE_ERROR; + return false; + } + + show_symbol_table(goto_model, filter, ui); + return_value = CPROVER_EXIT_SUCCESS; + return false; + } + show_symbol_table(goto_model, ui); + return_value = CPROVER_EXIT_SUCCESS; + return false; + } + if(cmdline.isset("list-symbols") || cmdline.isset("list-symbol-table")) + { + if(cmdline.isset("filter-symbol-table")) + { + symbol_table_filtert filter; + if(filter.setup(cmdline.get_value("filter-symbol-table"))) + { + return_value = CPROVER_EXIT_USAGE_ERROR; + return false; + } + + show_symbol_table_brief(goto_model, filter, ui); + return_value = CPROVER_EXIT_SUCCESS; + return false; + } + show_symbol_table_brief(goto_model, ui); + return_value = CPROVER_EXIT_SUCCESS; + return false; + } + return true; +} + void show_symbol_table_xml_ui() { } void show_symbol_table_brief_plain( const symbol_tablet &symbol_table, + const symbol_table_filtert &filter, std::ostream &out) { // we want to sort alphabetically @@ -57,12 +212,14 @@ void show_symbol_table_brief_plain( if(symbol.type.is_not_nil()) ptr->from_type(symbol.type, type_str, ns); - out << symbol.name << " " << type_str << '\n'; + if(filter.is_selected(symbol)) + out << symbol.name << " " << type_str << '\n'; } } void show_symbol_table_plain( const symbol_tablet &symbol_table, + const symbol_table_filtert &filter, std::ostream &out) { out << '\n' << "Symbols:" << '\n' << '\n'; @@ -103,6 +260,10 @@ void show_symbol_table_plain( if(symbol.value.is_not_nil()) ptr->from_expr(symbol.value, value_str, ns); + if(!filter.is_selected(symbol)) + { + continue; + } out << "Symbol......: " << symbol.name << '\n' << std::flush; out << "Pretty name.: " << symbol.pretty_name << '\n'; out << "Module......: " << symbol.module << '\n'; @@ -155,11 +316,20 @@ void show_symbol_table_plain( void show_symbol_table( const symbol_tablet &symbol_table, ui_message_handlert::uit ui) +{ + symbol_table_filtert filter; + show_symbol_table(symbol_table, filter, ui); +} + +void show_symbol_table( + const symbol_tablet &symbol_table, + const symbol_table_filtert &filter, + ui_message_handlert::uit ui) { switch(ui) { case ui_message_handlert::uit::PLAIN: - show_symbol_table_plain(symbol_table, std::cout); + show_symbol_table_plain(symbol_table, filter, std::cout); break; case ui_message_handlert::uit::XML_UI: @@ -178,14 +348,31 @@ void show_symbol_table( show_symbol_table(goto_model.symbol_table, ui); } +void show_symbol_table( + const goto_modelt &goto_model, + const symbol_table_filtert &filter, + ui_message_handlert::uit ui) +{ + show_symbol_table(goto_model.symbol_table, filter, ui); +} + +void show_symbol_table_brief( + const symbol_tablet &symbol_table, + ui_message_handlert::uit ui) +{ + symbol_table_filtert filter; + show_symbol_table_brief(symbol_table, filter, ui); +} + void show_symbol_table_brief( const symbol_tablet &symbol_table, + const symbol_table_filtert &filter, ui_message_handlert::uit ui) { switch(ui) { case ui_message_handlert::uit::PLAIN: - show_symbol_table_brief_plain(symbol_table, std::cout); + show_symbol_table_brief_plain(symbol_table, filter, std::cout); break; case ui_message_handlert::uit::XML_UI: @@ -197,6 +384,14 @@ void show_symbol_table_brief( } } +void show_symbol_table_brief( + const goto_modelt &goto_model, + const symbol_table_filtert &filter, + ui_message_handlert::uit ui) +{ + show_symbol_table_brief(goto_model.symbol_table, filter, ui); +} + void show_symbol_table_brief( const goto_modelt &goto_model, ui_message_handlert::uit ui) diff --git a/src/goto-programs/show_symbol_table.h b/src/goto-programs/show_symbol_table.h index 82e49128967..533c5b1ce83 100644 --- a/src/goto-programs/show_symbol_table.h +++ b/src/goto-programs/show_symbol_table.h @@ -16,21 +16,89 @@ Author: Daniel Kroening, kroening@kroening.com class symbol_tablet; class goto_modelt; +class symbolt; +class cmdlinet; + +// clang-format off +#define OPT_SHOW_SYMBOL_TABLE \ + "(show-symbol-table)" \ + "(list-symbols)(list-symbol-table)" \ + "(filter-symbol-table):" + +#define HELP_SHOW_SYMBOL_TABLE \ + " --show-symbol-table show loaded symbol table\n" \ + " --list-symbols keept for compatibility, use --list-symbol-table instead\n" \ + " --list-symbol-table list symbols with type information\n" \ + " --filter-symbol-table filter the symbol table for passed flags before printing\n" \ + " Allowed flags are: lvalue, static_lifetime, thread_local,\n" \ + " type, extern, intern, output, macro, parameter, auxilary,\n" \ + " You might pass a comma separatd list flag1,flag2,...\n" +// clang-format on + +class symbol_table_filtert +{ +public: + symbol_table_filtert(); + virtual bool is_selected(const symbolt &symbol) const; + virtual bool setup(const std::string &flags); + +protected: + virtual bool set_filter_flag(const std::string &flag); + +private: + bool filter_lvalue; + bool filter_static_lifetime; + bool filter_thread_local; + bool filter_file_local; + bool filter_type; + bool filter_extern; + bool filter_input; + bool filter_output; + bool filter_macro; + bool filter_parameter; + bool filter_auxilary; + bool filter_weak; + bool filter_property; + bool filter_state_var; + bool filter_exported; + bool filter_volatile; + bool default_pass; +}; + +bool check_commandline_for_show_symbol_flags( + int &return_value, + const cmdlinet &cmdline, + const goto_modelt &goto_model, + ui_message_handlert::uit ui); + +void show_symbol_table(const symbol_tablet &, ui_message_handlert::uit ui); void show_symbol_table( const symbol_tablet &, + const symbol_table_filtert &, ui_message_handlert::uit ui); void show_symbol_table_brief( const symbol_tablet &, ui_message_handlert::uit ui); +void show_symbol_table_brief( + const symbol_tablet &, + const symbol_table_filtert &, + ui_message_handlert::uit ui); + +void show_symbol_table(const goto_modelt &, ui_message_handlert::uit ui); + void show_symbol_table( const goto_modelt &, + const symbol_table_filtert &, ui_message_handlert::uit ui); void show_symbol_table_brief( const goto_modelt &, + const symbol_table_filtert &, ui_message_handlert::uit ui); +void show_symbol_table_brief(const goto_modelt &, ui_message_handlert::uit ui); + #endif // CPROVER_GOTO_PROGRAMS_SHOW_SYMBOL_TABLE_H