diff --git a/src/Type.cc b/src/Type.cc index cb595a4428..99debc3c9c 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -1094,16 +1094,42 @@ EnumType::~EnumType() delete [] iter->first; } -bro_int_t EnumType::AddName(const string& module_name, const char* name, bool is_export) +// Note, we don't use Error() and SetError(( for EnumType because EnumTypes can +// be redefined, the location associated with it is ill-defined and might result +// in error messaging with confusing line numbers. +void EnumType::AddName(const string& module_name, const char* name, bool is_export) + { + /* implicit, auto-increment */ + if ( counter < 0) + { + error("cannot mix explicit enumerator assignment and implicit auto-increment"); + return; + } + AddNameInternal(module_name, name, counter, is_export); + counter++; + } + +void EnumType::AddName(const string& module_name, const char* name, bro_int_t val, bool is_export) { - return AddName(module_name, name, counter, is_export); + /* explicit value specified */ + error_t rv; + if ( counter > 0 ) + { + error("cannot mix explicit enumerator assignment and implicit auto-increment"); + return; + } + counter = -1; + AddNameInternal(module_name, name, val, is_export); } -bro_int_t EnumType::AddName(const string& module_name, const char* name, bro_int_t val, bool is_export) +void EnumType::AddNameInternal(const string& module_name, const char* name, bro_int_t val, bool is_export) { ID *id; if ( Lookup(val) ) - return -1; + { + error("enumerator value in enumerated type definition already exists"); + return; + } id = lookup_ID(name, module_name.c_str()); if ( ! id ) @@ -1113,12 +1139,13 @@ bro_int_t EnumType::AddName(const string& module_name, const char* name, bro_int id->SetEnumConst(); } else - return -1; + { + error("identifier or enumerator value in enumerated type definition already exists"); + return; + } string fullname = make_full_var_name(module_name.c_str(), name); names[copy_string(fullname.c_str())] = val; - counter = val + 1; - return val; } bro_int_t EnumType::Lookup(const string& module_name, const char* name) diff --git a/src/Type.h b/src/Type.h index 7865946a1d..dca122eadf 100644 --- a/src/Type.h +++ b/src/Type.h @@ -455,16 +455,12 @@ public: EnumType(); ~EnumType(); - // The value of this name is next counter value, which is returned. - // A return value of -1 means that the identifier or the counter values - // already existed (and thus could not be used). - bro_int_t AddName(const string& module_name, const char* name, bool is_export); + // The value of this name is next counter value. The counter is incremented + void AddName(const string& module_name, const char* name, bool is_export); - // The value of this name is set to val, which is return. The counter will - // be updated, so the next name (without val) will have val+1 - // A return value of -1 means that the identifier or val - // already existed (and thus could not be used). - bro_int_t AddName(const string& module_name, const char* name, bro_int_t val, bool is_export); + // The value of this name is set to val. The counter will + // be set to -1 to indicate that we are assigning explicit values + void AddName(const string& module_name, const char* name, bro_int_t val, bool is_export); // -1 indicates not found. bro_int_t Lookup(const string& module_name, const char* name); @@ -473,8 +469,16 @@ public: protected: DECLARE_SERIAL(EnumType) + void AddNameInternal(const string& module_name, const char* name, bro_int_t val, bool is_export); + typedef std::map< const char*, bro_int_t, ltstr > NameMap; NameMap names; + // counter is initialized to 0 and incremented on every implicit + // auto-increment name that gets added (thus its > 0 if auto-increment + // is used). + // If an explicit value is specified, the counter is set to -1 + // This way counter can be used to prevent mixing of auto-increment + // and explicit enumerator specification bro_int_t counter; }; diff --git a/src/parse.y b/src/parse.y index 4338f6d788..e9de07eb8f 100644 --- a/src/parse.y +++ b/src/parse.y @@ -594,8 +594,8 @@ enum_body_elem: 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"); + else + cur_enum_type->AddName(current_module, $1, $3->InternalUnsigned(), is_export); } | TOK_ID '=' '-' TOK_CONSTANT { @@ -609,8 +609,7 @@ enum_body_elem: { 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"); + cur_enum_type->AddName(current_module, $1, is_export); } ; @@ -716,9 +715,10 @@ type: $$ = 0; } - | TOK_ENUM '{' { parser_new_enum(); } enum_body '}' + | TOK_ENUM '{' { set_location(@1); parser_new_enum(); } enum_body '}' { set_location(@1, @5); + $4->UpdateLocationEndInfo(@5); $$ = $4; }