global_ids(): Include module names

Ad-hoc include module names in the global_ids() table. Table values will
have the type_name field set to "module" and their key in the table is
prefixed with "module " to avoid clashes with existing global identifiers
shadowing module names (Management::Node being an existing example).

Closes #3136
This commit is contained in:
Arne Welzel 2023-07-04 16:15:51 +02:00
parent f6f9dd2620
commit 4cde1c3c3f
8 changed files with 85 additions and 12 deletions

4
NEWS
View file

@ -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
---------------------

View file

@ -470,6 +470,18 @@ void add_type(ID* id, TypePtr t, std::unique_ptr<std::vector<AttrPtr>> attr)
id->SetAttrs(make_intrusive<Attributes>(std::move(*attr), tnew, false, false));
}
static std::set<std::string> all_module_names;
void add_module(const char* module_name)
{
all_module_names.emplace(module_name);
}
const std::set<std::string>& module_names()
{
return all_module_names;
}
static void transfer_arg_defaults(RecordType* args, RecordType* recv)
{
for ( int i = 0; i < args->NumFields(); ++i )

View file

@ -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<std::vector<AttrPtr>> attr);
extern void add_module(const char* module_name);
const std::set<std::string>& module_names();
extern void begin_func(IDPtr id, const char* module_name, FunctionFlavor flavor, bool is_redef,
FuncTypePtr t, std::unique_ptr<std::vector<AttrPtr>> attrs = nullptr);

View file

@ -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<std::string> 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);
}

View file

@ -90,8 +90,6 @@ const char* last_tok_filename = 0;
const char* last_last_tok_filename = 0;
char last_tok[128];
extern std::set<std::string> 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();

View file

@ -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<zeek::TableType>("id_table");
auto ids = zeek::make_intrusive<zeek::TableVal>(id_table);
const auto& globals = zeek::detail::global_scope()->Vars();
for ( const auto& global : globals )
{
const auto& id = global.second;
static auto script_id = zeek::id::find_type<zeek::RecordType>("script_id");
auto ids = zeek::make_intrusive<zeek::TableVal>(id_table);
for ( const auto& [_, id] : zeek::detail::global_scope()->Vars() )
{
auto rec = zeek::make_intrusive<zeek::RecordVal>(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<zeek::StringVal>("module");
for ( const auto& module_name : zeek::detail::module_names() )
{
auto rec = zeek::make_intrusive<zeek::RecordVal>(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::StringVal>(zeek::util::fmt("module %s", module_name.c_str()));
ids->Assign(std::move(id_name), std::move(rec));
}
return ids;
%}

View file

@ -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=<uninitialized>]
module GLOBAL, [type_name=module, exported=F, constant=F, enum_constant=F, option_value=F, redefinable=F, broker_backend=F, value=<uninitialized>]
MyModule, [type_name=string, exported=F, constant=F, enum_constant=F, option_value=F, redefinable=F, broker_backend=F, value=shadows module]

View file

@ -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;
}
}