mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Broxygen can now read a config file specifying particular targets.
Though nothing currently gets built as most dependency/outdated checks and doc-generation methods are still skeleton code.
This commit is contained in:
parent
1fabbd441c
commit
bdd359d58c
9 changed files with 325 additions and 24 deletions
|
@ -6,8 +6,9 @@ include_directories(BEFORE
|
|||
)
|
||||
|
||||
set(broxygen_SRCS
|
||||
Manager.cc
|
||||
Configuration.cc
|
||||
Document.cc
|
||||
Manager.cc
|
||||
)
|
||||
|
||||
bif_target(broxygen.bif)
|
||||
|
|
123
src/broxygen/Configuration.cc
Normal file
123
src/broxygen/Configuration.cc
Normal file
|
@ -0,0 +1,123 @@
|
|||
#include "Configuration.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "Reporter.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
using namespace broxygen;
|
||||
using namespace std;
|
||||
|
||||
typedef map<string, Target::factory_fn> target_factory_map;
|
||||
|
||||
static target_factory_map create_target_factory_map()
|
||||
{
|
||||
target_factory_map rval;
|
||||
rval["package_index"] = &PackageTarget::Instantiate;
|
||||
rval["package"] = &PackageTarget::Instantiate;
|
||||
rval["proto_analyzer"] = &ProtoAnalyzerTarget::Instantiate;
|
||||
rval["file_analyzer"] = &FileAnalyzerTarget::Instantiate;
|
||||
rval["script_summary"] = &ScriptTarget::Instantiate;
|
||||
rval["script_index"] = &ScriptTarget::Instantiate;
|
||||
rval["script"] = &ScriptTarget::Instantiate;
|
||||
rval["identifier"] = &IdentifierTarget::Instantiate;
|
||||
return rval;
|
||||
}
|
||||
|
||||
static target_factory_map target_instantiators = create_target_factory_map();
|
||||
|
||||
bool Target::MatchesPattern(Document* doc) const
|
||||
{
|
||||
// TODO: prefix matching or full regex?
|
||||
|
||||
if ( doc->Name() == pattern )
|
||||
{
|
||||
DBG_LOG(DBG_BROXYGEN, "Doc '%s'' matched pattern for target '%s'",
|
||||
doc->Name().c_str(), name.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void filter_matching_docs(const std::vector<Document*>& filter_from, Target* t)
|
||||
{
|
||||
for ( size_t i = 0; i < filter_from.size(); ++i )
|
||||
{
|
||||
T* d = dynamic_cast<T*>(filter_from[i]);
|
||||
|
||||
if ( ! d )
|
||||
continue;
|
||||
|
||||
if ( t->MatchesPattern(d) )
|
||||
t->AddDependency(d);
|
||||
}
|
||||
}
|
||||
|
||||
void IdentifierTarget::DoFindDependencies(const std::vector<Document*>& docs)
|
||||
{
|
||||
filter_matching_docs<IdentifierDocument>(docs, this);
|
||||
}
|
||||
|
||||
Config::Config(const string& file, const string& delim)
|
||||
{
|
||||
if ( file.empty() )
|
||||
return;
|
||||
|
||||
ifstream f(file.c_str());
|
||||
|
||||
if ( ! f.is_open() )
|
||||
reporter->InternalError("failed to open Broxygen config file %s: %s",
|
||||
file.c_str(), strerror(errno));
|
||||
|
||||
string line;
|
||||
|
||||
while ( getline(f, line) )
|
||||
{
|
||||
vector<string> tokens;
|
||||
tokenize_string(line, delim, &tokens);
|
||||
tokens.erase(remove(tokens.begin(), tokens.end(), ""), tokens.end());
|
||||
|
||||
if ( tokens.size() != 3 )
|
||||
reporter->InternalError("malformed Broxygen target: %s",
|
||||
line.c_str());
|
||||
|
||||
target_factory_map::const_iterator it =
|
||||
target_instantiators.find(tokens[0]);
|
||||
|
||||
if ( it == target_instantiators.end() )
|
||||
reporter->InternalError("unkown Broxygen target type: %s",
|
||||
tokens[0].c_str());
|
||||
|
||||
targets.push_back(it->second(tokens[1], tokens[2]));
|
||||
}
|
||||
|
||||
if ( f.bad() )
|
||||
reporter->InternalError("error reading Broxygen config file %s: %s",
|
||||
file.c_str(), strerror(errno));
|
||||
}
|
||||
|
||||
Config::~Config()
|
||||
{
|
||||
for ( target_list::const_iterator it = targets.begin();
|
||||
it != targets.end(); ++it )
|
||||
delete *it;
|
||||
}
|
||||
|
||||
void Config::FindDependencies(const vector<Document*>& docs)
|
||||
{
|
||||
for ( target_list::const_iterator it = targets.begin();
|
||||
it != targets.end(); ++it )
|
||||
(*it)->FindDependencies(docs);
|
||||
}
|
||||
|
||||
void Config::GenerateDocs() const
|
||||
{
|
||||
for ( target_list::const_iterator it = targets.begin();
|
||||
it != targets.end(); ++it )
|
||||
(*it)->Generate();
|
||||
}
|
169
src/broxygen/Configuration.h
Normal file
169
src/broxygen/Configuration.h
Normal file
|
@ -0,0 +1,169 @@
|
|||
#ifndef BROXYGEN_CONFIGURATION_H
|
||||
#define BROXYGEN_CONFIGURATION_H
|
||||
|
||||
#include "Document.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
namespace broxygen {
|
||||
|
||||
// TODO: documentation...
|
||||
|
||||
class Target {
|
||||
public:
|
||||
|
||||
typedef Target* (*factory_fn)(const std::string&, const std::string&);
|
||||
|
||||
virtual ~Target() { }
|
||||
|
||||
void FindDependencies(const std::vector<Document*>& docs)
|
||||
{ DoFindDependencies(docs); }
|
||||
|
||||
void Generate() const
|
||||
{ DoGenerate(); }
|
||||
|
||||
bool MatchesPattern(Document* doc) const;
|
||||
|
||||
void AddDependency(Document* doc)
|
||||
{ dependencies.push_back(doc); }
|
||||
|
||||
protected:
|
||||
|
||||
Target(const std::string& arg_name, const std::string& arg_pattern)
|
||||
: name(arg_name), pattern(arg_pattern)
|
||||
{ }
|
||||
|
||||
std::string name;
|
||||
std::string pattern;
|
||||
std::list<Document*> dependencies;
|
||||
|
||||
private:
|
||||
|
||||
virtual void DoFindDependencies(const std::vector<Document*>& docs) = 0;
|
||||
|
||||
virtual void DoGenerate() const = 0;
|
||||
};
|
||||
|
||||
class ProtoAnalyzerTarget : public Target {
|
||||
public:
|
||||
|
||||
static Target* Instantiate(const std::string& name,
|
||||
const std::string& pattern)
|
||||
{ return new ProtoAnalyzerTarget(name, pattern); }
|
||||
|
||||
private:
|
||||
|
||||
ProtoAnalyzerTarget(const std::string& name, const std::string& pattern)
|
||||
: Target(name, pattern)
|
||||
{ }
|
||||
|
||||
void DoFindDependencies(const std::vector<Document*>& docs)
|
||||
{ /* TODO */ }
|
||||
|
||||
void DoGenerate() const
|
||||
{ /* TODO */ }
|
||||
};
|
||||
|
||||
class FileAnalyzerTarget : public Target {
|
||||
public:
|
||||
|
||||
static Target* Instantiate(const std::string& name,
|
||||
const std::string& pattern)
|
||||
{ return new FileAnalyzerTarget(name, pattern); }
|
||||
|
||||
private:
|
||||
|
||||
FileAnalyzerTarget(const std::string& name, const std::string& pattern)
|
||||
: Target(name, pattern)
|
||||
{ }
|
||||
|
||||
void DoFindDependencies(const std::vector<Document*>& docs)
|
||||
{ /* TODO */ }
|
||||
|
||||
void DoGenerate() const
|
||||
{ /* TODO */ }
|
||||
};
|
||||
|
||||
class PackageTarget : public Target {
|
||||
public:
|
||||
|
||||
static Target* Instantiate(const std::string& name,
|
||||
const std::string& pattern)
|
||||
{ return new PackageTarget(name, pattern); }
|
||||
|
||||
private:
|
||||
|
||||
PackageTarget(const std::string& name, const std::string& pattern)
|
||||
: Target(name, pattern)
|
||||
{ }
|
||||
|
||||
void DoFindDependencies(const std::vector<Document*>& docs)
|
||||
{ /* TODO */ }
|
||||
|
||||
void DoGenerate() const
|
||||
{ /* TODO */ }
|
||||
};
|
||||
|
||||
class ScriptTarget : public Target {
|
||||
public:
|
||||
|
||||
static Target* Instantiate(const std::string& name,
|
||||
const std::string& pattern)
|
||||
{ return new ScriptTarget(name, pattern); }
|
||||
|
||||
private:
|
||||
|
||||
ScriptTarget(const std::string& name, const std::string& pattern)
|
||||
: Target(name, pattern)
|
||||
{ }
|
||||
|
||||
void DoFindDependencies(const std::vector<Document*>& docs)
|
||||
{ /* TODO */ }
|
||||
|
||||
void DoGenerate() const
|
||||
{ /* TODO */ }
|
||||
};
|
||||
|
||||
class IdentifierTarget : public Target {
|
||||
public:
|
||||
|
||||
static Target* Instantiate(const std::string& name,
|
||||
const std::string& pattern)
|
||||
{ return new IdentifierTarget(name, pattern); }
|
||||
|
||||
private:
|
||||
|
||||
IdentifierTarget(const std::string& name, const std::string& pattern)
|
||||
: Target(name, pattern)
|
||||
{ }
|
||||
|
||||
void DoFindDependencies(const std::vector<Document*>& docs);
|
||||
|
||||
void DoGenerate() const
|
||||
{ /* TODO */ }
|
||||
};
|
||||
|
||||
class Config {
|
||||
public:
|
||||
|
||||
Config(const std::string& file, const std::string& delim = "\t");
|
||||
|
||||
~Config();
|
||||
|
||||
void FindDependencies(const std::vector<Document*>& docs);
|
||||
|
||||
void GenerateDocs() const;
|
||||
|
||||
private:
|
||||
|
||||
typedef std::list<Target*> target_list;
|
||||
|
||||
target_list targets;
|
||||
};
|
||||
|
||||
|
||||
} // namespace broxygen
|
||||
|
||||
#endif
|
|
@ -48,11 +48,11 @@ IdentifierDocument::~IdentifierDocument()
|
|||
{
|
||||
Unref(id);
|
||||
|
||||
for ( RedefList::const_iterator it = redefs.begin(); it != redefs.end();
|
||||
for ( redef_list::const_iterator it = redefs.begin(); it != redefs.end();
|
||||
++it )
|
||||
delete *it;
|
||||
|
||||
for ( RecordFieldMap::const_iterator it = fields.begin();
|
||||
for ( record_field_map::const_iterator it = fields.begin();
|
||||
it != fields.end(); ++it )
|
||||
delete it->second;
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ string IdentifierDocument::GetComments() const
|
|||
|
||||
string IdentifierDocument::GetFieldComments(const string& field) const
|
||||
{
|
||||
RecordFieldMap::const_iterator it = fields.find(field);
|
||||
record_field_map::const_iterator it = fields.find(field);
|
||||
|
||||
if ( it == fields.end() )
|
||||
return string();
|
||||
|
|
|
@ -116,14 +116,14 @@ private:
|
|||
std::vector<std::string> comments;
|
||||
};
|
||||
|
||||
typedef std::list<Redefinition*> RedefList;
|
||||
typedef std::map<std::string, RecordField*> RecordFieldMap;
|
||||
typedef std::list<Redefinition*> redef_list;
|
||||
typedef std::map<std::string, RecordField*> record_field_map;
|
||||
|
||||
std::vector<std::string> comments;
|
||||
ID* id;
|
||||
string initial_val_desc;
|
||||
RedefList redefs;
|
||||
RecordFieldMap fields;
|
||||
redef_list redefs;
|
||||
record_field_map fields;
|
||||
RecordField* last_field_seen;
|
||||
};
|
||||
|
||||
|
|
|
@ -83,13 +83,13 @@ static string PrettifyParams(const string& s)
|
|||
return s;
|
||||
}
|
||||
|
||||
Manager::Manager(const string& config)
|
||||
Manager::Manager(const string& arg_config)
|
||||
: disabled(), comment_buffer(), comment_buffer_map(), packages(), scripts(),
|
||||
identifiers(), all_docs(), last_identifier_seen(), incomplete_type()
|
||||
identifiers(), all_docs(), last_identifier_seen(), incomplete_type(),
|
||||
config(arg_config)
|
||||
{
|
||||
if ( getenv("BRO_DISABLE_BROXYGEN") )
|
||||
disabled = true;
|
||||
// TODO config file stuff
|
||||
}
|
||||
|
||||
Manager::~Manager()
|
||||
|
@ -109,16 +109,16 @@ void Manager::InitPostScript()
|
|||
{
|
||||
if ( disabled )
|
||||
return;
|
||||
// TODO: dependency resolution stuff?
|
||||
|
||||
config.FindDependencies(all_docs);
|
||||
}
|
||||
|
||||
void Manager::GenerateDocs() const
|
||||
{
|
||||
if ( disabled )
|
||||
return;
|
||||
// TODO
|
||||
|
||||
// may be a no-op if no config file
|
||||
config.GenerateDocs();
|
||||
}
|
||||
|
||||
void Manager::File(const string& path)
|
||||
|
@ -214,7 +214,8 @@ IdentifierDocument* Manager::CreateIdentifierDoc(ID* id, ScriptDocument* script)
|
|||
rval->AddComments(comment_buffer);
|
||||
comment_buffer.clear();
|
||||
|
||||
CommentBufferMap::const_iterator it = comment_buffer_map.find(id->Name());
|
||||
comment_buffer_map_t::const_iterator it =
|
||||
comment_buffer_map.find(id->Name());
|
||||
|
||||
if ( it != comment_buffer_map.end() )
|
||||
{
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef BROXYGEN_MANAGER_H
|
||||
#define BROXYGEN_MANAGER_H
|
||||
|
||||
#include "Configuration.h"
|
||||
#include "Document.h"
|
||||
#include "ID.h"
|
||||
#include "Type.h"
|
||||
|
@ -16,15 +17,15 @@ namespace broxygen {
|
|||
|
||||
template<class T>
|
||||
struct DocumentMap {
|
||||
typedef std::map<std::string, T*> MapType;
|
||||
typedef std::map<std::string, T*> map_type;
|
||||
|
||||
T* GetDocument(const std::string& name) const
|
||||
{
|
||||
typename MapType::const_iterator it = map.find(name);
|
||||
typename map_type::const_iterator it = map.find(name);
|
||||
return it == map.end() ? 0 : it->second;
|
||||
}
|
||||
|
||||
MapType map;
|
||||
map_type map;
|
||||
};
|
||||
|
||||
class Manager {
|
||||
|
@ -75,20 +76,21 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
typedef std::vector<std::string> CommentBuffer;
|
||||
typedef std::map<std::string, CommentBuffer> CommentBufferMap;
|
||||
typedef std::vector<std::string> comment_buffer_t;
|
||||
typedef std::map<std::string, comment_buffer_t> comment_buffer_map_t;
|
||||
|
||||
IdentifierDocument* CreateIdentifierDoc(ID* id, ScriptDocument* script);
|
||||
|
||||
bool disabled;
|
||||
CommentBuffer comment_buffer; // For whatever next identifier that comes in.
|
||||
CommentBufferMap comment_buffer_map; // For a particular identifier.
|
||||
comment_buffer_t comment_buffer; // For whatever next identifier that comes in.
|
||||
comment_buffer_map_t comment_buffer_map; // For a particular identifier.
|
||||
DocumentMap<PackageDocument> packages;
|
||||
DocumentMap<ScriptDocument> scripts;
|
||||
DocumentMap<IdentifierDocument> identifiers;
|
||||
std::vector<Document*> all_docs;
|
||||
IdentifierDocument* last_identifier_seen;
|
||||
IdentifierDocument* incomplete_type;
|
||||
Config config;
|
||||
};
|
||||
|
||||
} // namespace broxygen
|
||||
|
|
|
@ -996,8 +996,8 @@ string flatten_script_name(const string& name, const string& prefix)
|
|||
return rval;
|
||||
}
|
||||
|
||||
static vector<string>* tokenize_string(string input, const string& delim,
|
||||
vector<string>* rval)
|
||||
vector<string>* tokenize_string(string input, const string& delim,
|
||||
vector<string>* rval)
|
||||
{
|
||||
if ( ! rval )
|
||||
rval = new vector<string>();
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -105,6 +106,10 @@ std::string extract_ip_and_len(const std::string& i, int* len);
|
|||
std::string get_unescaped_string(const std::string& str);
|
||||
std::string get_escaped_string(const std::string& str, bool escape_all);
|
||||
|
||||
std::vector<std::string>* tokenize_string(std::string input,
|
||||
const std::string& delim,
|
||||
std::vector<std::string>* rval = 0);
|
||||
|
||||
extern char* copy_string(const char* s);
|
||||
extern int streq(const char* s1, const char* s2);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue