mirror of
https://github.com/zeek/zeek.git
synced 2025-10-13 20:18:20 +00:00
Add support for enum with explicit enumerator values.
* Adding support for enums with explicit enumerator values (see doc below) to bifcl and policy layer. * Bifcl: remove (partially written) output files on error and do a nice exit(1) instead of harsh abort() on parse errors. * CMakeText: if bifcl fails, remove output files (failsafe, in case bifcl fails to clean up after itself). Enum description ---------------- Enum's are supported in .bif and .bro scripts. An enum in a bif will become available in the event engine and the policy layer. Enums are "C-style". The first element in an enum will have a value of 0, the next value will be 1, etc. It is possible to assign an enumerator value to an element. If next element does not have an explicit value, its values will be the value of the last element + 1 Example:: type foo: enum { BAR_A, # value will be 0 BAR_B, # value will be 1 BAR_C = 10, # value will be 10 BAR_D, # value will be 11 }; Enumerator values can only by positive integer literals. The literals can be specified in (0x....), but not in octal (bro policy layer limitation). So, do not use 0123 as value in bifs! Each enumerator value can only be used once per enum (C allows to use the same value multiple times). This makes reverse mapping from value to name (e.g., in %s format strings) unambigious. This is enforced in by the policy script. Enums can be redef'ed, i.e., extended. Enumerator values will continue to increment. If there are multiple redefs in different policy scripts, then name <-> value mappings will obviously depend on the order in which scripts are loaded (which might not be obvious). Example:: redef enum foo += { BAR_E, # value will be 12 BAR_F = 5, # value will be 5 BAR_G, # value will be 6 };
This commit is contained in:
parent
2f7fa3470b
commit
72454c230b
6 changed files with 188 additions and 103 deletions
108
src/parse.y
108
src/parse.y
|
@ -51,7 +51,7 @@
|
|||
%type <expr> expr init anonymous_function
|
||||
%type <event_expr> event
|
||||
%type <stmt> stmt stmt_list func_body for_head
|
||||
%type <type> type opt_type refined_type enum_id_list
|
||||
%type <type> type opt_type refined_type enum_body
|
||||
%type <func_type> func_hdr func_params
|
||||
%type <type_l> type_list
|
||||
%type <type_decl> type_decl formal_args_decl
|
||||
|
@ -104,6 +104,29 @@ bool in_debug = false;
|
|||
bool resolving_global_ID = false;
|
||||
|
||||
ID* func_id = 0;
|
||||
EnumType *cur_enum_type = 0;
|
||||
|
||||
static void parser_new_enum (void)
|
||||
{
|
||||
/* starting a new enum definition. */
|
||||
assert(cur_enum_type == NULL);
|
||||
cur_enum_type = new EnumType();
|
||||
}
|
||||
static void parser_redef_enum (ID *id)
|
||||
{
|
||||
/* redef an enum. id points to the enum to be redefined.
|
||||
let cur_enum_type point to it */
|
||||
assert(cur_enum_type == NULL);
|
||||
if ( ! id->Type() )
|
||||
id->Error("unknown identifier");
|
||||
else
|
||||
{
|
||||
cur_enum_type = id->Type()->AsEnumType();
|
||||
if ( ! cur_enum_type )
|
||||
id->Error("not an enum");
|
||||
}
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%union {
|
||||
|
@ -546,27 +569,52 @@ single_pattern:
|
|||
{ $$ = $3; }
|
||||
;
|
||||
|
||||
enum_id_list:
|
||||
TOK_ID
|
||||
enum_body:
|
||||
enum_body_list opt_comma
|
||||
{
|
||||
set_location(@1);
|
||||
|
||||
EnumType* et = new EnumType(is_export);
|
||||
if ( et->AddName(current_module, $1) < 0 )
|
||||
error("identifier in enumerated type definition already exists");
|
||||
$$ = et;
|
||||
}
|
||||
|
||||
| enum_id_list ',' TOK_ID
|
||||
{
|
||||
set_location(@1, @3);
|
||||
|
||||
if ( $1->AsEnumType()->AddName(current_module, $3) < 1 )
|
||||
error("identifier in enumerated type definition already exists");
|
||||
$$ = $1;
|
||||
$$ = cur_enum_type;
|
||||
cur_enum_type = NULL;
|
||||
}
|
||||
;
|
||||
|
||||
enum_body_list:
|
||||
enum_body_elem /* No action */
|
||||
| enum_body_list ',' enum_body_elem /* no action */
|
||||
;
|
||||
|
||||
enum_body_elem:
|
||||
/* TODO: We could also define this as TOK_ID '=' expr, (or
|
||||
TOK_ID '=' = TOK_ID) so that we can return more descriptive
|
||||
error messages if someboy tries to use constant variables as
|
||||
enumerator.
|
||||
*/
|
||||
TOK_ID '=' TOK_CONSTANT
|
||||
{
|
||||
set_location(@1, @3);
|
||||
assert(cur_enum_type);
|
||||
if ($3->Type()->Tag() != TYPE_COUNT)
|
||||
error("enumerator is not a count constant");
|
||||
if ( cur_enum_type->AddName(current_module, $1, $3->InternalUnsigned(), is_export) < 0 )
|
||||
error("identifier or enumerator value in enumerated type definition already exists");
|
||||
}
|
||||
| TOK_ID '=' '-' TOK_CONSTANT
|
||||
{
|
||||
/* We only accept counts as enumerator, but we want to return a nice
|
||||
error message if users tries to use a negative integer (will also
|
||||
catch other cases, but that's fine)
|
||||
*/
|
||||
error("enumerator is not a count constant");
|
||||
}
|
||||
| TOK_ID
|
||||
{
|
||||
set_location(@1);
|
||||
assert(cur_enum_type);
|
||||
if ( cur_enum_type->AddName(current_module, $1, is_export) < 0 )
|
||||
error("identifier or enumerator value in enumerated type definition already exists");
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
type:
|
||||
TOK_BOOL {
|
||||
set_location(@1);
|
||||
|
@ -668,10 +716,10 @@ type:
|
|||
$$ = 0;
|
||||
}
|
||||
|
||||
| TOK_ENUM '{' enum_id_list opt_comma '}'
|
||||
| TOK_ENUM '{' { parser_new_enum(); } enum_body '}'
|
||||
{
|
||||
set_location(@1, @4);
|
||||
$$ = $3;
|
||||
set_location(@1, @5);
|
||||
$$ = $4;
|
||||
}
|
||||
|
||||
| TOK_LIST
|
||||
|
@ -801,21 +849,9 @@ decl:
|
|||
| TOK_REDEF global_id opt_type init_class opt_init opt_attr ';'
|
||||
{ add_global($2, $3, $4, $5, $6, VAR_REDEF); }
|
||||
|
||||
| TOK_REDEF TOK_ENUM global_id TOK_ADD_TO
|
||||
'{' enum_id_list opt_comma '}' ';'
|
||||
{
|
||||
if ( ! $3->Type() )
|
||||
$3->Error("unknown identifier");
|
||||
else
|
||||
{
|
||||
EnumType* add_to = $3->Type()->AsEnumType();
|
||||
if ( ! add_to )
|
||||
$3->Error("not an enum");
|
||||
else
|
||||
add_to->AddNamesFrom(current_module,
|
||||
$6->AsEnumType());
|
||||
}
|
||||
}
|
||||
| TOK_REDEF TOK_ENUM global_id TOK_ADD_TO
|
||||
'{' { parser_redef_enum($3); } enum_body '}' ';'
|
||||
{ /* no action */ }
|
||||
|
||||
| TOK_TYPE global_id ':' refined_type opt_attr ';'
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue