diff --git a/src/broxygen/CMakeLists.txt b/src/broxygen/CMakeLists.txt index c447ea9188..4e5c5e5d0d 100644 --- a/src/broxygen/CMakeLists.txt +++ b/src/broxygen/CMakeLists.txt @@ -6,8 +6,9 @@ include_directories(BEFORE ) set(broxygen_SRCS - Manager.cc + Configuration.cc Document.cc + Manager.cc ) bif_target(broxygen.bif) diff --git a/src/broxygen/Configuration.cc b/src/broxygen/Configuration.cc new file mode 100644 index 0000000000..cd8ee7be56 --- /dev/null +++ b/src/broxygen/Configuration.cc @@ -0,0 +1,123 @@ +#include "Configuration.h" + +#include "util.h" +#include "Reporter.h" + +#include +#include +#include +#include + +using namespace broxygen; +using namespace std; + +typedef map 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 +void filter_matching_docs(const std::vector& filter_from, Target* t) + { + for ( size_t i = 0; i < filter_from.size(); ++i ) + { + T* d = dynamic_cast(filter_from[i]); + + if ( ! d ) + continue; + + if ( t->MatchesPattern(d) ) + t->AddDependency(d); + } + } + +void IdentifierTarget::DoFindDependencies(const std::vector& docs) + { + filter_matching_docs(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 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& 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(); + } diff --git a/src/broxygen/Configuration.h b/src/broxygen/Configuration.h new file mode 100644 index 0000000000..2aef6f9806 --- /dev/null +++ b/src/broxygen/Configuration.h @@ -0,0 +1,169 @@ +#ifndef BROXYGEN_CONFIGURATION_H +#define BROXYGEN_CONFIGURATION_H + +#include "Document.h" + +#include +#include +#include + +namespace broxygen { + +// TODO: documentation... + +class Target { +public: + + typedef Target* (*factory_fn)(const std::string&, const std::string&); + + virtual ~Target() { } + + void FindDependencies(const std::vector& 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 dependencies; + +private: + + virtual void DoFindDependencies(const std::vector& 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& 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& 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& 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& 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& docs); + + void DoGenerate() const + { /* TODO */ } +}; + +class Config { +public: + + Config(const std::string& file, const std::string& delim = "\t"); + + ~Config(); + + void FindDependencies(const std::vector& docs); + + void GenerateDocs() const; + +private: + + typedef std::list target_list; + + target_list targets; +}; + + +} // namespace broxygen + +#endif diff --git a/src/broxygen/Document.cc b/src/broxygen/Document.cc index 41622aa41f..dbac11f234 100644 --- a/src/broxygen/Document.cc +++ b/src/broxygen/Document.cc @@ -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(); diff --git a/src/broxygen/Document.h b/src/broxygen/Document.h index fae3073ef9..ec9212bfba 100644 --- a/src/broxygen/Document.h +++ b/src/broxygen/Document.h @@ -116,14 +116,14 @@ private: std::vector comments; }; - typedef std::list RedefList; - typedef std::map RecordFieldMap; + typedef std::list redef_list; + typedef std::map record_field_map; std::vector comments; ID* id; string initial_val_desc; - RedefList redefs; - RecordFieldMap fields; + redef_list redefs; + record_field_map fields; RecordField* last_field_seen; }; diff --git a/src/broxygen/Manager.cc b/src/broxygen/Manager.cc index 72ef0aab1e..707481d86a 100644 --- a/src/broxygen/Manager.cc +++ b/src/broxygen/Manager.cc @@ -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() ) { diff --git a/src/broxygen/Manager.h b/src/broxygen/Manager.h index 4207c14630..67f7e543af 100644 --- a/src/broxygen/Manager.h +++ b/src/broxygen/Manager.h @@ -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 struct DocumentMap { - typedef std::map MapType; + typedef std::map 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 CommentBuffer; - typedef std::map CommentBufferMap; + typedef std::vector comment_buffer_t; + typedef std::map 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 packages; DocumentMap scripts; DocumentMap identifiers; std::vector all_docs; IdentifierDocument* last_identifier_seen; IdentifierDocument* incomplete_type; + Config config; }; } // namespace broxygen diff --git a/src/util.cc b/src/util.cc index eacbf46eb7..8f85d6fca4 100644 --- a/src/util.cc +++ b/src/util.cc @@ -996,8 +996,8 @@ string flatten_script_name(const string& name, const string& prefix) return rval; } -static vector* tokenize_string(string input, const string& delim, - vector* rval) +vector* tokenize_string(string input, const string& delim, + vector* rval) { if ( ! rval ) rval = new vector(); diff --git a/src/util.h b/src/util.h index 17dfb9c217..1dc47db68a 100644 --- a/src/util.h +++ b/src/util.h @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -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* tokenize_string(std::string input, + const std::string& delim, + std::vector* rval = 0); + extern char* copy_string(const char* s); extern int streq(const char* s1, const char* s2);