From bbe7c98ab39976523702b36f4588a8bba58808d0 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Tue, 22 Mar 2011 16:05:59 -0500 Subject: [PATCH] Major reformatting of auto-generated reST documentation. Introduces reST directives and roles in a "bro" domain that Sphinx will be taught to recognize. --- src/Attr.cc | 10 ++++-- src/BroDoc.cc | 10 ++++-- src/BroDocObj.cc | 14 ++++++--- src/BroDocObj.h | 15 +++++++++ src/Desc.cc | 6 ++++ src/Desc.h | 1 + src/ID.cc | 34 ++++++++++++++++----- src/ID.h | 2 +- src/Type.cc | 79 ++++++++++++++++++++++++++++++++---------------- src/Val.cc | 2 ++ src/parse.y | 4 ++- 11 files changed, 132 insertions(+), 45 deletions(-) diff --git a/src/Attr.cc b/src/Attr.cc index 31a01b3070..f7f7f0576a 100644 --- a/src/Attr.cc +++ b/src/Attr.cc @@ -51,12 +51,17 @@ void Attr::Describe(ODesc* d) const void Attr::DescribeReST(ODesc* d) const { - d->Add(".. bro:attr:: "); + d->Add(":bro:attr:`"); AddTag(d); + d->Add("`"); if ( expr ) { + d->SP(); d->Add("="); + d->SP(); + d->Add("``"); expr->Describe(d); + d-> Add("``"); } } @@ -176,7 +181,8 @@ void Attributes::DescribeReST(ODesc* d) const { loop_over_list(*attrs, i) { - d->NL(); + if ( i > 0 ) + d->Add(" "); (*attrs)[i]->DescribeReST(d); } } diff --git a/src/BroDoc.cc b/src/BroDoc.cc index 1de346987d..12b8cce284 100644 --- a/src/BroDoc.cc +++ b/src/BroDoc.cc @@ -99,14 +99,18 @@ void BroDoc::WriteDocFile() const WriteToDoc(":Author(s): "); WriteStringList("%s, ", "%s\n", authors); - WriteToDoc(":Namespaces: "); - WriteStringList("`%s`, ", "`%s`\n", modules); - WriteToDoc(":Imports: "); WriteStringList(":doc:`%s`, ", ":doc:`%s`\n", imports); WriteToDoc("\n"); + if ( ! modules.empty() ) + { + WriteSectionHeading("Namespaces", '-'); + WriteStringList(".. bro:namespace:: %s\n", modules); + WriteToDoc("\n"); + } + if ( ! notices.empty() ) WriteBroDocObjList(notices, "Notices", '-'); diff --git a/src/BroDocObj.cc b/src/BroDocObj.cc index c911817b30..326550e545 100644 --- a/src/BroDocObj.cc +++ b/src/BroDocObj.cc @@ -11,6 +11,7 @@ BroDocObj::BroDocObj(const ID* id, std::list*& reST, reST_doc_strings = reST; reST = 0; is_fake_id = is_fake; + use_role = 0; } BroDocObj::~BroDocObj() @@ -21,11 +22,12 @@ BroDocObj::~BroDocObj() void BroDocObj::WriteReST(FILE* file) const { + int indent_spaces = 3; ODesc desc; - desc.SetIndentSpaces(4); + desc.SetIndentSpaces(indent_spaces); desc.SetQuotes(1); - broID->DescribeReST(&desc); - fprintf(file, "%s\n", desc.Description()); + broID->DescribeReST(&desc, use_role); + fprintf(file, "%s", desc.Description()); if ( HasDocumentation() ) { @@ -33,7 +35,11 @@ void BroDocObj::WriteReST(FILE* file) const std::list::const_iterator it; for ( it = reST_doc_strings->begin(); it != reST_doc_strings->end(); ++it) - fprintf(file, " %s\n", it->c_str()); + { + for ( int i = 0; i < indent_spaces; ++i ) + fprintf(file, " "); + fprintf(file, "%s\n", it->c_str()); + } } fprintf(file, "\n"); diff --git a/src/BroDocObj.h b/src/BroDocObj.h index 3cbe72d7c9..e3fd30518b 100644 --- a/src/BroDocObj.h +++ b/src/BroDocObj.h @@ -50,10 +50,25 @@ public: bool HasDocumentation() const { return reST_doc_strings && reST_doc_strings->size() > 0; } + /** + * @return whether this object will use reST role (T) or directive (F) + * notation for the wrapped identifier. Roles are usually used + * for cross-referencing. + */ + bool UseRole() const { return use_role; } + + /** + * @param b whether this object will use reST role (T) or directive (F) + * notation for the wrapped identifier. Roles are usually used + * for cross-referencing. + */ + void SetRole(bool b) { use_role = b; } + protected: std::list* reST_doc_strings; const ID* broID; bool is_fake_id; /**< Whether the ID* is a dummy just for doc purposes */ + bool use_role; /**< Whether to use a reST role or directive for the ID */ private: }; diff --git a/src/Desc.cc b/src/Desc.cc index a70d94e188..57e67e6420 100644 --- a/src/Desc.cc +++ b/src/Desc.cc @@ -68,6 +68,12 @@ void ODesc::PopIndent() NL(); } +void ODesc::PopIndentNoNL() + { + if ( --indent_level < 0 ) + internal_error("ODesc::PopIndent underflow"); + } + void ODesc::Add(const char* s, int do_indent) { unsigned int n = strlen(s); diff --git a/src/Desc.h b/src/Desc.h index 2a40cfea11..1dc3b5434d 100644 --- a/src/Desc.h +++ b/src/Desc.h @@ -51,6 +51,7 @@ public: void PushIndent(); void PopIndent(); + void PopIndentNoNL(); int GetIndentLevel() const { return indent_level; } int IndentSpaces() const { return indent_with_spaces; } diff --git a/src/ID.cc b/src/ID.cc index 03403af86f..c4cf5a58c1 100644 --- a/src/ID.cc +++ b/src/ID.cc @@ -607,39 +607,57 @@ void ID::DescribeExtended(ODesc* d) const } } -void ID::DescribeReST(ODesc* d) const +void ID::DescribeReST(ODesc* d, bool is_role) const { - d->Add(".. bro:id:: "); - d->Add(name); + if ( is_role ) + { + if ( is_type ) + d->Add(":bro:type:`"); + else + d->Add(":bro:id:`"); + d->Add(name); + d->Add("`"); + } + else + { + if ( is_type ) + d->Add(".. bro:type:: "); + else + d->Add(".. bro:id:: "); + d->Add(name); + } d->PushIndent(); + d->NL(); if ( type ) { - d->Add(".. bro:type:: "); + d->Add(":Type: "); if ( ! is_type && type->GetTypeID() ) { - d->Add("`"); + d->Add(":bro:type:`"); d->Add(type->GetTypeID()); d->Add("`"); } else type->DescribeReST(d); + d->NL(); } if ( attrs ) { + d->Add(":Attributes: "); attrs->DescribeReST(d); + d->NL(); } if ( val && type && type->InternalType() != TYPE_INTERNAL_OTHER && type->InternalType() != TYPE_INTERNAL_VOID ) { - d->NL(); - d->Add(".. bro:val:: "); + d->Add(":Init: "); val->DescribeReST(d); + d->NL(); } - } #ifdef DEBUG diff --git a/src/ID.h b/src/ID.h index 7ebaf27918..90a0862a18 100644 --- a/src/ID.h +++ b/src/ID.h @@ -85,7 +85,7 @@ public: // Adds type and value to description. void DescribeExtended(ODesc* d) const; // Produces a description that's reST-ready - void DescribeReST(ODesc* d) const; + void DescribeReST(ODesc* d, bool is_role=false) const; bool Serialize(SerialInfo* info) const; static ID* Unserialize(UnserialInfo* info); diff --git a/src/Type.cc b/src/Type.cc index d74d02770c..ff5464843a 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -149,7 +149,9 @@ void BroType::Describe(ODesc* d) const void BroType::DescribeReST(ODesc* d) const { - Describe(d); + d->Add(":bro:type:`"); + d->Add(type_name(Tag())); + d->Add("`"); } void BroType::SetError() @@ -439,20 +441,22 @@ void IndexType::Describe(ODesc* d) const void IndexType::DescribeReST(ODesc* d) const { + d->Add(":bro:type:`"); if ( IsSet() ) d->Add("set"); else d->Add(type_name(Tag())); + d->Add("` "); d->Add("["); loop_over_list(*IndexTypes(), i) { if ( i > 0 ) - d->Add(","); + d->Add(", "); const BroType* t = (*IndexTypes())[i]; if ( t->GetTypeID() ) { - d->Add("`"); + d->Add(":bro:type:`"); d->Add(t->GetTypeID()); d->Add("`"); } @@ -466,7 +470,7 @@ void IndexType::DescribeReST(ODesc* d) const d->Add(" of "); if ( yield_type->GetTypeID() ) { - d->Add("`"); + d->Add(":bro:type:`"); d->Add(yield_type->GetTypeID()); d->Add("`"); } @@ -711,8 +715,10 @@ void FuncType::Describe(ODesc* d) const void FuncType::DescribeReST(ODesc* d) const { + d->Add(":bro:type:`"); d->Add(is_event ? "event" : "function"); - d->Add("("); + d->Add("`"); + d->Add(" ("); args->DescribeFieldsReST(d, true); d->Add(")"); if ( yield ) @@ -720,7 +726,7 @@ void FuncType::DescribeReST(ODesc* d) const d->AddSP(" :"); if ( yield->GetTypeID() ) { - d->Add("`"); + d->Add(":bro:type:`"); d->Add(yield->GetTypeID()); d->Add("`"); } @@ -997,7 +1003,8 @@ void RecordType::Describe(ODesc* d) const void RecordType::DescribeReST(ODesc* d) const { - d->Add("record"); + d->Add(":bro:type:`record`"); + d->NL(); DescribeFieldsReST(d, false); } @@ -1048,36 +1055,46 @@ void RecordType::DescribeFieldsReST(ODesc* d, bool func_args) const for ( int i = 0; i < num_fields; ++i ) { const TypeDecl* td = FieldDecl(i); - if ( ! func_args ) - d->Add(":bro:field: "); + + if ( i > 0 ) + if ( func_args ) + d->Add(", "); + else + { + d->NL(); + d->NL(); + } d->Add(td->id); d->Add(": "); - d->Add(":bro:type: "); if ( td->type->GetTypeID() ) { - d->Add("`"); + d->Add(":bro:type:`"); d->Add(td->type->GetTypeID()); d->Add("`"); } else td->type->DescribeReST(d); + if ( td->attrs ) + { + d->SP(); + td->attrs->DescribeReST(d); + } + if ( ! func_args ) + { if ( td->comment ) { d->PushIndent(); - d->Add(".. bro:comment:: "); d->Add(td->comment); - d->PopIndent(); + d->PopIndentNoNL(); } - - if ( i + 1 != num_fields ) - if ( func_args ) - d->Add(", "); - else - d->NL(); + } } + + if ( ! func_args ) + d->PopIndentNoNL(); } IMPLEMENT_SERIAL(RecordType, SER_RECORD_TYPE) @@ -1362,24 +1379,34 @@ void CommentedEnumType::DescribeReST(ODesc* d) const for ( NameMap::const_iterator it = names.begin(); it != names.end(); ++it ) rev[it->second] = it->first; + d->Add(":bro:type:`"); d->Add(type_name(Tag())); + d->Add("`"); d->PushIndent(); + d->NL(); - for ( RevNameMap::const_iterator it = rev.begin(); it != rev.end(); ) + for ( RevNameMap::const_iterator it = rev.begin(); it != rev.end(); ++it ) { + if ( it != rev.begin() ) + { + d->NL(); + d->NL(); + } + d->Add(".. bro:enum:: "); - d->Add(it->second); + d->AddSP(it->second); + d->Add(GetTypeID()); + CommentMap::const_iterator cmnt_it = comments.find(it->second); if ( cmnt_it != comments.end() ) { d->PushIndent(); - d->Add(".. bro:comment:: "); - d->Add(cmnt_it->second); - d->PopIndent(); - } - if ( ++it != rev.end() ) d->NL(); + d->Add(cmnt_it->second); + d->PopIndentNoNL(); + } } + d->PopIndentNoNL(); } IMPLEMENT_SERIAL(EnumType, SER_ENUM_TYPE); diff --git a/src/Val.cc b/src/Val.cc index f4c471b8dc..05ca0adc65 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -576,7 +576,9 @@ void Val::Describe(ODesc* d) const void Val::DescribeReST(ODesc* d) const { + d->Add("``"); ValDescribeReST(d); + d->Add("``"); } void Val::ValDescribe(ODesc* d) const diff --git a/src/parse.y b/src/parse.y index 5e4966fd5e..3c537e185e 100644 --- a/src/parse.y +++ b/src/parse.y @@ -153,12 +153,13 @@ static void add_enum_comment (const char* comment) cur_enum_type_doc->AddComment(current_module, cur_enum_elem_id, comment); } -static ID* create_dummy_id (const char* name, const BroType* type) +static ID* create_dummy_id (const char* name, BroType* type) { // normally, install_ID() figures out the right IDScope // but it doesn't matter for the dummy ID so use SCOPE_GLOBAL ID* fake_id = new ID(copy_string(name), SCOPE_GLOBAL, is_export); fake_id->SetType(cur_enum_type_doc); + type->SetTypeID(copy_string(name)); fake_id->MakeType(); return fake_id; } @@ -995,6 +996,7 @@ decl: ID* fake_id = create_dummy_id($3->Name(), cur_enum_type_doc); cur_enum_type_doc = 0; BroDocObj* o = new BroDocObj(fake_id, reST_doc_comments, true); + o->SetRole(true); if ( streq(fake_id->Name(), "Notice" ) ) current_reST_doc->AddNotice(o); else