diff --git a/NEWS b/NEWS index f40752aa08..18b6ce6b1c 100644 --- a/NEWS +++ b/NEWS @@ -35,6 +35,10 @@ New Functionality normalize JSON object key names. This can be useful if the keys in a JSON object are not valid Zeek identifiers or reserved keywords. +- Module names are now included in ``global_ids()``. Their key in the returned + table is prefixed with "module " and their value will have the ``type_name`` + field set to "module". + Changed Functionality --------------------- diff --git a/src/Var.cc b/src/Var.cc index f125540cac..5a327625a9 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -470,6 +470,18 @@ void add_type(ID* id, TypePtr t, std::unique_ptr> attr) id->SetAttrs(make_intrusive(std::move(*attr), tnew, false, false)); } +static std::set all_module_names; + +void add_module(const char* module_name) + { + all_module_names.emplace(module_name); + } + +const std::set& module_names() + { + return all_module_names; + } + static void transfer_arg_defaults(RecordType* args, RecordType* recv) { for ( int i = 0; i < args->NumFields(); ++i ) diff --git a/src/Var.h b/src/Var.h index 29cd2ce604..08f38a98d3 100644 --- a/src/Var.h +++ b/src/Var.h @@ -42,6 +42,10 @@ extern ExprPtr add_and_assign_local(IDPtr id, ExprPtr init, ValPtr val); extern void add_type(ID* id, TypePtr t, std::unique_ptr> attr); +extern void add_module(const char* module_name); + +const std::set& module_names(); + extern void begin_func(IDPtr id, const char* module_name, FunctionFlavor flavor, bool is_redef, FuncTypePtr t, std::unique_ptr> attrs = nullptr); diff --git a/src/parse.y b/src/parse.y index b9a80e50a9..624c7f0e64 100644 --- a/src/parse.y +++ b/src/parse.y @@ -157,8 +157,6 @@ static int func_hdr_cond_epoch = 0; EnumType* cur_enum_type = nullptr; static ID* cur_decl_type_id = nullptr; -std::set module_names; - static void parse_new_enum(void) { // Starting a new enum definition. @@ -1357,7 +1355,7 @@ decl: TOK_MODULE TOK_ID ';' { current_module = $2; - module_names.insert($2); + zeek::detail::add_module($2); zeekygen_mgr->ModuleUsage(::filename, current_module); } diff --git a/src/scan.l b/src/scan.l index f1a8ecd201..7d8d0063fe 100644 --- a/src/scan.l +++ b/src/scan.l @@ -90,8 +90,6 @@ const char* last_tok_filename = 0; const char* last_last_tok_filename = 0; char last_tok[128]; -extern std::set module_names; - #define YY_USER_ACTION strncpy(last_tok, yytext, sizeof(last_tok) - 1); \ last_last_tok_filename = last_tok_filename; \ last_tok_filename = ::filename; @@ -882,7 +880,7 @@ void do_atifdef(const char* id) // If the ID didn't exist, look to see if this is a module name instead. bool found = (i != nullptr); if ( ! found ) - found = (module_names.count(id) != 0); + found = (zeek::detail::module_names().count(id) != 0); if ( ! found ) begin_ignoring(); @@ -897,7 +895,7 @@ void do_atifndef(const char *id) // If the ID didn't exist, look to see if this is a module name instead. bool found = (i != nullptr); if ( ! found ) - found = (module_names.count(id) != 0); + found = (zeek::detail::module_names().count(id) != 0); if ( found ) begin_ignoring(); diff --git a/src/zeek.bif b/src/zeek.bif index b3b57eb6b3..2956c4bd46 100644 --- a/src/zeek.bif +++ b/src/zeek.bif @@ -2106,17 +2106,20 @@ function val_footprint%(v: any%): count ## exported, a constant, an enum constant, redefinable, and its value (if it ## has one). ## +## Module names are included in the returned table as well. The ``type_name`` +## field is set to "module" and their names are prefixed with "module " to avoid +## clashing with global identifiers. Note that there is no module type in Zeek. +## ## Returns: A table that maps identifier names to information about them. function global_ids%(%): id_table %{ static auto id_table = zeek::id::find_type("id_table"); - auto ids = zeek::make_intrusive(id_table); - const auto& globals = zeek::detail::global_scope()->Vars(); + static auto script_id = zeek::id::find_type("script_id"); - for ( const auto& global : globals ) + auto ids = zeek::make_intrusive(id_table); + + for ( const auto& [_, id] : zeek::detail::global_scope()->Vars() ) { - const auto& id = global.second; - static auto script_id = zeek::id::find_type("script_id"); auto rec = zeek::make_intrusive(script_id); rec->Assign(0, type_name(id->GetType()->Tag())); rec->Assign(1, id->IsExport()); @@ -2133,6 +2136,23 @@ function global_ids%(%): id_table ids->Assign(std::move(id_name), std::move(rec)); } + auto module_str = zeek::make_intrusive("module"); + + for ( const auto& module_name : zeek::detail::module_names() ) + { + auto rec = zeek::make_intrusive(script_id); + rec->Assign(0, module_str); // type_name + rec->Assign(1, false); // exported + rec->Assign(2, false); // constant + rec->Assign(3, false); // enum_constant + rec->Assign(4, false); // option_value + rec->Assign(5, false); // redefinable + rec->Assign(6, false); // broker_backend + + auto id_name = zeek::make_intrusive(zeek::util::fmt("module %s", module_name.c_str())); + ids->Assign(std::move(id_name), std::move(rec)); + } + return ids; %} diff --git a/testing/btest/Baseline/bifs.global_ids-modules/out b/testing/btest/Baseline/bifs.global_ids-modules/out new file mode 100644 index 0000000000..fb4b600db0 --- /dev/null +++ b/testing/btest/Baseline/bifs.global_ids-modules/out @@ -0,0 +1,4 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +module MyModule, [type_name=module, exported=F, constant=F, enum_constant=F, option_value=F, redefinable=F, broker_backend=F, value=] +module GLOBAL, [type_name=module, exported=F, constant=F, enum_constant=F, option_value=F, redefinable=F, broker_backend=F, value=] +MyModule, [type_name=string, exported=F, constant=F, enum_constant=F, option_value=F, redefinable=F, broker_backend=F, value=shadows module] diff --git a/testing/btest/bifs/global_ids-modules.zeek b/testing/btest/bifs/global_ids-modules.zeek new file mode 100644 index 0000000000..9d32597fd0 --- /dev/null +++ b/testing/btest/bifs/global_ids-modules.zeek @@ -0,0 +1,33 @@ +# @TEST-DOC: global_ids() also includes information about modules +# +# @TEST-EXEC: unset ZEEK_ALLOW_INIT_ERRORS; zeek -b %INPUT 2>&1 >out +# @TEST-EXEC: btest-diff out + +module MyModule; + +module GLOBAL; + +# This shadows the module +global MyModule = "shadows module"; + +event zeek_init() + { + local a = global_ids(); + + # Assert based testing. + assert "module GLOBAL" in a; + assert a["module GLOBAL"]$type_name == "module"; + + assert "module MyModule" in a; + assert a["module MyModule"]$type_name == "module"; + + assert "MyModule" in a; + assert a["MyModule"]$type_name == "string"; + + # And a classic baseline test for now, too. + for ( [k], v in a ) + { + if ( k in set("module GLOBAL", "module MyModule", "MyModule") ) + print k, v; + } + }