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:
Jon Siwek 2013-11-05 16:40:24 -06:00
parent 1fabbd441c
commit bdd359d58c
9 changed files with 325 additions and 24 deletions

View file

@ -6,8 +6,9 @@ include_directories(BEFORE
) )
set(broxygen_SRCS set(broxygen_SRCS
Manager.cc Configuration.cc
Document.cc Document.cc
Manager.cc
) )
bif_target(broxygen.bif) bif_target(broxygen.bif)

View 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();
}

View 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

View file

@ -48,11 +48,11 @@ IdentifierDocument::~IdentifierDocument()
{ {
Unref(id); Unref(id);
for ( RedefList::const_iterator it = redefs.begin(); it != redefs.end(); for ( redef_list::const_iterator it = redefs.begin(); it != redefs.end();
++it ) ++it )
delete *it; delete *it;
for ( RecordFieldMap::const_iterator it = fields.begin(); for ( record_field_map::const_iterator it = fields.begin();
it != fields.end(); ++it ) it != fields.end(); ++it )
delete it->second; delete it->second;
} }
@ -93,7 +93,7 @@ string IdentifierDocument::GetComments() const
string IdentifierDocument::GetFieldComments(const string& field) 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() ) if ( it == fields.end() )
return string(); return string();

View file

@ -116,14 +116,14 @@ private:
std::vector<std::string> comments; std::vector<std::string> comments;
}; };
typedef std::list<Redefinition*> RedefList; typedef std::list<Redefinition*> redef_list;
typedef std::map<std::string, RecordField*> RecordFieldMap; typedef std::map<std::string, RecordField*> record_field_map;
std::vector<std::string> comments; std::vector<std::string> comments;
ID* id; ID* id;
string initial_val_desc; string initial_val_desc;
RedefList redefs; redef_list redefs;
RecordFieldMap fields; record_field_map fields;
RecordField* last_field_seen; RecordField* last_field_seen;
}; };

View file

@ -83,13 +83,13 @@ static string PrettifyParams(const string& s)
return s; return s;
} }
Manager::Manager(const string& config) Manager::Manager(const string& arg_config)
: disabled(), comment_buffer(), comment_buffer_map(), packages(), scripts(), : 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") ) if ( getenv("BRO_DISABLE_BROXYGEN") )
disabled = true; disabled = true;
// TODO config file stuff
} }
Manager::~Manager() Manager::~Manager()
@ -109,16 +109,16 @@ void Manager::InitPostScript()
{ {
if ( disabled ) if ( disabled )
return; return;
// TODO: dependency resolution stuff?
config.FindDependencies(all_docs);
} }
void Manager::GenerateDocs() const void Manager::GenerateDocs() const
{ {
if ( disabled ) if ( disabled )
return; return;
// TODO
// may be a no-op if no config file config.GenerateDocs();
} }
void Manager::File(const string& path) void Manager::File(const string& path)
@ -214,7 +214,8 @@ IdentifierDocument* Manager::CreateIdentifierDoc(ID* id, ScriptDocument* script)
rval->AddComments(comment_buffer); rval->AddComments(comment_buffer);
comment_buffer.clear(); 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() ) if ( it != comment_buffer_map.end() )
{ {

View file

@ -1,6 +1,7 @@
#ifndef BROXYGEN_MANAGER_H #ifndef BROXYGEN_MANAGER_H
#define BROXYGEN_MANAGER_H #define BROXYGEN_MANAGER_H
#include "Configuration.h"
#include "Document.h" #include "Document.h"
#include "ID.h" #include "ID.h"
#include "Type.h" #include "Type.h"
@ -16,15 +17,15 @@ namespace broxygen {
template<class T> template<class T>
struct DocumentMap { struct DocumentMap {
typedef std::map<std::string, T*> MapType; typedef std::map<std::string, T*> map_type;
T* GetDocument(const std::string& name) const 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; return it == map.end() ? 0 : it->second;
} }
MapType map; map_type map;
}; };
class Manager { class Manager {
@ -75,20 +76,21 @@ public:
private: private:
typedef std::vector<std::string> CommentBuffer; typedef std::vector<std::string> comment_buffer_t;
typedef std::map<std::string, CommentBuffer> CommentBufferMap; typedef std::map<std::string, comment_buffer_t> comment_buffer_map_t;
IdentifierDocument* CreateIdentifierDoc(ID* id, ScriptDocument* script); IdentifierDocument* CreateIdentifierDoc(ID* id, ScriptDocument* script);
bool disabled; bool disabled;
CommentBuffer comment_buffer; // For whatever next identifier that comes in. comment_buffer_t comment_buffer; // For whatever next identifier that comes in.
CommentBufferMap comment_buffer_map; // For a particular identifier. comment_buffer_map_t comment_buffer_map; // For a particular identifier.
DocumentMap<PackageDocument> packages; DocumentMap<PackageDocument> packages;
DocumentMap<ScriptDocument> scripts; DocumentMap<ScriptDocument> scripts;
DocumentMap<IdentifierDocument> identifiers; DocumentMap<IdentifierDocument> identifiers;
std::vector<Document*> all_docs; std::vector<Document*> all_docs;
IdentifierDocument* last_identifier_seen; IdentifierDocument* last_identifier_seen;
IdentifierDocument* incomplete_type; IdentifierDocument* incomplete_type;
Config config;
}; };
} // namespace broxygen } // namespace broxygen

View file

@ -996,7 +996,7 @@ string flatten_script_name(const string& name, const string& prefix)
return rval; return rval;
} }
static vector<string>* tokenize_string(string input, const string& delim, vector<string>* tokenize_string(string input, const string& delim,
vector<string>* rval) vector<string>* rval)
{ {
if ( ! rval ) if ( ! rval )

View file

@ -17,6 +17,7 @@
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
#include <vector>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.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_unescaped_string(const std::string& str);
std::string get_escaped_string(const std::string& str, bool escape_all); 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 char* copy_string(const char* s);
extern int streq(const char* s1, const char* s2); extern int streq(const char* s1, const char* s2);