diff options
author | An-Cheng Huang <ancheng@vyatta.com> | 2010-11-12 19:12:53 -0800 |
---|---|---|
committer | An-Cheng Huang <ancheng@vyatta.com> | 2010-11-12 19:12:53 -0800 |
commit | 79a94470b0f3fd4f7924bb096c61b8e064b65750 (patch) | |
tree | 049225edbd21f873b9a4bcac6571603a35aa1e89 | |
parent | e08c1879028ddd3b594b01c82859f8431894f497 (diff) | |
download | vyatta-cfg-79a94470b0f3fd4f7924bb096c61b8e064b65750.tar.gz vyatta-cfg-79a94470b0f3fd4f7924bb096c61b8e064b65750.zip |
initial work to parse config file into data structure.
-rw-r--r-- | src/cnode/cnode-algorithm.cpp | 12 | ||||
-rw-r--r-- | src/cnode/cnode.cpp | 83 | ||||
-rw-r--r-- | src/cnode/cnode.hpp | 5 | ||||
-rw-r--r-- | src/cparse/cparse.hpp | 5 | ||||
-rw-r--r-- | src/cparse/cparse.ypp | 117 | ||||
-rw-r--r-- | src/cparse/cparse_lex.l | 24 |
6 files changed, 211 insertions, 35 deletions
diff --git a/src/cnode/cnode-algorithm.cpp b/src/cnode/cnode-algorithm.cpp index d1101d7..c830ce4 100644 --- a/src/cnode/cnode-algorithm.cpp +++ b/src/cnode/cnode-algorithm.cpp @@ -260,7 +260,8 @@ _diff_show_other(CfgNode *cfg1, CfgNode *cfg2, int level, bool show_def, * (3) has a "name". */ const string& name = cfg->getName(); - bool print_this = (((cfg1 && !cfg1->isTag()) || (cfg2 && !cfg2->isTag())) + bool print_this = (((cfg1 && (!cfg1->isTag() || cfg1->isValue())) + || (cfg2 && (!cfg2->isTag() || cfg2->isValue()))) && level >= 0 && name.size() > 0); if (print_this) { _diff_print_comment(cfg1, cfg2, level); @@ -288,13 +289,15 @@ _diff_show_other(CfgNode *cfg1, CfgNode *cfg2, int level, bool show_def, Cstore::MapT<string, CfgNode *> nmap1, nmap2; for (size_t i = 0; i < cnodes1.size(); i++) { string key - = (cfg->isTag() ? cnodes1[i]->getValue() : cnodes1[i]->getName()); + = ((cfg->isTag() && !cfg->isValue()) + ? cnodes1[i]->getValue() : cnodes1[i]->getName()); map[key] = true; nmap1[key] = cnodes1[i]; } for (size_t i = 0; i < cnodes2.size(); i++) { string key - = (cfg->isTag() ? cnodes2[i]->getValue() : cnodes2[i]->getName()); + = ((cfg->isTag() && !cfg->isValue()) + ? cnodes2[i]->getValue() : cnodes2[i]->getName()); map[key] = true; nmap2[key] = cnodes2[i]; } @@ -312,7 +315,8 @@ _diff_show_other(CfgNode *cfg1, CfgNode *cfg2, int level, bool show_def, CfgNode *c1 = (in1 ? nmap1[cnodes[i]] : NULL); CfgNode *c2 = (in2 ? nmap2[cnodes[i]] : NULL); - int next_level = (cfg->isTag() ? ((level >= 0) ? level : 0) : (level + 1)); + int next_level = ((cfg->isTag() && !cfg->isValue()) + ? ((level >= 0) ? level : 0) : (level + 1)); _show_diff(c1, c2, next_level, show_def, hide_secret); } diff --git a/src/cnode/cnode.cpp b/src/cnode/cnode.cpp index 2948a14..0f6976d 100644 --- a/src/cnode/cnode.cpp +++ b/src/cnode/cnode.cpp @@ -26,11 +26,82 @@ using namespace std; using namespace cnode; +/* XXX + from cstore: extra level for tag node + delayed processing for _is_empty, _is_leaf_typeless + */ + ////// constructors/destructors +CfgNode::CfgNode(vector<string>& path_comps, char *name, char *val, + char *comment, int deact, Cstore *cstore) + : _is_tag(false), _is_leaf(false), _is_multi(false), _is_value(false), + _is_default(false), _is_deactivated(false), _is_leaf_typeless(false), + _is_invalid(false), _is_empty(false) +{ + if (name && name[0]) { + // name must be non-empty + path_comps.push_back(name); + } + if (val) { + // value could be empty + path_comps.push_back(val); + } + + while (1) { + if (path_comps.size() == 0) { + // nothing to do for root node + break; + } + + vtw_def def; + if (cstore->validateTmplPath(path_comps, false, def)) { + // got the def + _is_value = def.is_value; + _is_tag = def.tag; + _is_leaf = (!def.tag && def.def_type != ERROR_TYPE); + _is_multi = def.multi; + + /* XXX given the current definition of "default", the concept of + * "default" doesn't really apply to config files. + */ + _is_default = false; + _is_deactivated = deact; + if (name) { + _name = name; + } + if (val) { + if (_is_multi) { + _values.push_back(val); + } else { + _value = val; + } + } + if (comment) { + _comment = comment; + } + // ignore return + } else { + // not a valid node + _is_invalid = true; + break; + } + + break; + } + + // restore path_comps + if (val) { + path_comps.pop_back(); + } + if (name && name[0]) { + path_comps.pop_back(); + } +} + CfgNode::CfgNode(Cstore& cstore, vector<string>& path_comps, bool active, bool recursive) : _is_tag(false), _is_leaf(false), _is_multi(false), _is_value(false), - _is_default(false), _is_deactivated(false), _is_leaf_typeless(false), + _is_default(false), _is_deactivated(false), _is_leaf_typeless(false), _is_invalid(false), _is_empty(false) { /* first get the def (only if path is not empty). if path is empty, i.e., @@ -41,17 +112,17 @@ CfgNode::CfgNode(Cstore& cstore, vector<string>& path_comps, if (cstore.validateTmplPath(path_comps, false, def)) { // got the def _is_value = def.is_value; - _is_tag = (def.tag && !_is_value); - _is_leaf = (!_is_tag && !_is_value && def.def_type != ERROR_TYPE); - _is_multi = (_is_leaf && def.multi); + _is_tag = def.tag; + _is_leaf = (!def.tag && def.def_type != ERROR_TYPE); + _is_multi = def.multi; _is_default = cstore.cfgPathDefault(path_comps, active); _is_deactivated = cstore.cfgPathDeactivated(path_comps, active); cstore.cfgPathGetComment(path_comps, _comment, active); // ignore return if (_is_leaf && _is_value) { - /* recursion should never reach here. if path is specified by user, - * nothing further to do. + /* "leaf value" so recursion should never reach here. if path is + * specified by user, nothing further to do. */ return; } diff --git a/src/cnode/cnode.hpp b/src/cnode/cnode.hpp index 0be02ca..aab2d4d 100644 --- a/src/cnode/cnode.hpp +++ b/src/cnode/cnode.hpp @@ -25,6 +25,8 @@ namespace cnode { class CfgNode { public: + CfgNode(vector<string>& path_comps, char *name, char *val, char *comment, + int deact, Cstore *cstore); CfgNode(Cstore& cstore, std::vector<string>& path_comps, bool active = false, bool recursive = true); ~CfgNode() {}; @@ -45,6 +47,9 @@ public: const std::string& getComment() const { return _comment; } const std::vector<CfgNode *>& getChildNodes() const { return _child_nodes; } + void addMultiValue(char *val) { _values.push_back(val); } + void addChildNode(CfgNode *cnode) { _child_nodes.push_back(cnode); } + private: bool _is_tag; bool _is_leaf; diff --git a/src/cparse/cparse.hpp b/src/cparse/cparse.hpp index 478af7b..0729416 100644 --- a/src/cparse/cparse.hpp +++ b/src/cparse/cparse.hpp @@ -17,9 +17,12 @@ #ifndef _CPARSE_HPP_ #define _CPARSE_HPP_ +#include <cstore/cstore.hpp> +#include <cnode/cnode.hpp> + namespace cparse { -int parse_file(FILE *fin); +int parse_file(FILE *fin, Cstore& cs); } // namespace cparse diff --git a/src/cparse/cparse.ypp b/src/cparse/cparse.ypp index eb2ab12..193077a 100644 --- a/src/cparse/cparse.ypp +++ b/src/cparse/cparse.ypp @@ -1,9 +1,16 @@ %{ #include <cstdio> +#include <vector> +#include <string> +#include <cstore/cstore.hpp> +#include <cnode/cnode.hpp> #include "cparse.hpp" #include "cparse_def.h" +using namespace std; +using namespace cnode; + // stuff from lex extern "C" { extern int cparse_lineno; @@ -19,33 +26,86 @@ cparse_error(const char *s) s, cparse_lineno, cparse_text); } -int level = 0; -int ndeact = 0; -char *ncomment = NULL; -char *nname = NULL; -char *nval = NULL; +static int ndeact = 0; +static char *ncomment = NULL; +static char *nname = NULL; +static char *nval = NULL; + +static Cstore *cstore = NULL; +static CfgNode *cur_node = NULL; +static CfgNode *cur_parent = NULL; +static CfgNode *prev_sibling = NULL; +static vector<CfgNode *> cur_path; +static vector<string> pcomps; +static vector<bool> pcomp_is_value; static void -print_node() +print_path() { - int i = 0; - if (ncomment) { - for (i = 0; i <= level; i++) { - printf(" "); + printf("[%p,%p] p[", cur_parent, cur_node); + for (size_t i = 0; i < pcomps.size(); i++) { + if (i > 0) { + printf(","); } - printf(" /*%s*/\n", ncomment); - } - printf("%s", ndeact ? "!" : " "); - for (i = 0; i <= level; i++) { - printf(" "); + printf("%s", pcomps[i].c_str()); } - printf("%s", nname); + printf("] n[%s]", nname); if (nval) { - printf(" '%s'", nval); + printf(" v[%s]", nval); + } + if (ncomment) { + printf(" c[%s]", ncomment); + } + if (ndeact) { + printf(" D"); } printf("\n"); } +static void +add_node() +{ + if (prev_sibling && nval + && prev_sibling->isValue() && prev_sibling->isMulti() + && prev_sibling->getName() == nname) { + prev_sibling->addMultiValue(nval); + } else { + cur_node = new CfgNode(pcomps, nname, nval, ncomment, ndeact, cstore); + cur_parent->addChildNode(cur_node); + prev_sibling = cur_node; + } +} + +static void +go_down() +{ + cur_path.push_back(cur_parent); + cur_parent = cur_node; + prev_sibling = NULL; + + pcomps.push_back(nname); + pcomp_is_value.push_back(false); + if (nval) { + pcomps.push_back(nval); + pcomp_is_value.push_back(true); + } +} + +static void +go_up() +{ + cur_parent = cur_path.back(); + cur_path.pop_back(); + prev_sibling = NULL; + + if (pcomp_is_value.back()) { + pcomps.pop_back(); + pcomp_is_value.pop_back(); + } + pcomps.pop_back(); + pcomp_is_value.pop_back(); +} + %} %token NODE @@ -62,15 +122,27 @@ input: forest ; forest: /* empty */ - | forest tree + | forest { + if (!cur_parent) { + // root node + cur_parent = new CfgNode(pcomps, nname, nval, ncomment, + ndeact, cstore); + } + } tree ; tree: node { - print_node(); + add_node(); + print_path(); } | node { - print_node(); - } LEFTB { ++level; } forest RIGHTB { --level; } + add_node(); + print_path(); + } LEFTB { + go_down(); + } forest RIGHTB { + go_up(); + } ; node: nodec { @@ -100,9 +172,10 @@ comment: COMMENT %% int -cparse::parse_file(FILE *fin) +cparse::parse_file(FILE *fin, Cstore& cs) { cparse_set_in(fin); + cstore = &cs; return cparse_parse(); } diff --git a/src/cparse/cparse_lex.l b/src/cparse/cparse_lex.l index 167e2af..1afe886 100644 --- a/src/cparse/cparse_lex.l +++ b/src/cparse/cparse_lex.l @@ -9,6 +9,9 @@ ID ([-[:alnum:]_]+) SPACE ([[:space:]]{-}[\n]) %{ +/* get rid of compiler warning */ +#define YY_NO_INPUT 1 + #include <string.h> #include "cparse_def.h" #include "cparse.h" @@ -80,8 +83,21 @@ set_ret_str() } <sComment>"*/" { + char *tmp; + size_t tlen; set_ret_str(); - cparse_lval.str = strdup(out_buf); + + /* need to strip out leading or trailing space */ + tmp = out_buf; + tlen = strlen(tmp); + if (tlen > 0 && tmp[tlen - 1] == ' ') { + tmp[tlen - 1] = 0; + --tlen; + } + if (tlen > 0 && tmp[0] == ' ') { + ++tmp; + } + cparse_lval.str = strdup(tmp); BEGIN(INITIAL); return COMMENT; } @@ -90,7 +106,11 @@ set_ret_str() node_deactivated = 1; } -<INITIAL>[[:space:]]+ { +<INITIAL>{SPACE}+ { +} + +<INITIAL>\n { + ++cparse_lineno; } <INITIAL>\} { |