mirror of
https://github.com/zeek/zeek.git
synced 2025-10-04 15:48:19 +00:00
Initial skeleton of new Broxygen infrastructure.
Doesn't generate any docs, but it's hooked in to all places needed to gather the necessary stuff w/ significantly less coupling than before. The gathering now always occurs unconditionally to make documentation available at runtime and a command line switch (-X) only toggles whether to output docs to disk (reST format). Should also improve the treatment of type name aliasing which wasn't a big problem in practice before, but I think it's more correct now: there's now a distinct BroType for each alias, but extensible types (record/enum) will automatically update the types for aliases on redef. Other misc refactoring of note: - Removed a redundant/unused way of declaring event types. - Changed type serialization format/process to preserve type name information and remove compatibility code (since broccoli will have be updated anyway).
This commit is contained in:
parent
eeaf3e9baf
commit
5a857a6dfc
18 changed files with 393 additions and 838 deletions
|
@ -556,6 +556,7 @@ static void WritePluginBifItems(FILE* f, const plugin::Plugin* p,
|
||||||
|
|
||||||
static void WriteAnalyzerTagDefn(FILE* f, EnumType* e, const string& module)
|
static void WriteAnalyzerTagDefn(FILE* f, EnumType* e, const string& module)
|
||||||
{
|
{
|
||||||
|
/* TODO
|
||||||
string tag_id= module + "::Tag";
|
string tag_id= module + "::Tag";
|
||||||
e = new CommentedEnumType(e);
|
e = new CommentedEnumType(e);
|
||||||
e->SetTypeID(copy_string(tag_id.c_str()));
|
e->SetTypeID(copy_string(tag_id.c_str()));
|
||||||
|
@ -570,6 +571,7 @@ static void WriteAnalyzerTagDefn(FILE* f, EnumType* e, const string& module)
|
||||||
BroDocObj bdo(dummy_id, r, true);
|
BroDocObj bdo(dummy_id, r, true);
|
||||||
|
|
||||||
bdo.WriteReST(f);
|
bdo.WriteReST(f);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ComponentsMatch(const plugin::Plugin* p, plugin::component::Type t,
|
static bool ComponentsMatch(const plugin::Plugin* p, plugin::component::Type t,
|
||||||
|
|
|
@ -78,4 +78,6 @@ private:
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern Brofiler brofiler;
|
||||||
|
|
||||||
#endif /* BROFILER_H_ */
|
#endif /* BROFILER_H_ */
|
||||||
|
|
|
@ -370,6 +370,8 @@ set(bro_SRCS
|
||||||
plugin/Plugin.cc
|
plugin/Plugin.cc
|
||||||
plugin/Macros.h
|
plugin/Macros.h
|
||||||
|
|
||||||
|
broxygen/Manager.cc
|
||||||
|
|
||||||
nb_dns.c
|
nb_dns.c
|
||||||
digest.h
|
digest.h
|
||||||
)
|
)
|
||||||
|
|
|
@ -5111,6 +5111,7 @@ BroType* ListExpr::InitType() const
|
||||||
types->append(td);
|
types->append(td);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return new RecordType(types);
|
return new RecordType(types);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -619,6 +619,7 @@ void ID::DescribeExtended(ODesc* d) const
|
||||||
|
|
||||||
void ID::DescribeReSTShort(ODesc* d) const
|
void ID::DescribeReSTShort(ODesc* d) const
|
||||||
{
|
{
|
||||||
|
/* TODO
|
||||||
if ( is_type )
|
if ( is_type )
|
||||||
d->Add(":bro:type:`");
|
d->Add(":bro:type:`");
|
||||||
else
|
else
|
||||||
|
@ -668,6 +669,7 @@ void ID::DescribeReSTShort(ODesc* d) const
|
||||||
d->SP();
|
d->SP();
|
||||||
attrs->DescribeReST(d);
|
attrs->DescribeReST(d);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void ID::DescribeReST(ODesc* d, bool is_role) const
|
void ID::DescribeReST(ODesc* d, bool is_role) const
|
||||||
|
@ -697,10 +699,10 @@ void ID::DescribeReST(ODesc* d, bool is_role) const
|
||||||
{
|
{
|
||||||
d->Add(":Type: ");
|
d->Add(":Type: ");
|
||||||
|
|
||||||
if ( ! is_type && type->GetTypeID() )
|
if ( ! is_type && ! type->GetName().empty() )
|
||||||
{
|
{
|
||||||
d->Add(":bro:type:`");
|
d->Add(":bro:type:`");
|
||||||
d->Add(type->GetTypeID());
|
d->Add(type->GetName());
|
||||||
d->Add("`");
|
d->Add("`");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -125,7 +125,7 @@ protected:
|
||||||
|
|
||||||
// This will be increased whenever there is an incompatible change
|
// This will be increased whenever there is an incompatible change
|
||||||
// in the data format.
|
// in the data format.
|
||||||
static const uint32 DATA_FORMAT_VERSION = 23;
|
static const uint32 DATA_FORMAT_VERSION = 24;
|
||||||
|
|
||||||
ChunkedIO* io;
|
ChunkedIO* io;
|
||||||
|
|
||||||
|
|
260
src/Type.cc
260
src/Type.cc
|
@ -8,13 +8,12 @@
|
||||||
#include "Scope.h"
|
#include "Scope.h"
|
||||||
#include "Serializer.h"
|
#include "Serializer.h"
|
||||||
#include "Reporter.h"
|
#include "Reporter.h"
|
||||||
|
#include "broxygen/Manager.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
extern int generate_documentation;
|
|
||||||
|
|
||||||
// Note: This function must be thread-safe.
|
// Note: This function must be thread-safe.
|
||||||
const char* type_name(TypeTag t)
|
const char* type_name(TypeTag t)
|
||||||
{
|
{
|
||||||
|
@ -47,7 +46,6 @@ BroType::BroType(TypeTag t, bool arg_base_type)
|
||||||
tag = t;
|
tag = t;
|
||||||
is_network_order = 0;
|
is_network_order = 0;
|
||||||
base_type = arg_base_type;
|
base_type = arg_base_type;
|
||||||
type_id = 0;
|
|
||||||
|
|
||||||
switch ( tag ) {
|
switch ( tag ) {
|
||||||
case TYPE_VOID:
|
case TYPE_VOID:
|
||||||
|
@ -110,10 +108,26 @@ BroType::BroType(TypeTag t, bool arg_base_type)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BroType::~BroType()
|
BroType* BroType::Clone() const
|
||||||
{
|
{
|
||||||
if ( type_id )
|
SerializationFormat* form = new BinarySerializationFormat();
|
||||||
delete [] type_id;
|
form->StartWrite();
|
||||||
|
CloneSerializer ss(form);
|
||||||
|
SerialInfo sinfo(&ss);
|
||||||
|
sinfo.cache = false;
|
||||||
|
|
||||||
|
this->Serialize(&sinfo);
|
||||||
|
char* data;
|
||||||
|
uint32 len = form->EndWrite(&data);
|
||||||
|
form->StartRead(data, len);
|
||||||
|
|
||||||
|
UnserialInfo uinfo(&ss);
|
||||||
|
uinfo.cache = false;
|
||||||
|
BroType* rval = this->Unserialize(&uinfo);
|
||||||
|
|
||||||
|
delete [] data;
|
||||||
|
|
||||||
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int BroType::MatchesIndex(ListExpr*& index) const
|
int BroType::MatchesIndex(ListExpr*& index) const
|
||||||
|
@ -222,9 +236,21 @@ BroType* BroType::Unserialize(UnserialInfo* info, TypeTag want)
|
||||||
if ( ! t )
|
if ( ! t )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// For base types, we return our current instance
|
if ( ! t->name.empty() )
|
||||||
// if not in "documentation mode".
|
{
|
||||||
if ( t->base_type && ! generate_documentation )
|
// Avoid creating a new type if it's known by name.
|
||||||
|
// Also avoids loss of base type name alias (from condition below).
|
||||||
|
ID* id = global_scope()->Lookup(t->name.c_str());
|
||||||
|
BroType* t2 = id ? id->AsType() : 0;
|
||||||
|
|
||||||
|
if ( t2 )
|
||||||
|
{
|
||||||
|
Unref(t);
|
||||||
|
return t2->Ref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( t->base_type )
|
||||||
{
|
{
|
||||||
BroType* t2 = ::base_type(TypeTag(t->tag));
|
BroType* t2 = ::base_type(TypeTag(t->tag));
|
||||||
Unref(t);
|
Unref(t);
|
||||||
|
@ -247,21 +273,10 @@ bool BroType::DoSerialize(SerialInfo* info) const
|
||||||
if ( ! (SERIALIZE(char(tag)) && SERIALIZE(char(internal_tag))) )
|
if ( ! (SERIALIZE(char(tag)) && SERIALIZE(char(internal_tag))) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ( ! (SERIALIZE(is_network_order) && SERIALIZE(base_type) &&
|
if ( ! (SERIALIZE(is_network_order) && SERIALIZE(base_type)) )
|
||||||
// Serialize the former "bool is_global_attributes_type" for
|
|
||||||
// backwards compatibility.
|
|
||||||
SERIALIZE(false)) )
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Likewise, serialize the former optional "RecordType* attributes_type"
|
SERIALIZE_STR(name.c_str(), name.size());
|
||||||
// for backwards compatibility.
|
|
||||||
void* null = NULL;
|
|
||||||
SERIALIZE(null);
|
|
||||||
|
|
||||||
if ( generate_documentation )
|
|
||||||
{
|
|
||||||
SERIALIZE_OPTIONAL_STR(type_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
info->s->WriteCloseTag("Type");
|
info->s->WriteCloseTag("Type");
|
||||||
|
|
||||||
|
@ -279,24 +294,15 @@ bool BroType::DoUnserialize(UnserialInfo* info)
|
||||||
tag = (TypeTag) c1;
|
tag = (TypeTag) c1;
|
||||||
internal_tag = (InternalTypeTag) c2;
|
internal_tag = (InternalTypeTag) c2;
|
||||||
|
|
||||||
bool not_used;
|
if ( ! (UNSERIALIZE(&is_network_order) && UNSERIALIZE(&base_type)) )
|
||||||
|
|
||||||
if ( ! (UNSERIALIZE(&is_network_order) && UNSERIALIZE(&base_type)
|
|
||||||
// Unerialize the former "bool is_global_attributes_type" for
|
|
||||||
// backwards compatibility.
|
|
||||||
&& UNSERIALIZE(¬_used)) )
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
BroType* not_used_either;
|
const char* n;
|
||||||
|
if ( ! UNSERIALIZE_STR(&n, 0) )
|
||||||
|
return false;
|
||||||
|
|
||||||
// Likewise, unserialize the former optional "RecordType*
|
name = n;
|
||||||
// attributes_type" for backwards compatibility.
|
delete [] n;
|
||||||
UNSERIALIZE_OPTIONAL(not_used_either, BroType::Unserialize(info, TYPE_RECORD));
|
|
||||||
|
|
||||||
if ( generate_documentation )
|
|
||||||
{
|
|
||||||
UNSERIALIZE_OPTIONAL_STR(type_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -470,10 +476,10 @@ void IndexType::DescribeReST(ODesc* d) const
|
||||||
|
|
||||||
const BroType* t = (*IndexTypes())[i];
|
const BroType* t = (*IndexTypes())[i];
|
||||||
|
|
||||||
if ( t->GetTypeID() )
|
if ( ! t->GetName().empty() )
|
||||||
{
|
{
|
||||||
d->Add(":bro:type:`");
|
d->Add(":bro:type:`");
|
||||||
d->Add(t->GetTypeID());
|
d->Add(t->GetName());
|
||||||
d->Add("`");
|
d->Add("`");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -486,10 +492,10 @@ void IndexType::DescribeReST(ODesc* d) const
|
||||||
{
|
{
|
||||||
d->Add(" of ");
|
d->Add(" of ");
|
||||||
|
|
||||||
if ( yield_type->GetTypeID() )
|
if ( ! yield_type->GetName().empty() )
|
||||||
{
|
{
|
||||||
d->Add(":bro:type:`");
|
d->Add(":bro:type:`");
|
||||||
d->Add(yield_type->GetTypeID());
|
d->Add(yield_type->GetName());
|
||||||
d->Add("`");
|
d->Add("`");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -781,10 +787,10 @@ void FuncType::DescribeReST(ODesc* d) const
|
||||||
{
|
{
|
||||||
d->AddSP(" :");
|
d->AddSP(" :");
|
||||||
|
|
||||||
if ( yield->GetTypeID() )
|
if ( ! yield->GetName().empty() )
|
||||||
{
|
{
|
||||||
d->Add(":bro:type:`");
|
d->Add(":bro:type:`");
|
||||||
d->Add(yield->GetTypeID());
|
d->Add(yield->GetName());
|
||||||
d->Add("`");
|
d->Add("`");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -873,6 +879,17 @@ TypeDecl::TypeDecl(BroType* t, const char* i, attr_list* arg_attrs, bool in_reco
|
||||||
id = i;
|
id = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypeDecl::TypeDecl(const TypeDecl& other)
|
||||||
|
{
|
||||||
|
type = other.type->Ref();
|
||||||
|
attrs = other.attrs;
|
||||||
|
|
||||||
|
if ( attrs )
|
||||||
|
::Ref(attrs);
|
||||||
|
|
||||||
|
id = copy_string(other.id);
|
||||||
|
}
|
||||||
|
|
||||||
TypeDecl::~TypeDecl()
|
TypeDecl::~TypeDecl()
|
||||||
{
|
{
|
||||||
Unref(type);
|
Unref(type);
|
||||||
|
@ -914,10 +931,10 @@ void TypeDecl::DescribeReST(ODesc* d) const
|
||||||
d->Add(id);
|
d->Add(id);
|
||||||
d->Add(": ");
|
d->Add(": ");
|
||||||
|
|
||||||
if ( type->GetTypeID() )
|
if ( ! type->GetName().empty() )
|
||||||
{
|
{
|
||||||
d->Add(":bro:type:`");
|
d->Add(":bro:type:`");
|
||||||
d->Add(type->GetTypeID());
|
d->Add(type->GetName());
|
||||||
d->Add("`");
|
d->Add("`");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -930,37 +947,6 @@ void TypeDecl::DescribeReST(ODesc* d) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CommentedTypeDecl::CommentedTypeDecl(BroType* t, const char* i,
|
|
||||||
attr_list* attrs, bool in_record, std::list<std::string>* cmnt_list)
|
|
||||||
: TypeDecl(t, i, attrs, in_record)
|
|
||||||
{
|
|
||||||
comments = cmnt_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
CommentedTypeDecl::~CommentedTypeDecl()
|
|
||||||
{
|
|
||||||
if ( comments ) delete comments;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CommentedTypeDecl::DescribeReST(ODesc* d) const
|
|
||||||
{
|
|
||||||
TypeDecl::DescribeReST(d);
|
|
||||||
|
|
||||||
if ( comments )
|
|
||||||
{
|
|
||||||
d->PushIndent();
|
|
||||||
std::list<std::string>::const_iterator i;
|
|
||||||
|
|
||||||
for ( i = comments->begin(); i != comments->end(); ++i)
|
|
||||||
{
|
|
||||||
if ( i != comments->begin() ) d->NL();
|
|
||||||
d->Add(i->c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
d->PopIndentNoNL();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RecordType::RecordType(type_decl_list* arg_types) : BroType(TYPE_RECORD)
|
RecordType::RecordType(type_decl_list* arg_types) : BroType(TYPE_RECORD)
|
||||||
{
|
{
|
||||||
types = arg_types;
|
types = arg_types;
|
||||||
|
@ -1328,38 +1314,12 @@ bool OpaqueType::DoUnserialize(UnserialInfo* info)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
EnumType::EnumType(const string& arg_name)
|
|
||||||
: BroType(TYPE_ENUM)
|
|
||||||
{
|
|
||||||
name = arg_name;
|
|
||||||
counter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EnumType::EnumType(EnumType* e)
|
|
||||||
: BroType(TYPE_ENUM)
|
|
||||||
{
|
|
||||||
name = e->name;
|
|
||||||
counter = e->counter;
|
|
||||||
|
|
||||||
for ( NameMap::iterator it = e->names.begin(); it != e->names.end(); ++it )
|
|
||||||
names[copy_string(it->first)] = it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
EnumType::~EnumType()
|
EnumType::~EnumType()
|
||||||
{
|
{
|
||||||
for ( NameMap::iterator iter = names.begin(); iter != names.end(); ++iter )
|
for ( NameMap::iterator iter = names.begin(); iter != names.end(); ++iter )
|
||||||
delete [] iter->first;
|
delete [] iter->first;
|
||||||
}
|
}
|
||||||
|
|
||||||
CommentedEnumType::~CommentedEnumType()
|
|
||||||
{
|
|
||||||
for ( CommentMap::iterator iter = comments.begin(); iter != comments.end(); ++iter )
|
|
||||||
{
|
|
||||||
delete [] iter->first;
|
|
||||||
delete iter->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note, we use reporter->Error() here (not Error()) to include the current script
|
// Note, we use reporter->Error() here (not Error()) to include the current script
|
||||||
// location in the error message, rather than the one where the type was
|
// location in the error message, rather than the one where the type was
|
||||||
// originally defined.
|
// originally defined.
|
||||||
|
@ -1372,7 +1332,7 @@ void EnumType::AddName(const string& module_name, const char* name, bool is_expo
|
||||||
SetError();
|
SetError();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AddNameInternal(module_name, name, counter, is_export);
|
CheckAndAddName(module_name, name, counter, is_export);
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1386,32 +1346,12 @@ void EnumType::AddName(const string& module_name, const char* name, bro_int_t va
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
counter = -1;
|
counter = -1;
|
||||||
AddNameInternal(module_name, name, val, is_export);
|
CheckAndAddName(module_name, name, val, is_export);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommentedEnumType::AddComment(const string& module_name, const char* name,
|
void EnumType::CheckAndAddName(const string& module_name, const char* name,
|
||||||
std::list<std::string>* new_comments)
|
bro_int_t val, bool is_export)
|
||||||
{
|
{
|
||||||
if ( ! new_comments )
|
|
||||||
return;
|
|
||||||
|
|
||||||
string fullname = make_full_var_name(module_name.c_str(), name);
|
|
||||||
|
|
||||||
CommentMap::iterator it = comments.find(fullname.c_str());
|
|
||||||
|
|
||||||
if ( it == comments.end() )
|
|
||||||
comments[copy_string(fullname.c_str())] = new_comments;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
list<string>* prev_comments = comments[fullname.c_str()];
|
|
||||||
prev_comments->splice(prev_comments->end(), *new_comments);
|
|
||||||
delete new_comments;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnumType::AddNameInternal(const string& module_name, const char* name, bro_int_t val, bool is_export)
|
|
||||||
{
|
|
||||||
ID *id;
|
|
||||||
if ( Lookup(val) )
|
if ( Lookup(val) )
|
||||||
{
|
{
|
||||||
reporter->Error("enumerator value in enumerated type definition already exists");
|
reporter->Error("enumerator value in enumerated type definition already exists");
|
||||||
|
@ -1419,12 +1359,14 @@ void EnumType::AddNameInternal(const string& module_name, const char* name, bro_
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
id = lookup_ID(name, module_name.c_str());
|
ID* id = lookup_ID(name, module_name.c_str());
|
||||||
|
|
||||||
if ( ! id )
|
if ( ! id )
|
||||||
{
|
{
|
||||||
id = install_ID(name, module_name.c_str(), true, is_export);
|
id = install_ID(name, module_name.c_str(), true, is_export);
|
||||||
id->SetType(this->Ref());
|
id->SetType(this->Ref());
|
||||||
id->SetEnumConst();
|
id->SetEnumConst();
|
||||||
|
broxygen_mgr->Identifier(id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1433,11 +1375,19 @@ void EnumType::AddNameInternal(const string& module_name, const char* name, bro_
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string fullname = make_full_var_name(module_name.c_str(), name);
|
AddNameInternal(module_name, name, val, is_export);
|
||||||
names[copy_string(fullname.c_str())] = val;
|
|
||||||
|
set<BroType*> types = type_aliases[GetName()];
|
||||||
|
set<BroType*>::const_iterator it;
|
||||||
|
|
||||||
|
for ( it = types.begin(); it != types.end(); ++it )
|
||||||
|
if ( *it != this )
|
||||||
|
(*it)->AsEnumType()->AddNameInternal(module_name, name, val,
|
||||||
|
is_export);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommentedEnumType::AddNameInternal(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)
|
||||||
{
|
{
|
||||||
string fullname = make_full_var_name(module_name.c_str(), name);
|
string fullname = make_full_var_name(module_name.c_str(), name);
|
||||||
names[copy_string(fullname.c_str())] = val;
|
names[copy_string(fullname.c_str())] = val;
|
||||||
|
@ -1466,54 +1416,8 @@ const char* EnumType::Lookup(bro_int_t value)
|
||||||
|
|
||||||
void EnumType::DescribeReST(ODesc* d) const
|
void EnumType::DescribeReST(ODesc* d) const
|
||||||
{
|
{
|
||||||
d->Add(":bro:type:`");
|
// TODO: this probably goes away
|
||||||
d->Add(name.c_str());
|
d->Add(":bro:type:`enum`");
|
||||||
d->Add("`");
|
|
||||||
}
|
|
||||||
|
|
||||||
void CommentedEnumType::DescribeReST(ODesc* d) const
|
|
||||||
{
|
|
||||||
// create temporary, reverse name map so that enums can be documented
|
|
||||||
// in ascending order of their actual integral value instead of by name
|
|
||||||
typedef std::map< bro_int_t, const char* > RevNameMap;
|
|
||||||
RevNameMap rev;
|
|
||||||
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(); ++it )
|
|
||||||
{
|
|
||||||
if ( it != rev.begin() )
|
|
||||||
{
|
|
||||||
d->NL();
|
|
||||||
d->NL();
|
|
||||||
}
|
|
||||||
|
|
||||||
d->Add(".. bro:enum:: ");
|
|
||||||
d->AddSP(it->second);
|
|
||||||
d->Add(GetTypeID());
|
|
||||||
|
|
||||||
CommentMap::const_iterator cmnt_it = comments.find(it->second);
|
|
||||||
if ( cmnt_it != comments.end() )
|
|
||||||
{
|
|
||||||
d->PushIndent();
|
|
||||||
d->NL();
|
|
||||||
std::list<std::string>::const_iterator i;
|
|
||||||
const std::list<std::string>* cmnt_list = cmnt_it->second;
|
|
||||||
for ( i = cmnt_list->begin(); i != cmnt_list->end(); ++i)
|
|
||||||
{
|
|
||||||
if ( i != cmnt_list->begin() ) d->NL();
|
|
||||||
d->Add(i->c_str());
|
|
||||||
}
|
|
||||||
d->PopIndentNoNL();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
d->PopIndentNoNL();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IMPLEMENT_SERIAL(EnumType, SER_ENUM_TYPE);
|
IMPLEMENT_SERIAL(EnumType, SER_ENUM_TYPE);
|
||||||
|
|
68
src/Type.h
68
src/Type.h
|
@ -4,7 +4,7 @@
|
||||||
#define type_h
|
#define type_h
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <list>
|
#include <set>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "Obj.h"
|
#include "Obj.h"
|
||||||
|
@ -73,7 +73,9 @@ const int MATCHES_INDEX_VECTOR = 2;
|
||||||
class BroType : public BroObj {
|
class BroType : public BroObj {
|
||||||
public:
|
public:
|
||||||
BroType(TypeTag tag, bool base_type = false);
|
BroType(TypeTag tag, bool base_type = false);
|
||||||
~BroType();
|
~BroType() { }
|
||||||
|
|
||||||
|
BroType* Clone() const;
|
||||||
|
|
||||||
TypeTag Tag() const { return tag; }
|
TypeTag Tag() const { return tag; }
|
||||||
InternalTypeTag InternalType() const { return internal_tag; }
|
InternalTypeTag InternalType() const { return internal_tag; }
|
||||||
|
@ -232,11 +234,11 @@ public:
|
||||||
bool Serialize(SerialInfo* info) const;
|
bool Serialize(SerialInfo* info) const;
|
||||||
static BroType* Unserialize(UnserialInfo* info, TypeTag want = TYPE_ANY);
|
static BroType* Unserialize(UnserialInfo* info, TypeTag want = TYPE_ANY);
|
||||||
|
|
||||||
void SetTypeID(const char* id) { type_id = id; }
|
void SetName(const string& arg_name) { name = arg_name; }
|
||||||
const char* GetTypeID() const { return type_id; }
|
string GetName() const { return name; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BroType() { type_id = 0; }
|
BroType() { }
|
||||||
|
|
||||||
void SetError();
|
void SetError();
|
||||||
|
|
||||||
|
@ -247,10 +249,7 @@ private:
|
||||||
InternalTypeTag internal_tag;
|
InternalTypeTag internal_tag;
|
||||||
bool is_network_order;
|
bool is_network_order;
|
||||||
bool base_type;
|
bool base_type;
|
||||||
|
string name;
|
||||||
// This type_id field is only used by the documentation framework to
|
|
||||||
// track the names of declared types.
|
|
||||||
const char* type_id;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TypeList : public BroType {
|
class TypeList : public BroType {
|
||||||
|
@ -408,6 +407,7 @@ protected:
|
||||||
class TypeDecl {
|
class TypeDecl {
|
||||||
public:
|
public:
|
||||||
TypeDecl(BroType* t, const char* i, attr_list* attrs = 0, bool in_record = false);
|
TypeDecl(BroType* t, const char* i, attr_list* attrs = 0, bool in_record = false);
|
||||||
|
TypeDecl(const TypeDecl& other);
|
||||||
virtual ~TypeDecl();
|
virtual ~TypeDecl();
|
||||||
|
|
||||||
const Attr* FindAttr(attr_tag a) const
|
const Attr* FindAttr(attr_tag a) const
|
||||||
|
@ -423,17 +423,6 @@ public:
|
||||||
const char* id;
|
const char* id;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CommentedTypeDecl : public TypeDecl {
|
|
||||||
public:
|
|
||||||
CommentedTypeDecl(BroType* t, const char* i, attr_list* attrs = 0,
|
|
||||||
bool in_record = false, std::list<std::string>* cmnt_list = 0);
|
|
||||||
virtual ~CommentedTypeDecl();
|
|
||||||
|
|
||||||
void DescribeReST(ODesc* d) const;
|
|
||||||
|
|
||||||
std::list<std::string>* comments;
|
|
||||||
};
|
|
||||||
|
|
||||||
class RecordType : public BroType {
|
class RecordType : public BroType {
|
||||||
public:
|
public:
|
||||||
RecordType(type_decl_list* types);
|
RecordType(type_decl_list* types);
|
||||||
|
@ -522,8 +511,7 @@ protected:
|
||||||
|
|
||||||
class EnumType : public BroType {
|
class EnumType : public BroType {
|
||||||
public:
|
public:
|
||||||
EnumType(const string& arg_name);
|
EnumType() : BroType(TYPE_ENUM) { counter = 0; }
|
||||||
EnumType(EnumType* e);
|
|
||||||
~EnumType();
|
~EnumType();
|
||||||
|
|
||||||
// The value of this name is next internal counter value, starting
|
// The value of this name is next internal counter value, starting
|
||||||
|
@ -539,17 +527,17 @@ public:
|
||||||
bro_int_t Lookup(const string& module_name, const char* name);
|
bro_int_t Lookup(const string& module_name, const char* name);
|
||||||
const char* Lookup(bro_int_t value); // Returns 0 if not found
|
const char* Lookup(bro_int_t value); // Returns 0 if not found
|
||||||
|
|
||||||
string Name() const { return name; }
|
|
||||||
|
|
||||||
void DescribeReST(ODesc* d) const;
|
void DescribeReST(ODesc* d) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
EnumType() { counter = 0; }
|
|
||||||
DECLARE_SERIAL(EnumType)
|
DECLARE_SERIAL(EnumType)
|
||||||
|
|
||||||
virtual void AddNameInternal(const string& module_name,
|
void AddNameInternal(const string& module_name,
|
||||||
const char* name, bro_int_t val, bool is_export);
|
const char* name, bro_int_t val, bool is_export);
|
||||||
|
|
||||||
|
void CheckAndAddName(const string& module_name,
|
||||||
|
const char* name, bro_int_t val, bool is_export);
|
||||||
|
|
||||||
typedef std::map< const char*, bro_int_t, ltstr > NameMap;
|
typedef std::map< const char*, bro_int_t, ltstr > NameMap;
|
||||||
NameMap names;
|
NameMap names;
|
||||||
|
|
||||||
|
@ -560,31 +548,6 @@ protected:
|
||||||
// as a flag to prevent mixing of auto-increment and explicit
|
// as a flag to prevent mixing of auto-increment and explicit
|
||||||
// enumerator specifications.
|
// enumerator specifications.
|
||||||
bro_int_t counter;
|
bro_int_t counter;
|
||||||
|
|
||||||
// The name of the enum type is stored for documentation purposes.
|
|
||||||
string name;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CommentedEnumType: public EnumType {
|
|
||||||
public:
|
|
||||||
CommentedEnumType(const string& arg_name) : EnumType(arg_name) {}
|
|
||||||
CommentedEnumType(EnumType* e) : EnumType(e) {}
|
|
||||||
~CommentedEnumType();
|
|
||||||
|
|
||||||
void DescribeReST(ODesc* d) const;
|
|
||||||
void AddComment(const string& module_name, const char* name,
|
|
||||||
std::list<std::string>* comments);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// This overriden method does not install the given ID name into a
|
|
||||||
// scope and it also does not do any kind of checking that the
|
|
||||||
// provided name already exists.
|
|
||||||
void AddNameInternal(const string& module_name, const char* name,
|
|
||||||
bro_int_t val, bool is_export);
|
|
||||||
|
|
||||||
// Comments are only filled when in "documentation mode".
|
|
||||||
typedef std::map< const char*, std::list<std::string>*, ltstr > CommentMap;
|
|
||||||
CommentMap comments;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class VectorType : public BroType {
|
class VectorType : public BroType {
|
||||||
|
@ -609,6 +572,9 @@ protected:
|
||||||
BroType* yield_type;
|
BroType* yield_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::map<std::string, std::set<BroType*> > TypeAliasMap;
|
||||||
|
extern TypeAliasMap type_aliases;
|
||||||
|
|
||||||
extern OpaqueType* md5_type;
|
extern OpaqueType* md5_type;
|
||||||
extern OpaqueType* sha1_type;
|
extern OpaqueType* sha1_type;
|
||||||
extern OpaqueType* sha256_type;
|
extern OpaqueType* sha256_type;
|
||||||
|
|
67
src/Var.cc
67
src/Var.cc
|
@ -10,8 +10,6 @@
|
||||||
#include "RemoteSerializer.h"
|
#include "RemoteSerializer.h"
|
||||||
#include "EventRegistry.h"
|
#include "EventRegistry.h"
|
||||||
|
|
||||||
extern int generate_documentation;
|
|
||||||
|
|
||||||
static Val* init_val(Expr* init, const BroType* t, Val* aggr)
|
static Val* init_val(Expr* init, const BroType* t, Val* aggr)
|
||||||
{
|
{
|
||||||
return init->InitVal(t, aggr);
|
return init->InitVal(t, aggr);
|
||||||
|
@ -261,61 +259,26 @@ extern Expr* add_and_assign_local(ID* id, Expr* init, Val* val)
|
||||||
return new AssignExpr(new NameExpr(id), init, 0, val);
|
return new AssignExpr(new NameExpr(id), init, 0, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_type(ID* id, BroType* t, attr_list* attr, int /* is_event */)
|
void add_type(ID* id, BroType* t, attr_list* attr)
|
||||||
{
|
{
|
||||||
BroType* tnew = t;
|
string new_type_name(id->Name());
|
||||||
|
string old_type_name(t->GetName());
|
||||||
|
BroType* tnew = 0;
|
||||||
|
|
||||||
// In "documentation mode", we'd like to to be able to associate
|
if ( (t->Tag() == TYPE_RECORD || t->Tag() == TYPE_ENUM) &&
|
||||||
// an identifier name with a declared type. Dealing with declared
|
! old_type_name.empty() )
|
||||||
// types that are "aliases" to a builtin type requires that the BroType
|
// Clone the type to preserve type name aliasing.
|
||||||
// is cloned before setting the identifier name that resolves to it.
|
tnew = t->Clone();
|
||||||
// And still this is not enough to document cases where the declared type
|
else
|
||||||
// is an alias for another declared type -- but that's not a natural/common
|
// An extensible types (record/enum) being declared for first time.
|
||||||
// practice. If documenting that corner case is desired, one way
|
tnew = t;
|
||||||
// is to add an ID* to class ID that tracks aliases and set it here if
|
|
||||||
// t->GetTypeID() is true.
|
|
||||||
if ( generate_documentation )
|
|
||||||
{
|
|
||||||
switch ( t->Tag() ) {
|
|
||||||
// Only "shallow" copy types that may contain records because
|
|
||||||
// we want to be able to see additions to the original record type's
|
|
||||||
// list of fields
|
|
||||||
case TYPE_RECORD:
|
|
||||||
tnew = new RecordType(t->AsRecordType()->Types());
|
|
||||||
break;
|
|
||||||
case TYPE_TABLE:
|
|
||||||
tnew = new TableType(t->AsTableType()->Indices(),
|
|
||||||
t->AsTableType()->YieldType());
|
|
||||||
break;
|
|
||||||
case TYPE_VECTOR:
|
|
||||||
tnew = new VectorType(t->AsVectorType()->YieldType());
|
|
||||||
break;
|
|
||||||
case TYPE_FUNC:
|
|
||||||
tnew = new FuncType(t->AsFuncType()->Args(),
|
|
||||||
t->AsFuncType()->YieldType(),
|
|
||||||
t->AsFuncType()->Flavor());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
SerializationFormat* form = new BinarySerializationFormat();
|
|
||||||
form->StartWrite();
|
|
||||||
CloneSerializer ss(form);
|
|
||||||
SerialInfo sinfo(&ss);
|
|
||||||
sinfo.cache = false;
|
|
||||||
|
|
||||||
t->Serialize(&sinfo);
|
type_aliases[new_type_name].insert(tnew);
|
||||||
char* data;
|
|
||||||
uint32 len = form->EndWrite(&data);
|
|
||||||
form->StartRead(data, len);
|
|
||||||
|
|
||||||
UnserialInfo uinfo(&ss);
|
if ( new_type_name != old_type_name && ! old_type_name.empty() )
|
||||||
uinfo.cache = false;
|
type_aliases[old_type_name].insert(tnew);
|
||||||
tnew = t->Unserialize(&uinfo);
|
|
||||||
|
|
||||||
delete [] data;
|
tnew->SetName(id->Name());
|
||||||
}
|
|
||||||
|
|
||||||
tnew->SetTypeID(copy_string(id->Name()));
|
|
||||||
}
|
|
||||||
|
|
||||||
id->SetType(tnew);
|
id->SetType(tnew);
|
||||||
id->MakeType();
|
id->MakeType();
|
||||||
|
|
|
@ -18,7 +18,7 @@ extern Stmt* add_local(ID* id, BroType* t, init_class c, Expr* init,
|
||||||
attr_list* attr, decl_type dt);
|
attr_list* attr, decl_type dt);
|
||||||
extern Expr* add_and_assign_local(ID* id, Expr* init, Val* val = 0);
|
extern Expr* add_and_assign_local(ID* id, Expr* init, Val* val = 0);
|
||||||
|
|
||||||
extern void add_type(ID* id, BroType* t, attr_list* attr, int is_event);
|
extern void add_type(ID* id, BroType* t, attr_list* attr);
|
||||||
|
|
||||||
extern void begin_func(ID* id, const char* module_name, function_flavor flavor,
|
extern void begin_func(ID* id, const char* module_name, function_flavor flavor,
|
||||||
int is_redef, FuncType* t);
|
int is_redef, FuncType* t);
|
||||||
|
|
88
src/broxygen/Manager.cc
Normal file
88
src/broxygen/Manager.cc
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
#include "Manager.h"
|
||||||
|
|
||||||
|
using namespace broxygen;
|
||||||
|
|
||||||
|
Manager::Manager(const std::string& config)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::GenerateDocs() const
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
// may be a no-op if no config
|
||||||
|
|
||||||
|
// does the old canon_doc_func_param stuff happen here now on the fly
|
||||||
|
// for functions we're about to document?
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::File(const std::string& path)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
// determine bropath subpath
|
||||||
|
// can be a file or directory?
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::ScriptDependency(const std::string& path, const std::string& dep)
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
// need anything from BroDoc::AddImport?
|
||||||
|
// warn about unconsumed comments (and discard any)
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::ModuleUsage(const std::string& path, const std::string& module)
|
||||||
|
{
|
||||||
|
// TODO lookup script and add module to a set
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::Identifier(const ID *id)
|
||||||
|
{
|
||||||
|
// TODO: lookup script to associate w/ by GetLocationInfo()->filename
|
||||||
|
// do different things depending on Type? (eg function flavor versus state)
|
||||||
|
// do different things based on redef attr + const ?
|
||||||
|
// consume any buffered comments and associate w/ id
|
||||||
|
// deal w/ type aliasing
|
||||||
|
// special enum or record handing?
|
||||||
|
// if it's a function we may already have added it (decl versus impl)
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::RecordField(const ID *id, const TypeDecl *field,
|
||||||
|
const std::string& path)
|
||||||
|
{
|
||||||
|
// TODO: consume comments
|
||||||
|
// redef is implicit -- script path of field will differ from ID/type's
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::Redef(const ID* id, const string& path)
|
||||||
|
{
|
||||||
|
// TODO: lookup script w/ 'path' to associate the id in as redef'd
|
||||||
|
// consume any buffered comments and associate w/ redef'd id
|
||||||
|
// can sort notices here
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::SummaryComment(const std::string& script,
|
||||||
|
const std::string& comment)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
// canon_doc_comment ?
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::PreComment(const std::string& comment)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
// canon_doc_comment
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::PostComment(const std::string& comment)
|
||||||
|
{
|
||||||
|
// TODO this gets associated with the last thing registered
|
||||||
|
// canon_doc_comment
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: "canon_doc_comment" means treat "##Text" and "## Text" the same
|
||||||
|
// so that a single space doesn't generate an indentation level.
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: creating proto/file analyzer docs
|
43
src/broxygen/Manager.h
Normal file
43
src/broxygen/Manager.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef BROXYGEN_MANAGER_H
|
||||||
|
#define BROXYGEN_MANAGER_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "ID.h"
|
||||||
|
#include "Type.h"
|
||||||
|
|
||||||
|
namespace broxygen {
|
||||||
|
|
||||||
|
class Manager {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Manager(const std::string& config);
|
||||||
|
|
||||||
|
void GenerateDocs() const;
|
||||||
|
|
||||||
|
void File(const std::string& path);
|
||||||
|
|
||||||
|
void ScriptDependency(const std::string& path, const std::string& dep);
|
||||||
|
|
||||||
|
void ModuleUsage(const std::string& path, const std::string& module);
|
||||||
|
|
||||||
|
void Identifier(const ID* id);
|
||||||
|
|
||||||
|
void RecordField(const ID* id, const TypeDecl* field,
|
||||||
|
const std::string& path);
|
||||||
|
|
||||||
|
void Redef(const ID* id, const std::string& path);
|
||||||
|
|
||||||
|
void SummaryComment(const std::string& path, const std::string& comment);
|
||||||
|
|
||||||
|
void PreComment(const std::string& comment);
|
||||||
|
|
||||||
|
void PostComment(const std::string& comment);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace broxygen
|
||||||
|
|
||||||
|
extern broxygen::Manager* broxygen_mgr;
|
||||||
|
|
||||||
|
#endif
|
41
src/main.cc
41
src/main.cc
|
@ -61,8 +61,8 @@ extern "C" void OPENSSL_add_all_algorithms_conf(void);
|
||||||
#include "analyzer/Manager.h"
|
#include "analyzer/Manager.h"
|
||||||
#include "analyzer/Tag.h"
|
#include "analyzer/Tag.h"
|
||||||
#include "plugin/Manager.h"
|
#include "plugin/Manager.h"
|
||||||
|
|
||||||
#include "file_analysis/Manager.h"
|
#include "file_analysis/Manager.h"
|
||||||
|
#include "broxygen/Manager.h"
|
||||||
|
|
||||||
#include "binpac_bro.h"
|
#include "binpac_bro.h"
|
||||||
|
|
||||||
|
@ -100,6 +100,7 @@ input::Manager* input_mgr = 0;
|
||||||
plugin::Manager* plugin_mgr = 0;
|
plugin::Manager* plugin_mgr = 0;
|
||||||
analyzer::Manager* analyzer_mgr = 0;
|
analyzer::Manager* analyzer_mgr = 0;
|
||||||
file_analysis::Manager* file_mgr = 0;
|
file_analysis::Manager* file_mgr = 0;
|
||||||
|
broxygen::Manager* broxygen_mgr = 0;
|
||||||
Stmt* stmts;
|
Stmt* stmts;
|
||||||
EventHandlerPtr net_done = 0;
|
EventHandlerPtr net_done = 0;
|
||||||
RuleMatcher* rule_matcher = 0;
|
RuleMatcher* rule_matcher = 0;
|
||||||
|
@ -116,7 +117,6 @@ int signal_val = 0;
|
||||||
int optimize = 0;
|
int optimize = 0;
|
||||||
int do_notice_analysis = 0;
|
int do_notice_analysis = 0;
|
||||||
int rule_bench = 0;
|
int rule_bench = 0;
|
||||||
int generate_documentation = 0;
|
|
||||||
SecondaryPath* secondary_path = 0;
|
SecondaryPath* secondary_path = 0;
|
||||||
extern char version[];
|
extern char version[];
|
||||||
char* command_line_policy = 0;
|
char* command_line_policy = 0;
|
||||||
|
@ -124,6 +124,8 @@ vector<string> params;
|
||||||
char* proc_status_file = 0;
|
char* proc_status_file = 0;
|
||||||
int snaplen = 0; // this gets set from the scripting-layer's value
|
int snaplen = 0; // this gets set from the scripting-layer's value
|
||||||
|
|
||||||
|
TypeAliasMap type_aliases;
|
||||||
|
|
||||||
OpaqueType* md5_type = 0;
|
OpaqueType* md5_type = 0;
|
||||||
OpaqueType* sha1_type = 0;
|
OpaqueType* sha1_type = 0;
|
||||||
OpaqueType* sha256_type = 0;
|
OpaqueType* sha256_type = 0;
|
||||||
|
@ -132,8 +134,6 @@ OpaqueType* cardinality_type = 0;
|
||||||
OpaqueType* topk_type = 0;
|
OpaqueType* topk_type = 0;
|
||||||
OpaqueType* bloomfilter_type = 0;
|
OpaqueType* bloomfilter_type = 0;
|
||||||
|
|
||||||
extern std::list<BroDoc*> docs_generated;
|
|
||||||
|
|
||||||
// Keep copy of command line
|
// Keep copy of command line
|
||||||
int bro_argc;
|
int bro_argc;
|
||||||
char** bro_argv;
|
char** bro_argv;
|
||||||
|
@ -203,7 +203,7 @@ void usage()
|
||||||
fprintf(stderr, " -T|--re-level <level> | set 'RE_level' for rules\n");
|
fprintf(stderr, " -T|--re-level <level> | set 'RE_level' for rules\n");
|
||||||
fprintf(stderr, " -U|--status-file <file> | Record process status in file\n");
|
fprintf(stderr, " -U|--status-file <file> | Record process status in file\n");
|
||||||
fprintf(stderr, " -W|--watchdog | activate watchdog timer\n");
|
fprintf(stderr, " -W|--watchdog | activate watchdog timer\n");
|
||||||
fprintf(stderr, " -Z|--doc-scripts | generate documentation for all loaded scripts\n");
|
fprintf(stderr, " -X|--broxygen | generate documentation based on config file\n");
|
||||||
|
|
||||||
#ifdef USE_PERFTOOLS_DEBUG
|
#ifdef USE_PERFTOOLS_DEBUG
|
||||||
fprintf(stderr, " -m|--mem-leaks | show leaks [perftools]\n");
|
fprintf(stderr, " -m|--mem-leaks | show leaks [perftools]\n");
|
||||||
|
@ -373,6 +373,7 @@ void terminate_bro()
|
||||||
|
|
||||||
plugin_mgr->FinishPlugins();
|
plugin_mgr->FinishPlugins();
|
||||||
|
|
||||||
|
delete broxygen_mgr;
|
||||||
delete timer_mgr;
|
delete timer_mgr;
|
||||||
delete dns_mgr;
|
delete dns_mgr;
|
||||||
delete persistence_serializer;
|
delete persistence_serializer;
|
||||||
|
@ -473,7 +474,7 @@ int main(int argc, char** argv)
|
||||||
{"filter", required_argument, 0, 'f'},
|
{"filter", required_argument, 0, 'f'},
|
||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{"iface", required_argument, 0, 'i'},
|
{"iface", required_argument, 0, 'i'},
|
||||||
{"doc-scripts", no_argument, 0, 'Z'},
|
{"broxygen", required_argument, 0, 'X'},
|
||||||
{"prefix", required_argument, 0, 'p'},
|
{"prefix", required_argument, 0, 'p'},
|
||||||
{"readfile", required_argument, 0, 'r'},
|
{"readfile", required_argument, 0, 'r'},
|
||||||
{"flowfile", required_argument, 0, 'y'},
|
{"flowfile", required_argument, 0, 'y'},
|
||||||
|
@ -532,7 +533,7 @@ int main(int argc, char** argv)
|
||||||
if ( p )
|
if ( p )
|
||||||
add_to_name_list(p, ':', prefixes);
|
add_to_name_list(p, ':', prefixes);
|
||||||
|
|
||||||
string active_file;
|
string broxygen_config;
|
||||||
|
|
||||||
#ifdef USE_IDMEF
|
#ifdef USE_IDMEF
|
||||||
string libidmef_dtd_path = "idmef-message.dtd";
|
string libidmef_dtd_path = "idmef-message.dtd";
|
||||||
|
@ -545,7 +546,7 @@ int main(int argc, char** argv)
|
||||||
opterr = 0;
|
opterr = 0;
|
||||||
|
|
||||||
char opts[256];
|
char opts[256];
|
||||||
safe_strncpy(opts, "B:D:e:f:I:i:K:l:n:p:R:r:s:T:t:U:w:x:X:y:Y:z:CFGLNOPSWbdghvZ",
|
safe_strncpy(opts, "B:D:e:f:I:i:K:l:n:p:R:r:s:T:t:U:w:x:X:y:Y:z:CFGLNOPSWbdghv",
|
||||||
sizeof(opts));
|
sizeof(opts));
|
||||||
|
|
||||||
#ifdef USE_PERFTOOLS_DEBUG
|
#ifdef USE_PERFTOOLS_DEBUG
|
||||||
|
@ -727,8 +728,8 @@ int main(int argc, char** argv)
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case 'Z':
|
case 'X':
|
||||||
generate_documentation = 1;
|
broxygen_config = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef USE_IDMEF
|
#ifdef USE_IDMEF
|
||||||
|
@ -760,6 +761,7 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
reporter = new Reporter();
|
reporter = new Reporter();
|
||||||
thread_mgr = new threading::Manager();
|
thread_mgr = new threading::Manager();
|
||||||
|
broxygen_mgr = new broxygen::Manager(broxygen_config);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if ( debug_streams )
|
if ( debug_streams )
|
||||||
|
@ -888,23 +890,6 @@ int main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ( generate_documentation )
|
|
||||||
{
|
|
||||||
CreateProtoAnalyzerDoc("proto-analyzers.rst");
|
|
||||||
CreateFileAnalyzerDoc("file-analyzers.rst");
|
|
||||||
|
|
||||||
std::list<BroDoc*>::iterator it;
|
|
||||||
|
|
||||||
for ( it = docs_generated.begin(); it != docs_generated.end(); ++it )
|
|
||||||
(*it)->WriteDocFile();
|
|
||||||
|
|
||||||
for ( it = docs_generated.begin(); it != docs_generated.end(); ++it )
|
|
||||||
delete *it;
|
|
||||||
|
|
||||||
terminate_bro();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( reporter->Errors() > 0 )
|
if ( reporter->Errors() > 0 )
|
||||||
{
|
{
|
||||||
delete dns_mgr;
|
delete dns_mgr;
|
||||||
|
@ -915,6 +900,8 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
init_general_global_var();
|
init_general_global_var();
|
||||||
|
|
||||||
|
broxygen_mgr->GenerateDocs();
|
||||||
|
|
||||||
if ( user_pcap_filter )
|
if ( user_pcap_filter )
|
||||||
{
|
{
|
||||||
ID* id = global_scope()->Lookup("cmd_line_bpf_filter");
|
ID* id = global_scope()->Lookup("cmd_line_bpf_filter");
|
||||||
|
|
411
src/parse.y
411
src/parse.y
|
@ -2,7 +2,7 @@
|
||||||
// See the file "COPYING" in the main distribution directory for copyright.
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%expect 85
|
%expect 75
|
||||||
|
|
||||||
%token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY
|
%token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY
|
||||||
%token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF
|
%token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF
|
||||||
|
@ -28,8 +28,6 @@
|
||||||
|
|
||||||
%token TOK_DEBUG
|
%token TOK_DEBUG
|
||||||
|
|
||||||
%token TOK_DOC TOK_POST_DOC
|
|
||||||
|
|
||||||
%token TOK_NO_TEST
|
%token TOK_NO_TEST
|
||||||
|
|
||||||
%nonassoc TOK_HOOK
|
%nonassoc TOK_HOOK
|
||||||
|
@ -47,8 +45,7 @@
|
||||||
%left '$' '[' ']' '(' ')' TOK_HAS_FIELD TOK_HAS_ATTR
|
%left '$' '[' ']' '(' ')' TOK_HAS_FIELD TOK_HAS_ATTR
|
||||||
|
|
||||||
%type <b> opt_no_test opt_no_test_block
|
%type <b> opt_no_test opt_no_test_block
|
||||||
%type <str> TOK_ID TOK_PATTERN_TEXT single_pattern TOK_DOC TOK_POST_DOC
|
%type <str> TOK_ID TOK_PATTERN_TEXT single_pattern
|
||||||
%type <str_l> opt_doc_list opt_post_doc_list
|
|
||||||
%type <id> local_id global_id def_global_id event_id global_or_event_id resolve_id begin_func
|
%type <id> local_id global_id def_global_id event_id global_or_event_id resolve_id begin_func
|
||||||
%type <id_l> local_id_list
|
%type <id_l> local_id_list
|
||||||
%type <ic> init_class
|
%type <ic> init_class
|
||||||
|
@ -83,17 +80,13 @@
|
||||||
#include "RE.h"
|
#include "RE.h"
|
||||||
#include "Scope.h"
|
#include "Scope.h"
|
||||||
#include "Reporter.h"
|
#include "Reporter.h"
|
||||||
#include "BroDoc.h"
|
|
||||||
#include "BroDocObj.h"
|
|
||||||
#include "Brofiler.h"
|
#include "Brofiler.h"
|
||||||
|
#include "broxygen/Manager.h"
|
||||||
|
|
||||||
#include <list>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
extern Brofiler brofiler;
|
extern const char* filename; // Absolute path of file currently being parsed.
|
||||||
extern BroDoc* current_reST_doc;
|
|
||||||
extern int generate_documentation;
|
|
||||||
extern std::list<std::string>* reST_doc_comments;
|
|
||||||
|
|
||||||
YYLTYPE GetCurrentLocation();
|
YYLTYPE GetCurrentLocation();
|
||||||
extern int yyerror(const char[]);
|
extern int yyerror(const char[]);
|
||||||
|
@ -127,24 +120,13 @@ bool defining_global_ID = false;
|
||||||
|
|
||||||
ID* func_id = 0;
|
ID* func_id = 0;
|
||||||
EnumType *cur_enum_type = 0;
|
EnumType *cur_enum_type = 0;
|
||||||
CommentedEnumType *cur_enum_type_doc = 0;
|
|
||||||
const char* cur_enum_elem_id = 0;
|
|
||||||
|
|
||||||
type_decl_list* fake_type_decl_list = 0;
|
|
||||||
TypeDecl* last_fake_type_decl = 0;
|
|
||||||
|
|
||||||
static ID* cur_decl_type_id = 0;
|
static ID* cur_decl_type_id = 0;
|
||||||
|
|
||||||
static void parser_new_enum (void)
|
static void parser_new_enum (void)
|
||||||
{
|
{
|
||||||
/* Starting a new enum definition. */
|
/* Starting a new enum definition. */
|
||||||
assert(cur_enum_type == NULL);
|
assert(cur_enum_type == NULL);
|
||||||
cur_enum_type = new EnumType(cur_decl_type_id->Name());
|
cur_enum_type = new EnumType();
|
||||||
|
|
||||||
// For documentation purposes, a separate type object is created
|
|
||||||
// in order to avoid overlap that can be caused by redefs.
|
|
||||||
if ( generate_documentation )
|
|
||||||
cur_enum_type_doc = new CommentedEnumType(cur_decl_type_id->Name());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parser_redef_enum (ID *id)
|
static void parser_redef_enum (ID *id)
|
||||||
|
@ -160,53 +142,75 @@ static void parser_redef_enum (ID *id)
|
||||||
if ( ! cur_enum_type )
|
if ( ! cur_enum_type )
|
||||||
id->Error("not an enum");
|
id->Error("not an enum");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( generate_documentation )
|
|
||||||
cur_enum_type_doc = new CommentedEnumType(id->Name());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_enum_comment (std::list<std::string>* comments)
|
static type_decl_list* copy_type_decl_list(type_decl_list* tdl)
|
||||||
{
|
{
|
||||||
cur_enum_type_doc->AddComment(current_module, cur_enum_elem_id, comments);
|
if ( ! tdl )
|
||||||
}
|
return 0;
|
||||||
|
|
||||||
static ID* create_dummy_id (ID* id, BroType* type)
|
type_decl_list* rval = new type_decl_list();
|
||||||
{
|
|
||||||
ID* fake_id = new ID(copy_string(id->Name()), (IDScope) id->Scope(),
|
|
||||||
is_export);
|
|
||||||
|
|
||||||
fake_id->SetType(type->Ref());
|
loop_over_list(*tdl, i)
|
||||||
|
|
||||||
if ( id->AsType() )
|
|
||||||
{
|
{
|
||||||
type->SetTypeID(copy_string(id->Name()));
|
TypeDecl* td = (*tdl)[i];
|
||||||
fake_id->MakeType();
|
rval->append(new TypeDecl(*td));
|
||||||
}
|
}
|
||||||
|
|
||||||
return fake_id;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::list<std::string>* concat_opt_docs (std::list<std::string>* pre,
|
static attr_list* copy_attr_list(attr_list* al)
|
||||||
std::list<std::string>* post)
|
|
||||||
{
|
{
|
||||||
if ( ! pre && ! post ) return 0;
|
if ( ! al )
|
||||||
|
return 0;
|
||||||
|
|
||||||
if ( pre && ! post ) return pre;
|
attr_list* rval = new attr_list();
|
||||||
|
|
||||||
if ( ! pre && post ) return post;
|
loop_over_list(*al, i)
|
||||||
|
{
|
||||||
|
Attr* a = (*al)[i];
|
||||||
|
::Ref(a);
|
||||||
|
rval->append(a);
|
||||||
|
}
|
||||||
|
|
||||||
pre->splice(pre->end(), *post);
|
return rval;
|
||||||
delete post;
|
|
||||||
|
|
||||||
return pre;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void extend_record(ID* id, type_decl_list* fields, attr_list* attrs)
|
||||||
|
{
|
||||||
|
set<BroType*> types = type_aliases[id->Name()];
|
||||||
|
|
||||||
|
if ( types.empty() )
|
||||||
|
{
|
||||||
|
id->Error("failed to redef record: no types found in alias map");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( set<BroType*>::const_iterator it = types.begin(); it != types.end(); )
|
||||||
|
{
|
||||||
|
RecordType* add_to = (*it)->AsRecordType();
|
||||||
|
const char* error = 0;
|
||||||
|
++it;
|
||||||
|
|
||||||
|
if ( it == types.end() )
|
||||||
|
error = add_to->AddFields(fields, attrs);
|
||||||
|
else
|
||||||
|
error = add_to->AddFields(copy_type_decl_list(fields),
|
||||||
|
copy_attr_list(attrs));
|
||||||
|
|
||||||
|
if ( error )
|
||||||
|
{
|
||||||
|
id->Error(error);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%union {
|
%union {
|
||||||
bool b;
|
bool b;
|
||||||
char* str;
|
char* str;
|
||||||
std::list<std::string>* str_l;
|
|
||||||
ID* id;
|
ID* id;
|
||||||
id_list* id_l;
|
id_list* id_l;
|
||||||
init_class ic;
|
init_class ic;
|
||||||
|
@ -699,46 +703,24 @@ single_pattern:
|
||||||
;
|
;
|
||||||
|
|
||||||
enum_body:
|
enum_body:
|
||||||
enum_body_list opt_post_doc_list
|
enum_body_list
|
||||||
{
|
{
|
||||||
$$ = cur_enum_type;
|
$$ = cur_enum_type;
|
||||||
|
|
||||||
if ( generate_documentation )
|
|
||||||
{
|
|
||||||
add_enum_comment($2);
|
|
||||||
cur_enum_elem_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_enum_type = NULL;
|
cur_enum_type = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
| enum_body_list ',' opt_post_doc_list
|
| enum_body_list ','
|
||||||
{
|
{
|
||||||
$$ = cur_enum_type;
|
$$ = cur_enum_type;
|
||||||
|
|
||||||
if ( generate_documentation )
|
|
||||||
{
|
|
||||||
add_enum_comment($3);
|
|
||||||
cur_enum_elem_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_enum_type = NULL;
|
cur_enum_type = NULL;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
enum_body_list:
|
enum_body_list:
|
||||||
enum_body_elem opt_post_doc_list
|
enum_body_elem
|
||||||
{
|
|
||||||
if ( generate_documentation )
|
|
||||||
add_enum_comment($2);
|
|
||||||
}
|
|
||||||
|
|
||||||
| enum_body_list ',' opt_post_doc_list
|
| enum_body_list ',' enum_body_elem
|
||||||
{
|
;
|
||||||
if ( generate_documentation )
|
|
||||||
add_enum_comment($3);
|
|
||||||
} enum_body_elem
|
|
||||||
;
|
|
||||||
|
|
||||||
enum_body_elem:
|
enum_body_elem:
|
||||||
/* TODO: We could also define this as TOK_ID '=' expr, (or
|
/* TODO: We could also define this as TOK_ID '=' expr, (or
|
||||||
|
@ -746,25 +728,19 @@ enum_body_elem:
|
||||||
error messages if someboy tries to use constant variables as
|
error messages if someboy tries to use constant variables as
|
||||||
enumerator.
|
enumerator.
|
||||||
*/
|
*/
|
||||||
opt_doc_list TOK_ID '=' TOK_CONSTANT
|
TOK_ID '=' TOK_CONSTANT
|
||||||
{
|
{
|
||||||
set_location(@2, @4);
|
set_location(@1, @3);
|
||||||
assert(cur_enum_type);
|
assert(cur_enum_type);
|
||||||
|
|
||||||
if ( $4->Type()->Tag() != TYPE_COUNT )
|
if ( $3->Type()->Tag() != TYPE_COUNT )
|
||||||
reporter->Error("enumerator is not a count constant");
|
reporter->Error("enumerator is not a count constant");
|
||||||
else
|
else
|
||||||
cur_enum_type->AddName(current_module, $2, $4->InternalUnsigned(), is_export);
|
cur_enum_type->AddName(current_module, $1,
|
||||||
|
$3->InternalUnsigned(), is_export);
|
||||||
if ( generate_documentation )
|
|
||||||
{
|
|
||||||
cur_enum_type_doc->AddName(current_module, $2, $4->InternalUnsigned(), is_export);
|
|
||||||
cur_enum_elem_id = $2;
|
|
||||||
add_enum_comment($1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
| opt_doc_list TOK_ID '=' '-' TOK_CONSTANT
|
| TOK_ID '=' '-' TOK_CONSTANT
|
||||||
{
|
{
|
||||||
/* We only accept counts as enumerator, but we want to return a nice
|
/* We only accept counts as enumerator, but we want to return a nice
|
||||||
error message if users triy to use a negative integer (will also
|
error message if users triy to use a negative integer (will also
|
||||||
|
@ -773,18 +749,11 @@ enum_body_elem:
|
||||||
reporter->Error("enumerator is not a count constant");
|
reporter->Error("enumerator is not a count constant");
|
||||||
}
|
}
|
||||||
|
|
||||||
| opt_doc_list TOK_ID
|
| TOK_ID
|
||||||
{
|
{
|
||||||
set_location(@2);
|
set_location(@1);
|
||||||
assert(cur_enum_type);
|
assert(cur_enum_type);
|
||||||
cur_enum_type->AddName(current_module, $2, is_export);
|
cur_enum_type->AddName(current_module, $1, is_export);
|
||||||
|
|
||||||
if ( generate_documentation )
|
|
||||||
{
|
|
||||||
cur_enum_type_doc->AddName(current_module, $2, is_export);
|
|
||||||
cur_enum_elem_id = $2;
|
|
||||||
add_enum_comment($1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -872,12 +841,11 @@ type:
|
||||||
}
|
}
|
||||||
|
|
||||||
| TOK_RECORD '{'
|
| TOK_RECORD '{'
|
||||||
{ ++in_record; do_doc_token_start(); }
|
{ ++in_record; }
|
||||||
type_decl_list
|
type_decl_list
|
||||||
{ --in_record; }
|
{ --in_record; }
|
||||||
'}'
|
'}'
|
||||||
{
|
{
|
||||||
do_doc_token_stop();
|
|
||||||
set_location(@1, @5);
|
set_location(@1, @5);
|
||||||
$$ = new RecordType($4);
|
$$ = new RecordType($4);
|
||||||
}
|
}
|
||||||
|
@ -889,9 +857,8 @@ type:
|
||||||
$$ = 0;
|
$$ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
| TOK_ENUM '{' { set_location(@1); parser_new_enum(); do_doc_token_start(); } enum_body '}'
|
| TOK_ENUM '{' { set_location(@1); parser_new_enum(); } enum_body '}'
|
||||||
{
|
{
|
||||||
do_doc_token_stop();
|
|
||||||
set_location(@1, @5);
|
set_location(@1, @5);
|
||||||
$4->UpdateLocationEndInfo(@5);
|
$4->UpdateLocationEndInfo(@5);
|
||||||
$$ = $4;
|
$$ = $4;
|
||||||
|
@ -983,45 +950,21 @@ type_decl_list:
|
||||||
type_decl_list type_decl
|
type_decl_list type_decl
|
||||||
{
|
{
|
||||||
$1->append($2);
|
$1->append($2);
|
||||||
|
|
||||||
if ( generate_documentation && last_fake_type_decl )
|
|
||||||
{
|
|
||||||
fake_type_decl_list->append(last_fake_type_decl);
|
|
||||||
last_fake_type_decl = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
|
||||||
{
|
{
|
||||||
$$ = new type_decl_list();
|
$$ = new type_decl_list();
|
||||||
|
|
||||||
if ( generate_documentation )
|
|
||||||
fake_type_decl_list = new type_decl_list();
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
type_decl:
|
type_decl:
|
||||||
opt_doc_list TOK_ID ':' type opt_attr ';' opt_post_doc_list
|
TOK_ID ':' type opt_attr ';'
|
||||||
{
|
{
|
||||||
set_location(@2, @6);
|
set_location(@1, @4);
|
||||||
|
$$ = new TypeDecl($3, $1, $4, (in_record > 0));
|
||||||
|
|
||||||
if ( generate_documentation )
|
if ( in_record > 0 )
|
||||||
{
|
broxygen_mgr->RecordField(cur_decl_type_id, $$, ::filename);
|
||||||
// TypeDecl ctor deletes the attr list, so make a copy
|
|
||||||
attr_list* a = $5;
|
|
||||||
attr_list* a_copy = 0;
|
|
||||||
|
|
||||||
if ( a )
|
|
||||||
{
|
|
||||||
a_copy = new attr_list;
|
|
||||||
loop_over_list(*a, i)
|
|
||||||
a_copy->append((*a)[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
last_fake_type_decl = new CommentedTypeDecl(
|
|
||||||
$4, $2, a_copy, (in_record > 0), concat_opt_docs($1, $7));
|
|
||||||
}
|
|
||||||
|
|
||||||
$$ = new TypeDecl($4, $2, $5, (in_record > 0));
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -1055,9 +998,7 @@ decl:
|
||||||
TOK_MODULE TOK_ID ';'
|
TOK_MODULE TOK_ID ';'
|
||||||
{
|
{
|
||||||
current_module = $2;
|
current_module = $2;
|
||||||
|
broxygen_mgr->ModuleUsage(::filename, current_module);
|
||||||
if ( generate_documentation )
|
|
||||||
current_reST_doc->AddModule(current_module);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
| TOK_EXPORT '{' { is_export = true; } decl_list '}'
|
| TOK_EXPORT '{' { is_export = true; } decl_list '}'
|
||||||
|
@ -1066,171 +1007,43 @@ decl:
|
||||||
| TOK_GLOBAL def_global_id opt_type init_class opt_init opt_attr ';'
|
| TOK_GLOBAL def_global_id opt_type init_class opt_init opt_attr ';'
|
||||||
{
|
{
|
||||||
add_global($2, $3, $4, $5, $6, VAR_REGULAR);
|
add_global($2, $3, $4, $5, $6, VAR_REGULAR);
|
||||||
|
broxygen_mgr->Identifier($2);
|
||||||
if ( generate_documentation )
|
|
||||||
{
|
|
||||||
ID* id = $2;
|
|
||||||
if ( id->Type()->Tag() == TYPE_FUNC )
|
|
||||||
{
|
|
||||||
switch ( id->Type()->AsFuncType()->Flavor() ) {
|
|
||||||
|
|
||||||
case FUNC_FLAVOR_FUNCTION:
|
|
||||||
current_reST_doc->AddFunction(
|
|
||||||
new BroDocObj(id, reST_doc_comments));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FUNC_FLAVOR_EVENT:
|
|
||||||
current_reST_doc->AddEvent(
|
|
||||||
new BroDocObj(id, reST_doc_comments));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FUNC_FLAVOR_HOOK:
|
|
||||||
current_reST_doc->AddHook(
|
|
||||||
new BroDocObj(id, reST_doc_comments));
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
reporter->InternalError("invalid function flavor");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
current_reST_doc->AddStateVar(
|
|
||||||
new BroDocObj(id, reST_doc_comments));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
| TOK_CONST def_global_id opt_type init_class opt_init opt_attr ';'
|
| TOK_CONST def_global_id opt_type init_class opt_init opt_attr ';'
|
||||||
{
|
{
|
||||||
add_global($2, $3, $4, $5, $6, VAR_CONST);
|
add_global($2, $3, $4, $5, $6, VAR_CONST);
|
||||||
|
broxygen_mgr->Identifier($2);
|
||||||
if ( generate_documentation )
|
|
||||||
{
|
|
||||||
if ( $2->FindAttr(ATTR_REDEF) )
|
|
||||||
current_reST_doc->AddOption(
|
|
||||||
new BroDocObj($2, reST_doc_comments));
|
|
||||||
else
|
|
||||||
current_reST_doc->AddConstant(
|
|
||||||
new BroDocObj($2, reST_doc_comments));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
| TOK_REDEF global_id opt_type init_class opt_init opt_attr ';'
|
| TOK_REDEF global_id opt_type init_class opt_init opt_attr ';'
|
||||||
{
|
{
|
||||||
add_global($2, $3, $4, $5, $6, VAR_REDEF);
|
add_global($2, $3, $4, $5, $6, VAR_REDEF);
|
||||||
|
broxygen_mgr->Redef($2, ::filename);
|
||||||
if ( generate_documentation &&
|
|
||||||
! streq("capture_filters", $2->Name()) )
|
|
||||||
{
|
|
||||||
ID* fake_id = create_dummy_id($2, $2->Type());
|
|
||||||
BroDocObj* o = new BroDocObj(fake_id, reST_doc_comments, true);
|
|
||||||
o->SetRole(true);
|
|
||||||
current_reST_doc->AddRedef(o);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
| TOK_REDEF TOK_ENUM global_id TOK_ADD_TO
|
| TOK_REDEF TOK_ENUM global_id TOK_ADD_TO
|
||||||
'{' { parser_redef_enum($3); do_doc_token_start(); } enum_body '}' ';'
|
'{' { parser_redef_enum($3); } enum_body '}' ';'
|
||||||
{
|
{
|
||||||
do_doc_token_stop();
|
// Broxygen already grabbed new enum IDs as the type created them.
|
||||||
|
|
||||||
if ( generate_documentation )
|
|
||||||
{
|
|
||||||
ID* fake_id = create_dummy_id($3, cur_enum_type_doc);
|
|
||||||
cur_enum_type_doc = 0;
|
|
||||||
BroDocObj* o = new BroDocObj(fake_id, reST_doc_comments, true);
|
|
||||||
o->SetRole(true);
|
|
||||||
|
|
||||||
if ( extract_module_name(fake_id->Name()) == "Notice" &&
|
|
||||||
extract_var_name(fake_id->Name()) == "Type" )
|
|
||||||
current_reST_doc->AddNotice(o);
|
|
||||||
else
|
|
||||||
current_reST_doc->AddRedef(o);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
| TOK_REDEF TOK_RECORD global_id TOK_ADD_TO
|
| TOK_REDEF TOK_RECORD global_id { cur_decl_type_id = $3; } TOK_ADD_TO
|
||||||
'{' { ++in_record; do_doc_token_start(); }
|
'{' { ++in_record; } type_decl_list { --in_record; } '}' opt_attr ';'
|
||||||
type_decl_list
|
|
||||||
{ --in_record; do_doc_token_stop(); } '}' opt_attr ';'
|
|
||||||
{
|
{
|
||||||
|
cur_decl_type_id = 0;
|
||||||
|
|
||||||
if ( ! $3->Type() )
|
if ( ! $3->Type() )
|
||||||
$3->Error("unknown identifier");
|
$3->Error("unknown identifier");
|
||||||
else
|
else
|
||||||
{
|
extend_record($3, $8, $11);
|
||||||
RecordType* add_to = $3->Type()->AsRecordType();
|
|
||||||
if ( ! add_to )
|
|
||||||
$3->Error("not a record type");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const char* error = add_to->AddFields($7, $10);
|
|
||||||
if ( error )
|
|
||||||
$3->Error(error);
|
|
||||||
else if ( generate_documentation )
|
|
||||||
{
|
|
||||||
if ( fake_type_decl_list )
|
|
||||||
{
|
|
||||||
BroType* fake_record =
|
|
||||||
new RecordType(fake_type_decl_list);
|
|
||||||
ID* fake = create_dummy_id($3, fake_record);
|
|
||||||
fake_type_decl_list = 0;
|
|
||||||
BroDocObj* o =
|
|
||||||
new BroDocObj(fake, reST_doc_comments, true);
|
|
||||||
o->SetRole(true);
|
|
||||||
current_reST_doc->AddRedef(o);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Warning: doc mode did not process "
|
|
||||||
"record extension for '%s', CommentedTypeDecl"
|
|
||||||
"list unavailable.\n", $3->Name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
| TOK_TYPE global_id ':' { cur_decl_type_id = $2; } type opt_attr ';'
|
| TOK_TYPE global_id ':' { cur_decl_type_id = $2; } type opt_attr ';'
|
||||||
{
|
{
|
||||||
cur_decl_type_id = 0;
|
cur_decl_type_id = 0;
|
||||||
add_type($2, $5, $6, 0);
|
add_type($2, $5, $6);
|
||||||
|
broxygen_mgr->Identifier($2);
|
||||||
if ( generate_documentation )
|
|
||||||
{
|
|
||||||
TypeTag t = $2->AsType()->Tag();
|
|
||||||
if ( t == TYPE_ENUM && cur_enum_type_doc )
|
|
||||||
{
|
|
||||||
ID* fake = create_dummy_id($2, cur_enum_type_doc);
|
|
||||||
cur_enum_type_doc = 0;
|
|
||||||
current_reST_doc->AddType(
|
|
||||||
new BroDocObj(fake, reST_doc_comments, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
else if ( t == TYPE_RECORD && fake_type_decl_list )
|
|
||||||
{
|
|
||||||
BroType* fake_record = new RecordType(fake_type_decl_list);
|
|
||||||
ID* fake = create_dummy_id($2, fake_record);
|
|
||||||
fake_type_decl_list = 0;
|
|
||||||
current_reST_doc->AddType(
|
|
||||||
new BroDocObj(fake, reST_doc_comments, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
current_reST_doc->AddType(
|
|
||||||
new BroDocObj($2, reST_doc_comments));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
| TOK_EVENT event_id ':' type_list opt_attr ';'
|
|
||||||
{
|
|
||||||
add_type($2, $4, $5, 1);
|
|
||||||
|
|
||||||
if ( generate_documentation )
|
|
||||||
current_reST_doc->AddEvent(
|
|
||||||
new BroDocObj($2, reST_doc_comments));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
| func_hdr func_body
|
| func_hdr func_body
|
||||||
|
@ -1258,18 +1071,13 @@ func_hdr:
|
||||||
begin_func($2, current_module.c_str(),
|
begin_func($2, current_module.c_str(),
|
||||||
FUNC_FLAVOR_FUNCTION, 0, $3);
|
FUNC_FLAVOR_FUNCTION, 0, $3);
|
||||||
$$ = $3;
|
$$ = $3;
|
||||||
if ( generate_documentation )
|
broxygen_mgr->Identifier($2);
|
||||||
current_reST_doc->AddFunction(
|
|
||||||
new BroDocObj($2, reST_doc_comments));
|
|
||||||
}
|
}
|
||||||
| TOK_EVENT event_id func_params
|
| TOK_EVENT event_id func_params
|
||||||
{
|
{
|
||||||
begin_func($2, current_module.c_str(),
|
begin_func($2, current_module.c_str(),
|
||||||
FUNC_FLAVOR_EVENT, 0, $3);
|
FUNC_FLAVOR_EVENT, 0, $3);
|
||||||
$$ = $3;
|
$$ = $3;
|
||||||
if ( generate_documentation )
|
|
||||||
current_reST_doc->AddEventHandler(
|
|
||||||
new BroDocObj($2, reST_doc_comments));
|
|
||||||
}
|
}
|
||||||
| TOK_HOOK def_global_id func_params
|
| TOK_HOOK def_global_id func_params
|
||||||
{
|
{
|
||||||
|
@ -1278,9 +1086,6 @@ func_hdr:
|
||||||
begin_func($2, current_module.c_str(),
|
begin_func($2, current_module.c_str(),
|
||||||
FUNC_FLAVOR_HOOK, 0, $3);
|
FUNC_FLAVOR_HOOK, 0, $3);
|
||||||
$$ = $3;
|
$$ = $3;
|
||||||
if ( generate_documentation )
|
|
||||||
current_reST_doc->AddHookHandler(
|
|
||||||
new BroDocObj($2, reST_doc_comments));
|
|
||||||
}
|
}
|
||||||
| TOK_REDEF TOK_EVENT event_id func_params
|
| TOK_REDEF TOK_EVENT event_id func_params
|
||||||
{
|
{
|
||||||
|
@ -1729,40 +1534,6 @@ resolve_id:
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
opt_post_doc_list:
|
|
||||||
opt_post_doc_list TOK_POST_DOC
|
|
||||||
{
|
|
||||||
$1->push_back($2);
|
|
||||||
$$ = $1;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
TOK_POST_DOC
|
|
||||||
{
|
|
||||||
$$ = new std::list<std::string>();
|
|
||||||
$$->push_back($1);
|
|
||||||
delete [] $1;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
{ $$ = 0; }
|
|
||||||
;
|
|
||||||
|
|
||||||
opt_doc_list:
|
|
||||||
opt_doc_list TOK_DOC
|
|
||||||
{
|
|
||||||
$1->push_back($2);
|
|
||||||
$$ = $1;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
TOK_DOC
|
|
||||||
{
|
|
||||||
$$ = new std::list<std::string>();
|
|
||||||
$$->push_back($1);
|
|
||||||
delete [] $1;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
{ $$ = 0; }
|
|
||||||
;
|
|
||||||
|
|
||||||
opt_no_test:
|
opt_no_test:
|
||||||
TOK_NO_TEST
|
TOK_NO_TEST
|
||||||
{ $$ = true; }
|
{ $$ = true; }
|
||||||
|
@ -1788,10 +1559,6 @@ int yyerror(const char msg[])
|
||||||
else
|
else
|
||||||
sprintf(msgbuf, "%s, at or near \"%s\"", msg, last_tok);
|
sprintf(msgbuf, "%s, at or near \"%s\"", msg, last_tok);
|
||||||
|
|
||||||
if ( generate_documentation )
|
|
||||||
strcat(msgbuf, "\nDocumentation mode is enabled: "
|
|
||||||
"remember to check syntax of ## style comments\n");
|
|
||||||
|
|
||||||
if ( in_debug )
|
if ( in_debug )
|
||||||
g_curr_debug_error = copy_string(msg);
|
g_curr_debug_error = copy_string(msg);
|
||||||
|
|
||||||
|
|
|
@ -130,9 +130,9 @@ template <class T, class C>
|
||||||
ComponentManager<T, C>::ComponentManager(const string& arg_module)
|
ComponentManager<T, C>::ComponentManager(const string& arg_module)
|
||||||
: module(arg_module)
|
: module(arg_module)
|
||||||
{
|
{
|
||||||
tag_enum_type = new EnumType(module + "::Tag");
|
tag_enum_type = new EnumType();
|
||||||
::ID* id = install_ID("Tag", module.c_str(), true, true);
|
::ID* id = install_ID("Tag", module.c_str(), true, true);
|
||||||
add_type(id, tag_enum_type, 0, 0);
|
add_type(id, tag_enum_type, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class C>
|
template <class T, class C>
|
||||||
|
|
221
src/scan.l
221
src/scan.l
|
@ -23,16 +23,15 @@
|
||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
#include "PolicyFile.h"
|
#include "PolicyFile.h"
|
||||||
#include "broparse.h"
|
#include "broparse.h"
|
||||||
#include "BroDoc.h"
|
|
||||||
#include "Reporter.h"
|
#include "Reporter.h"
|
||||||
#include "RE.h"
|
#include "RE.h"
|
||||||
#include "Net.h"
|
#include "Net.h"
|
||||||
|
|
||||||
#include "analyzer/Analyzer.h"
|
#include "analyzer/Analyzer.h"
|
||||||
|
#include "broxygen/Manager.h"
|
||||||
|
|
||||||
extern YYLTYPE yylloc; // holds start line and column of token
|
extern YYLTYPE yylloc; // holds start line and column of token
|
||||||
extern int print_loaded_scripts;
|
extern int print_loaded_scripts;
|
||||||
extern int generate_documentation;
|
|
||||||
|
|
||||||
// Track the @if... depth.
|
// Track the @if... depth.
|
||||||
ptr_compat_int current_depth = 0;
|
ptr_compat_int current_depth = 0;
|
||||||
|
@ -40,10 +39,7 @@ ptr_compat_int current_depth = 0;
|
||||||
int_list if_stack;
|
int_list if_stack;
|
||||||
|
|
||||||
int line_number = 1;
|
int line_number = 1;
|
||||||
const char* filename = 0;
|
const char* filename = 0; // Absolute path of file currently being parsed.
|
||||||
BroDoc* current_reST_doc = 0;
|
|
||||||
static BroDoc* last_reST_doc = 0;
|
|
||||||
string current_scanned_file_path;
|
|
||||||
|
|
||||||
char last_tok[128];
|
char last_tok[128];
|
||||||
|
|
||||||
|
@ -56,41 +52,15 @@ char last_tok[128];
|
||||||
if ( ((result = fread(buf, 1, max_size, yyin)) == 0) && ferror(yyin) ) \
|
if ( ((result = fread(buf, 1, max_size, yyin)) == 0) && ferror(yyin) ) \
|
||||||
reporter->Error("read failed with \"%s\"", strerror(errno));
|
reporter->Error("read failed with \"%s\"", strerror(errno));
|
||||||
|
|
||||||
// reST documents that we've created (or have at least opened so far).
|
static string get_dirname(const char* path)
|
||||||
std::list<BroDoc*> docs_generated;
|
|
||||||
|
|
||||||
// reST comments (those starting with ##) seen so far.
|
|
||||||
std::list<std::string>* reST_doc_comments = 0;
|
|
||||||
|
|
||||||
// Print current contents of reST_doc_comments list to stderr.
|
|
||||||
void print_current_reST_doc_comments();
|
|
||||||
|
|
||||||
// Delete the reST_doc_comments list object.
|
|
||||||
void clear_reST_doc_comments();
|
|
||||||
|
|
||||||
// Adds changes to capture_filter to the current script's reST documentation.
|
|
||||||
static void check_capture_filter_changes();
|
|
||||||
|
|
||||||
static const char* canon_doc_comment(const char* comment)
|
|
||||||
{
|
{
|
||||||
// "##Text" and "## Text" are treated the same in order to be able
|
if ( ! path )
|
||||||
// to still preserve indentation level, but not unintentionally
|
return "";
|
||||||
// signify an indentation level for all the text when using
|
|
||||||
// the "## Text" style.
|
|
||||||
return ( comment[0] == ' ' ) ? comment + 1 : comment;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string canon_doc_func_param(const char* id_start)
|
char* tmp = copy_string(path);
|
||||||
{
|
string rval = dirname(tmp);
|
||||||
std::string id_name(id_start, strcspn(id_start, ":"));
|
delete[] tmp;
|
||||||
const char* comment = id_start + id_name.size() + 1;
|
return rval;
|
||||||
std::string doc;
|
|
||||||
|
|
||||||
if ( id_name == "Returns" )
|
|
||||||
doc.append(":returns:").append(comment);
|
|
||||||
else
|
|
||||||
doc.append(":param ").append(id_name).append(":").append(comment);
|
|
||||||
return doc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ino_t get_inode_num(FILE* f, const char* filename)
|
static ino_t get_inode_num(FILE* f, const char* filename)
|
||||||
|
@ -99,7 +69,8 @@ static ino_t get_inode_num(FILE* f, const char* filename)
|
||||||
|
|
||||||
if ( fstat(fileno(f), &b) )
|
if ( fstat(fileno(f), &b) )
|
||||||
{
|
{
|
||||||
reporter->Error("failed to fstat fd of %s\n", filename);
|
reporter->Error("failed to fstat fd of %s: %s\n", filename,
|
||||||
|
strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,8 +87,6 @@ public:
|
||||||
const char* name;
|
const char* name;
|
||||||
int line;
|
int line;
|
||||||
int level;
|
int level;
|
||||||
BroDoc* doc;
|
|
||||||
string path;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// A stack of input buffers we're scanning. file_stack[len-1] is the
|
// A stack of input buffers we're scanning. file_stack[len-1] is the
|
||||||
|
@ -141,7 +110,6 @@ static int load_files(const char* file);
|
||||||
|
|
||||||
%x RE
|
%x RE
|
||||||
%x IGNORE
|
%x IGNORE
|
||||||
%s DOC
|
|
||||||
|
|
||||||
OWS [ \t]*
|
OWS [ \t]*
|
||||||
WS [ \t]+
|
WS [ \t]+
|
||||||
|
@ -159,63 +127,15 @@ ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+))
|
||||||
%%
|
%%
|
||||||
|
|
||||||
##!.* {
|
##!.* {
|
||||||
// Add this format of comments to the script documentation's "summary".
|
broxygen_mgr->SummaryComment(::filename, yytext + 3);
|
||||||
if ( generate_documentation )
|
|
||||||
current_reST_doc->AddSummary(canon_doc_comment(yytext + 3));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<DOC>##<.* {
|
|
||||||
yylval.str = copy_string(canon_doc_comment(yytext + 3));
|
|
||||||
return TOK_POST_DOC;
|
|
||||||
}
|
|
||||||
|
|
||||||
<DOC>##{OWS}{ID}:{WS}.* {
|
|
||||||
const char* id_start = skip_whitespace(yytext + 2);
|
|
||||||
yylval.str = copy_string(canon_doc_func_param(id_start).c_str());
|
|
||||||
return TOK_DOC;
|
|
||||||
}
|
|
||||||
|
|
||||||
<DOC>##.* {
|
|
||||||
if ( yytext[2] != '#' )
|
|
||||||
{
|
|
||||||
yylval.str = copy_string(canon_doc_comment(yytext + 2));
|
|
||||||
return TOK_DOC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
##{OWS}{ID}:{WS}.* {
|
|
||||||
if ( generate_documentation )
|
|
||||||
{
|
|
||||||
// Comment is documenting either a function parameter or return type,
|
|
||||||
// so appropriate reST markup substitutions are automatically made
|
|
||||||
// in order to distinguish them from other comments.
|
|
||||||
if ( ! reST_doc_comments )
|
|
||||||
reST_doc_comments = new std::list<std::string>();
|
|
||||||
|
|
||||||
// always insert a blank line so that this param/return markup
|
|
||||||
// 1) doesn't show up in the summary section in the case that it's
|
|
||||||
// the first comment for the function/event
|
|
||||||
// 2) has a blank line between it and non-field-list reST markup,
|
|
||||||
// which is required for correct HTML rendering by Sphinx
|
|
||||||
reST_doc_comments->push_back("");
|
|
||||||
const char* id_start = skip_whitespace(yytext + 2);
|
|
||||||
reST_doc_comments->push_back(canon_doc_func_param(id_start));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
##<.* {
|
##<.* {
|
||||||
if ( generate_documentation && BroDocObj::last )
|
broxygen_mgr->PostComment(yytext + 3);
|
||||||
BroDocObj::last->AddDocString(canon_doc_comment(yytext + 3));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
##.* {
|
##.* {
|
||||||
if ( generate_documentation && (yytext[2] != '#') )
|
broxygen_mgr->PreComment(yytext + 2);
|
||||||
{
|
|
||||||
if ( ! reST_doc_comments )
|
|
||||||
reST_doc_comments = new std::list<std::string>();
|
|
||||||
|
|
||||||
reST_doc_comments->push_back(canon_doc_comment(yytext + 2));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#{OWS}@no-test.* return TOK_NO_TEST;
|
#{OWS}@no-test.* return TOK_NO_TEST;
|
||||||
|
@ -224,7 +144,7 @@ ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+))
|
||||||
|
|
||||||
{WS} /* eat whitespace */
|
{WS} /* eat whitespace */
|
||||||
|
|
||||||
<INITIAL,IGNORE,DOC>\n {
|
<INITIAL,IGNORE>\n {
|
||||||
++line_number;
|
++line_number;
|
||||||
++yylloc.first_line;
|
++yylloc.first_line;
|
||||||
++yylloc.last_line;
|
++yylloc.last_line;
|
||||||
|
@ -345,7 +265,7 @@ when return TOK_WHEN;
|
||||||
@DEBUG return TOK_DEBUG; // marks input for debugger
|
@DEBUG return TOK_DEBUG; // marks input for debugger
|
||||||
|
|
||||||
@DIR {
|
@DIR {
|
||||||
string rval = current_scanned_file_path;
|
string rval = get_dirname(::filename);
|
||||||
|
|
||||||
if ( ! rval.empty() && rval[0] == '.' )
|
if ( ! rval.empty() && rval[0] == '.' )
|
||||||
{
|
{
|
||||||
|
@ -374,25 +294,15 @@ when return TOK_WHEN;
|
||||||
|
|
||||||
@load{WS}{FILE} {
|
@load{WS}{FILE} {
|
||||||
const char* new_file = skip_whitespace(yytext + 5); // Skip "@load".
|
const char* new_file = skip_whitespace(yytext + 5); // Skip "@load".
|
||||||
if ( generate_documentation )
|
broxygen_mgr->ScriptDependency(::filename, new_file);
|
||||||
{
|
|
||||||
current_reST_doc->AddImport(new_file);
|
|
||||||
|
|
||||||
if ( reST_doc_comments )
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Warning: unconsumed reST documentation is being "
|
|
||||||
"discarded before doing '@load %s' in %s:\n",
|
|
||||||
new_file, current_reST_doc->GetSourceFileName());
|
|
||||||
clear_reST_doc_comments();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(void) load_files(new_file);
|
(void) load_files(new_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
@load-sigs{WS}{FILE} {
|
@load-sigs{WS}{FILE} {
|
||||||
const char* new_sig_file = skip_whitespace(yytext + 10);
|
const char* new_sig_file = skip_whitespace(yytext + 10);
|
||||||
const char* full_filename = 0;
|
const char* full_filename = 0;
|
||||||
FILE* f = search_for_file(new_sig_file, "sig", &full_filename, false, 0);
|
FILE* f = search_for_file(new_sig_file, "sig", &full_filename, false, 0,
|
||||||
|
get_dirname(::filename));
|
||||||
|
|
||||||
if ( f )
|
if ( f )
|
||||||
{
|
{
|
||||||
|
@ -411,7 +321,8 @@ when return TOK_WHEN;
|
||||||
|
|
||||||
// All we have to do is pretend we've already scanned it.
|
// All we have to do is pretend we've already scanned it.
|
||||||
const char* full_filename;
|
const char* full_filename;
|
||||||
FILE* f = search_for_file(new_file, "bro", &full_filename, true, 0);
|
FILE* f = search_for_file(new_file, "bro", &full_filename, true, 0,
|
||||||
|
get_dirname(::filename));
|
||||||
|
|
||||||
if ( f )
|
if ( f )
|
||||||
{
|
{
|
||||||
|
@ -603,7 +514,7 @@ static int load_files(const char* orig_file)
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
f = search_for_file(orig_file, "bro", &full_filename, true, &bropath_subpath);
|
f = search_for_file(orig_file, "bro", &full_filename, true, &bropath_subpath, get_dirname(::filename));
|
||||||
bropath_subpath_delete = bropath_subpath; // This will be deleted.
|
bropath_subpath_delete = bropath_subpath; // This will be deleted.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -666,15 +577,7 @@ static int load_files(const char* orig_file)
|
||||||
else
|
else
|
||||||
file_stack.append(new FileInfo);
|
file_stack.append(new FileInfo);
|
||||||
|
|
||||||
char* tmp = copy_string(full_filename);
|
broxygen_mgr->File(full_filename);
|
||||||
current_scanned_file_path = dirname(tmp);
|
|
||||||
delete [] tmp;
|
|
||||||
|
|
||||||
if ( generate_documentation )
|
|
||||||
{
|
|
||||||
current_reST_doc = new BroDoc(bropath_subpath, full_filename);
|
|
||||||
docs_generated.push_back(current_reST_doc);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete [] bropath_subpath_delete;
|
delete [] bropath_subpath_delete;
|
||||||
|
|
||||||
|
@ -776,28 +679,11 @@ void do_atendif()
|
||||||
--current_depth;
|
--current_depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_doc_token_start()
|
|
||||||
{
|
|
||||||
if ( generate_documentation )
|
|
||||||
BEGIN(DOC);
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_doc_token_stop()
|
|
||||||
{
|
|
||||||
if ( generate_documentation )
|
|
||||||
BEGIN(INITIAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Be careful to never delete things from this list, as the strings
|
// Be careful to never delete things from this list, as the strings
|
||||||
// are referred to (in order to save the locations of tokens and statements,
|
// are referred to (in order to save the locations of tokens and statements,
|
||||||
// for error reporting and debugging).
|
// for error reporting and debugging).
|
||||||
static name_list input_files;
|
static name_list input_files;
|
||||||
|
|
||||||
const char* get_current_input_filename()
|
|
||||||
{
|
|
||||||
return ::filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_input_file(const char* file)
|
void add_input_file(const char* file)
|
||||||
{
|
{
|
||||||
if ( ! file )
|
if ( ! file )
|
||||||
|
@ -852,8 +738,6 @@ int yywrap()
|
||||||
// Stack is now empty.
|
// Stack is now empty.
|
||||||
while ( input_files.length() > 0 )
|
while ( input_files.length() > 0 )
|
||||||
{
|
{
|
||||||
check_capture_filter_changes();
|
|
||||||
|
|
||||||
if ( load_files(input_files[0]) )
|
if ( load_files(input_files[0]) )
|
||||||
{
|
{
|
||||||
// Don't delete the filename - it's pointed to by
|
// Don't delete the filename - it's pointed to by
|
||||||
|
@ -867,8 +751,6 @@ int yywrap()
|
||||||
(void) input_files.remove_nth(0);
|
(void) input_files.remove_nth(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
check_capture_filter_changes();
|
|
||||||
|
|
||||||
// For each file scanned so far, and for each @prefix, look for a
|
// For each file scanned so far, and for each @prefix, look for a
|
||||||
// prefixed and flattened version of the loaded file in BROPATH. The
|
// prefixed and flattened version of the loaded file in BROPATH. The
|
||||||
// flattening involves taking the path in BROPATH in which the
|
// flattening involves taking the path in BROPATH in which the
|
||||||
|
@ -893,7 +775,8 @@ int yywrap()
|
||||||
|
|
||||||
string s;
|
string s;
|
||||||
s = dot_canon(it->subpath.c_str(), it->name.c_str(), prefixes[i]);
|
s = dot_canon(it->subpath.c_str(), it->name.c_str(), prefixes[i]);
|
||||||
FILE* f = search_for_file(s.c_str(), "bro", 0, false, 0);
|
FILE* f = search_for_file(s.c_str(), "bro", 0, false, 0,
|
||||||
|
get_dirname(::filename));
|
||||||
|
|
||||||
//printf("====== prefix search ======\n");
|
//printf("====== prefix search ======\n");
|
||||||
//printf("File : %s\n", it->name.c_str());
|
//printf("File : %s\n", it->name.c_str());
|
||||||
|
@ -977,9 +860,6 @@ int yywrap()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( generate_documentation )
|
|
||||||
clear_reST_doc_comments();
|
|
||||||
|
|
||||||
// Otherwise, we are done.
|
// Otherwise, we are done.
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -990,8 +870,6 @@ FileInfo::FileInfo(string arg_restore_module)
|
||||||
restore_module = arg_restore_module;
|
restore_module = arg_restore_module;
|
||||||
name = ::filename;
|
name = ::filename;
|
||||||
line = ::line_number;
|
line = ::line_number;
|
||||||
doc = ::current_reST_doc;
|
|
||||||
path = current_scanned_file_path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FileInfo::~FileInfo()
|
FileInfo::~FileInfo()
|
||||||
|
@ -1002,56 +880,7 @@ FileInfo::~FileInfo()
|
||||||
yy_switch_to_buffer(buffer_state);
|
yy_switch_to_buffer(buffer_state);
|
||||||
yylloc.filename = filename = name;
|
yylloc.filename = filename = name;
|
||||||
yylloc.first_line = yylloc.last_line = line_number = line;
|
yylloc.first_line = yylloc.last_line = line_number = line;
|
||||||
last_reST_doc = current_reST_doc;
|
|
||||||
current_reST_doc = doc;
|
|
||||||
current_scanned_file_path = path;
|
|
||||||
|
|
||||||
if ( restore_module != "" )
|
if ( restore_module != "" )
|
||||||
current_module = restore_module;
|
current_module = restore_module;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_capture_filter_changes()
|
|
||||||
{
|
|
||||||
if ( ! generate_documentation )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Lookup the "capture_filters" identifier, if it has any defined
|
|
||||||
// value, add it to the script's reST documentation, and finally
|
|
||||||
// clear the table so it doesn't taint the documentation for
|
|
||||||
// subsequent scripts.
|
|
||||||
|
|
||||||
ID* capture_filters = global_scope()->Lookup("capture_filters");
|
|
||||||
|
|
||||||
if ( capture_filters )
|
|
||||||
{
|
|
||||||
ODesc desc;
|
|
||||||
desc.SetIndentSpaces(4);
|
|
||||||
capture_filters->ID_Val()->Describe(&desc);
|
|
||||||
last_reST_doc->SetPacketFilter(desc.Description());
|
|
||||||
capture_filters->ID_Val()->AsTableVal()->RemoveAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_current_reST_doc_comments()
|
|
||||||
{
|
|
||||||
if ( ! reST_doc_comments )
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::list<std::string>::iterator it;
|
|
||||||
|
|
||||||
for ( it = reST_doc_comments->begin(); it != reST_doc_comments->end(); ++it )
|
|
||||||
fprintf(stderr, "##%s\n", it->c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear_reST_doc_comments()
|
|
||||||
{
|
|
||||||
if ( ! reST_doc_comments )
|
|
||||||
return;
|
|
||||||
|
|
||||||
fprintf(stderr, "Warning: %zu unconsumed reST comments:\n",
|
|
||||||
reST_doc_comments->size());
|
|
||||||
|
|
||||||
print_current_reST_doc_comments();
|
|
||||||
delete reST_doc_comments;
|
|
||||||
reST_doc_comments = 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1060,11 +1060,9 @@ void get_script_subpath(const std::string& full_filename, const char** subpath)
|
||||||
*subpath = normalize_path(my_subpath.c_str());
|
*subpath = normalize_path(my_subpath.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
extern string current_scanned_file_path;
|
|
||||||
|
|
||||||
FILE* search_for_file(const char* filename, const char* ext,
|
FILE* search_for_file(const char* filename, const char* ext,
|
||||||
const char** full_filename, bool load_pkgs,
|
const char** full_filename, bool load_pkgs,
|
||||||
const char** bropath_subpath)
|
const char** bropath_subpath, string prepend_to_search_path)
|
||||||
{
|
{
|
||||||
// If the file is a literal absolute path we don't have to search,
|
// If the file is a literal absolute path we don't have to search,
|
||||||
// just return the result of trying to open it. If the file is
|
// just return the result of trying to open it. If the file is
|
||||||
|
@ -1088,9 +1086,9 @@ FILE* search_for_file(const char* filename, const char* ext,
|
||||||
|
|
||||||
// Prepend the currently loading script's path to BROPATH so that
|
// Prepend the currently loading script's path to BROPATH so that
|
||||||
// @loads can be referenced relatively.
|
// @loads can be referenced relatively.
|
||||||
if ( current_scanned_file_path != "" && filename[0] == '.' )
|
if ( ! prepend_to_search_path.empty() && filename[0] == '.' )
|
||||||
safe_snprintf(path, sizeof(path), "%s:%s",
|
safe_snprintf(path, sizeof(path), "%s:%s",
|
||||||
current_scanned_file_path.c_str(), bro_path());
|
prepend_to_search_path.c_str(), bro_path());
|
||||||
else
|
else
|
||||||
safe_strncpy(path, bro_path(), sizeof(path));
|
safe_strncpy(path, bro_path(), sizeof(path));
|
||||||
|
|
||||||
|
|
|
@ -209,7 +209,8 @@ std::string dot_canon(std::string path, std::string file, std::string prefix = "
|
||||||
const char* normalize_path(const char* path);
|
const char* normalize_path(const char* path);
|
||||||
void get_script_subpath(const std::string& full_filename, const char** subpath);
|
void get_script_subpath(const std::string& full_filename, const char** subpath);
|
||||||
extern FILE* search_for_file(const char* filename, const char* ext,
|
extern FILE* search_for_file(const char* filename, const char* ext,
|
||||||
const char** full_filename, bool load_pkgs, const char** bropath_subpath);
|
const char** full_filename, bool load_pkgs, const char** bropath_subpath,
|
||||||
|
std::string prepend_to_search_path = "");
|
||||||
|
|
||||||
// Renames the given file to a new temporary name, and opens a new file with
|
// Renames the given file to a new temporary name, and opens a new file with
|
||||||
// the original name. Returns new file or NULL on error. Inits rotate_info if
|
// the original name. Returns new file or NULL on error. Inits rotate_info if
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue