diff --git a/src/ID.cc b/src/ID.cc index e6392bc964..ad7f345667 100644 --- a/src/ID.cc +++ b/src/ID.cc @@ -463,20 +463,26 @@ void ID::DescribeReST(ODesc* d, bool roles_only) const } if ( val && type && - type->Tag() != TYPE_FUNC && - type->InternalType() != TYPE_INTERNAL_VOID && - // Values within Version module are likely to include a - // constantly-changing version number and be a frequent - // source of error/desynchronization, so don't include them. - ModuleName() != "Version" ) + type->Tag() != TYPE_FUNC && + type->InternalType() != TYPE_INTERNAL_VOID && + // Values within Version module are likely to include a + // constantly-changing version number and be a frequent + // source of error/desynchronization, so don't include them. + ModuleName() != "Version" ) { d->Add(":Default:"); + auto ii = zeekygen_mgr->GetIdentifierInfo(Name()); + auto redefs = ii->GetRedefs(); + auto iv = val; + + if ( ! redefs.empty() && ii->InitialVal() ) + iv = ii->InitialVal(); if ( type->InternalType() == TYPE_INTERNAL_OTHER ) { switch ( type->Tag() ) { case TYPE_TABLE: - if ( val->AsTable()->Length() == 0 ) + if ( iv->AsTable()->Length() == 0 ) { d->Add(" ``{}``"); d->NL(); @@ -486,11 +492,12 @@ void ID::DescribeReST(ODesc* d, bool roles_only) const default: d->NL(); - d->NL(); + d->PushIndent(); d->Add("::"); d->NL(); d->PushIndent(); - val->DescribeReST(d); + iv->DescribeReST(d); + d->PopIndent(); d->PopIndent(); } } @@ -498,9 +505,45 @@ void ID::DescribeReST(ODesc* d, bool roles_only) const else { d->SP(); - val->DescribeReST(d); + iv->DescribeReST(d); d->NL(); } + + for ( auto& ir : redefs ) + { + if ( ! ir->init_expr ) + continue; + + if ( ir->ic == INIT_NONE ) + continue; + + std::string redef_str; + ODesc expr_desc; + ir->init_expr->Describe(&expr_desc); + redef_str = expr_desc.Description(); + redef_str = strreplace(redef_str, "\n", " "); + + d->Add(":Redefinition: "); + d->Add(fmt("from :doc:`/scripts/%s`", ir->from_script.data())); + d->NL(); + d->PushIndent(); + + if ( ir->ic == INIT_FULL ) + d->Add("``=``"); + else if ( ir->ic == INIT_EXTRA ) + d->Add("``+=``"); + else if ( ir->ic == INIT_REMOVE ) + d->Add("``-=``"); + else + assert(false); + + d->Add("::"); + d->NL(); + d->PushIndent(); + d->Add(redef_str.data()); + d->PopIndent(); + d->PopIndent(); + } } } diff --git a/src/parse.y b/src/parse.y index 63bd49c042..820e958a98 100644 --- a/src/parse.y +++ b/src/parse.y @@ -1096,7 +1096,7 @@ decl: | TOK_REDEF global_id opt_type init_class opt_init opt_attr ';' { add_global($2, $3, $4, $5, $6, VAR_REDEF); - zeekygen_mgr->Redef($2, ::filename); + zeekygen_mgr->Redef($2, ::filename, $4, $5); } | TOK_REDEF TOK_ENUM global_id TOK_ADD_TO '{' diff --git a/src/zeekygen/IdentifierInfo.cc b/src/zeekygen/IdentifierInfo.cc index 5c494799b4..5db21ed956 100644 --- a/src/zeekygen/IdentifierInfo.cc +++ b/src/zeekygen/IdentifierInfo.cc @@ -5,28 +5,26 @@ #include "Desc.h" #include "Val.h" +#include "Expr.h" using namespace std; using namespace zeekygen; IdentifierInfo::IdentifierInfo(ID* arg_id, ScriptInfo* script) : Info(), - comments(), id(arg_id), initial_val_desc(), redefs(), fields(), + comments(), id(arg_id), initial_val(), redefs(), fields(), last_field_seen(), declaring_script(script) { Ref(id); - if ( id->ID_Val() ) - { - ODesc d; - id->ID_Val()->Describe(&d); - initial_val_desc = d.Description(); - } + if ( id->ID_Val() && (id->IsOption() || id->IsRedefinable()) ) + initial_val = id->ID_Val()->Clone(); } IdentifierInfo::~IdentifierInfo() { Unref(id); + Unref(initial_val); for ( redef_list::const_iterator it = redefs.begin(); it != redefs.end(); ++it ) @@ -37,20 +35,10 @@ IdentifierInfo::~IdentifierInfo() delete it->second; } -void IdentifierInfo::AddRedef(const string& script, - const vector& comments) +void IdentifierInfo::AddRedef(const string& script, init_class ic, + Expr* init_expr, const vector& comments) { - Redefinition* redef = new Redefinition(); - redef->from_script = script; - - if ( id->ID_Val() ) - { - ODesc d; - id->ID_Val()->Describe(&d); - redef->new_val_desc = d.Description(); - } - - redef->comments = comments; + Redefinition* redef = new Redefinition(script, ic, init_expr, comments); redefs.push_back(redef); } @@ -146,3 +134,48 @@ time_t IdentifierInfo::DoGetModificationTime() const // contributed to the ID declaration/redefinitions, but this is easier... return declaring_script->GetModificationTime(); } + +IdentifierInfo::Redefinition::Redefinition( + std::string arg_script, + init_class arg_ic, + Expr* arg_expr, + std::vector arg_comments) + : from_script(std::move(arg_script)), + ic(arg_ic), + init_expr(arg_expr ? arg_expr->Ref() : nullptr), + comments(std::move(arg_comments)) + { + } + +IdentifierInfo::Redefinition::Redefinition(const IdentifierInfo::Redefinition& other) + { + from_script = other.from_script; + ic = other.ic; + init_expr = other.init_expr; + comments = other.comments; + + if ( init_expr ) + init_expr->Ref(); + } + +IdentifierInfo::Redefinition& +IdentifierInfo::Redefinition::operator=(const IdentifierInfo::Redefinition& other) + { + if ( &other == this ) + return *this; + + from_script = other.from_script; + ic = other.ic; + init_expr = other.init_expr; + comments = other.comments; + + if ( init_expr ) + init_expr->Ref(); + + return *this; + } + +IdentifierInfo::Redefinition::~Redefinition() + { + Unref(init_expr); + } diff --git a/src/zeekygen/IdentifierInfo.h b/src/zeekygen/IdentifierInfo.h index 868dd3781b..eaf4fff490 100644 --- a/src/zeekygen/IdentifierInfo.h +++ b/src/zeekygen/IdentifierInfo.h @@ -38,6 +38,12 @@ public: */ ~IdentifierInfo() override; + /** + * Returns the initial value of the identifier. + */ + Val* InitialVal() const + { return initial_val; } + /** * Add a comment associated with the identifier. If the identifier is a * record type and it's in the middle of parsing fields, the comment is @@ -59,9 +65,12 @@ public: /** * Register a redefinition of the identifier. * @param from_script The script in which the redef occurred. + * @param ic The initialization class used (e.g. =, +=, -=) + * @param init_expr The initialzation expression used. * @param comments Comments associated with the redef statement. */ - void AddRedef(const std::string& from_script, + void AddRedef(const std::string& from_script, init_class ic, + Expr* init_expr, const std::vector& comments); /** @@ -117,8 +126,19 @@ public: */ struct Redefinition { std::string from_script; /**< Name of script doing the redef. */ - std::string new_val_desc; /**< Description of new value bound to ID. */ + init_class ic; + Expr* init_expr; std::vector comments; /**< Zeekygen comments on redef. */ + + Redefinition(std::string arg_script, init_class arg_ic, + Expr* arg_expr, + std::vector arg_comments); + + Redefinition(const Redefinition& other); + + Redefinition& operator=(const Redefinition& other); + + ~Redefinition(); }; /** @@ -129,6 +149,13 @@ public: */ std::list GetRedefs(const std::string& from_script) const; + /** + * Get a list of information about redefinitions of the identifier. + * @return A list of redefs that occurred for the identifier. + */ + const std::list& GetRedefs() const + { return redefs; } + private: time_t DoGetModificationTime() const override; @@ -152,7 +179,7 @@ private: std::vector comments; ID* id; - std::string initial_val_desc; + Val* initial_val; redef_list redefs; record_field_map fields; RecordField* last_field_seen; diff --git a/src/zeekygen/Manager.cc b/src/zeekygen/Manager.cc index 52fdd64613..57cc19d531 100644 --- a/src/zeekygen/Manager.cc +++ b/src/zeekygen/Manager.cc @@ -352,7 +352,8 @@ void Manager::RecordField(const ID* id, const TypeDecl* field, field->id, id->Name(), script.c_str()); } -void Manager::Redef(const ID* id, const string& path) +void Manager::Redef(const ID* id, const string& path, + init_class ic, Expr* init_expr) { if ( disabled ) return; @@ -380,7 +381,7 @@ void Manager::Redef(const ID* id, const string& path) return; } - id_info->AddRedef(from_script, comment_buffer); + id_info->AddRedef(from_script, ic, init_expr, comment_buffer); script_info->AddRedef(id_info); comment_buffer.clear(); last_identifier_seen = id_info; diff --git a/src/zeekygen/Manager.h b/src/zeekygen/Manager.h index 36860522ea..99c6b353cc 100644 --- a/src/zeekygen/Manager.h +++ b/src/zeekygen/Manager.h @@ -136,8 +136,11 @@ public: * Register a redefinition of a particular identifier. * @param id The identifier being redef'd. * @param path Absolute path to a Bro script doing the redef. + * @param ic The initialization class that was used (e.g. =, +=, -=). + * @param init_expr The intiialization expression that was used. */ - void Redef(const ID* id, const std::string& path); + void Redef(const ID* id, const std::string& path, + init_class ic = INIT_NONE, Expr* init_expr = nullptr); /** * Register Zeekygen script summary content. diff --git a/testing/btest/Baseline/doc.zeekygen.vectors/autogen-reST-vectors.rst b/testing/btest/Baseline/doc.zeekygen.vectors/autogen-reST-vectors.rst index 48b7204b60..e0a8ea9727 100644 --- a/testing/btest/Baseline/doc.zeekygen.vectors/autogen-reST-vectors.rst +++ b/testing/btest/Baseline/doc.zeekygen.vectors/autogen-reST-vectors.rst @@ -3,9 +3,10 @@ :Type: :zeek:type:`vector` of :zeek:type:`string` :Default: - :: + :: + + [] - [] Yield type is documented/cross-referenced for primitize types. @@ -14,9 +15,10 @@ :Type: :zeek:type:`vector` of :zeek:type:`TestRecord` :Default: - :: + :: + + [] - [] Yield type is documented/cross-referenced for composite types. @@ -25,9 +27,10 @@ :Type: :zeek:type:`vector` of :zeek:type:`vector` of :zeek:type:`TestRecord` :Default: - :: + :: + + [] - [] Just showing an even fancier yield type.