summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAn-Cheng Huang <ancheng@vyatta.com>2010-11-12 19:12:53 -0800
committerAn-Cheng Huang <ancheng@vyatta.com>2010-11-12 19:12:53 -0800
commit79a94470b0f3fd4f7924bb096c61b8e064b65750 (patch)
tree049225edbd21f873b9a4bcac6571603a35aa1e89 /src
parente08c1879028ddd3b594b01c82859f8431894f497 (diff)
downloadvyatta-cfg-79a94470b0f3fd4f7924bb096c61b8e064b65750.tar.gz
vyatta-cfg-79a94470b0f3fd4f7924bb096c61b8e064b65750.zip
initial work to parse config file into data structure.
Diffstat (limited to 'src')
-rw-r--r--src/cnode/cnode-algorithm.cpp12
-rw-r--r--src/cnode/cnode.cpp83
-rw-r--r--src/cnode/cnode.hpp5
-rw-r--r--src/cparse/cparse.hpp5
-rw-r--r--src/cparse/cparse.ypp117
-rw-r--r--src/cparse/cparse_lex.l24
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>\} {