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:
Gregor Maier 2010-12-09 18:29:47 -08:00
parent 2f7fa3470b
commit 72454c230b
6 changed files with 188 additions and 103 deletions

View file

@ -2,6 +2,7 @@
// $Id: builtin-func.l 6015 2008-07-23 05:42:37Z vern $
#include <string.h>
#include <unistd.h>
#include "bif_arg.h"
#include "bif_parse.h"
@ -29,6 +30,7 @@ int check_c_mode(int t)
WS [ \t]+
ID [A-Za-z_][A-Za-z_0-9]*
ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+))
INT [[:digit:]]+
%option nodefault
@ -78,6 +80,11 @@ ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+))
"T" yylval.val = 1; return TOK_BOOL;
"F" yylval.val = 0; return TOK_BOOL;
{INT} {
yylval.str = copy_string(yytext);
return TOK_INT;
}
{ID} {
yylval.str = copy_string(yytext);
return TOK_ID;
@ -111,6 +118,7 @@ ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+))
}
%%
int yywrap()
{
yy_delete_buffer(YY_CURRENT_BUFFER);
@ -120,13 +128,21 @@ int yywrap()
extern int yyparse();
char* input_filename = 0;
FILE* fp_bro_init;
FILE* fp_func_def;
FILE* fp_func_h;
FILE* fp_func_init;
FILE* fp_netvar_h;
FILE* fp_netvar_def;
FILE* fp_netvar_init;
FILE* fp_bro_init = 0;
FILE* fp_func_def = 0;
FILE* fp_func_h = 0;
FILE* fp_func_init = 0;
FILE* fp_netvar_h = 0;
FILE* fp_netvar_def = 0;
FILE* fp_netvar_init = 0;
void remove_file(const char *surfix);
void err_exit(void);
FILE* open_output_file(const char* surfix);
void close_if_open(FILE **fpp);
void close_all_output_files(void);
FILE* open_output_file(const char* surfix)
{
@ -137,12 +153,13 @@ FILE* open_output_file(const char* surfix)
if ( (fp = fopen(fn, "w")) == NULL )
{
fprintf(stderr, "Error: cannot open file: %s\n", fn);
exit(1);
err_exit();
}
return fp;
}
int main(int argc, char* argv[])
{
for ( int i = 1; i < argc; i++ )
@ -156,6 +173,7 @@ int main(int argc, char* argv[])
if ( (fp_input = fopen(input_filename, "r")) == NULL )
{
fprintf(stderr, "Error: cannot open file: %s\n", input_filename);
/* no output files open. can simply exit */
exit(1);
}
@ -174,12 +192,48 @@ int main(int argc, char* argv[])
yyparse();
fclose(fp_input);
fclose(fp_bro_init);
fclose(fp_func_h);
fclose(fp_func_def);
fclose(fp_func_init);
fclose(fp_netvar_h);
fclose(fp_netvar_def);
fclose(fp_netvar_init);
close_all_output_files();
}
}
void close_if_open(FILE **fpp)
{
if (*fpp)
fclose(*fpp);
*fpp = NULL;
}
void close_all_output_files(void)
{
close_if_open(&fp_bro_init);
close_if_open(&fp_func_h);
close_if_open(&fp_func_def);
close_if_open(&fp_func_init);
close_if_open(&fp_netvar_h);
close_if_open(&fp_netvar_def);
close_if_open(&fp_netvar_init);
}
void remove_file(const char *surfix)
{
char fn[1024];
snprintf(fn, sizeof(fn), "%s.%s", input_filename, surfix);
unlink(fn);
}
void err_exit(void)
{
close_all_output_files();
/* clean up. remove all output files we've generated so far */
remove_file("bro");
remove_file("func_h");
remove_file("func_def");
remove_file("func_init");
remove_file("netvar_h");
remove_file("netvar_def");
remove_file("netvar_init");
exit(1);
}