From f4b8287436aeb0018ee70b3dc32241b212bda5e9 Mon Sep 17 00:00:00 2001 From: Matthew Williams Date: Sat, 4 Dec 2010 06:14:34 +0000 Subject: [PATCH 01/12] initial support for if blocks (no else) --- apps/dsm/DSMChartReader.cpp | 237 +++++++++++++++++++++++------------- apps/dsm/DSMChartReader.h | 6 +- apps/dsm/DSMStateEngine.cpp | 94 +++++++++----- apps/dsm/DSMStateEngine.h | 19 ++- 4 files changed, 229 insertions(+), 127 deletions(-) diff --git a/apps/dsm/DSMChartReader.cpp b/apps/dsm/DSMChartReader.cpp index 45b0a7ba..90c52f3e 100644 --- a/apps/dsm/DSMChartReader.cpp +++ b/apps/dsm/DSMChartReader.cpp @@ -43,7 +43,7 @@ bool DSMChartReader::is_wsp(const char c) { } bool DSMChartReader::is_snt(const char c) { - return c== ';' || c == '{' || c == '}'; + return c== ';' || c == '{' || c == '}' || c == '[' || c == ']'; } string DSMChartReader::getToken(string str, size_t& pos) { @@ -219,16 +219,44 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, stack.push_back(new DSMTransition()); continue; } - + if (stack.empty()) { if (token == ";") - continue; + continue; ERROR("Without context I do not understand '%s'\n", token.c_str()); return false; } DSMElement* stack_top = &(*stack.back()); + DSMConditionTree* ct = dynamic_cast(stack_top); + if (ct) { + if (token == "[") { + stack.push_back(new DSMConditionList()); + continue; + } + if (token == "{") { + stack.push_back(new ActionList(ActionList::AL_if)); + continue; + } + if (token == ";") { + stack.pop_back(); + ActionList* al = dynamic_cast(&(*stack.back())); + if (al) { + owner->transferElem(ct); + al->actions.push_back(ct); + DBG("Added DSMConditionTree to ActionList\n"); + } else { + ERROR("no ActionList for DSMConditionTree\n"); + delete al; + return false; + } + continue; + } + } + + + State* state = dynamic_cast(stack_top); if (state) { if (!state->name.length()) { @@ -237,6 +265,7 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, continue; } if (token == "enter") { + DBG("adding 'enter' actions for state '%s'\n", state->name.c_str()); stack.push_back(new ActionList(ActionList::AL_enter)); continue; } @@ -261,116 +290,150 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, continue; } - ActionList* al = dynamic_cast(stack_top); - if (al) { - if (token == ";") { - continue; + ActionList* al = dynamic_cast(stack_top); + if (al) { + if (token == ";") { + continue; + } + if (token == "{") { + continue; + } + + if ((token == "}") || (token == "->")) { + stack.pop_back(); + if (stack.empty()) { + ERROR("no item for action list\n"); + delete al; + return false; + } + + if (al->al_type == ActionList::AL_if || + al->al_type == ActionList::AL_else) { + DSMConditionTree* ct = dynamic_cast(&(*stack.back())); + if (!ct) { + ERROR("no DSMConditionTree for action list\n"); + delete al; + return false; + } + + if (al->al_type == ActionList::AL_if) { + ct->run_if_true = al->actions; + } else if (al->al_type == ActionList::AL_else) { + ct->run_if_false = al->actions; + } + } else if (al->al_type == ActionList::AL_enter || + al->al_type == ActionList::AL_exit) { + State* s = dynamic_cast(&(*stack.back())); + if (!s) { + ERROR("no State for action list\n"); + delete al; + return false; + } + + if (al->al_type == ActionList::AL_enter) { + s->pre_actions = al->actions; + } else if (al->al_type == ActionList::AL_exit) { + s->post_actions = al->actions; + } + } else if (al->al_type == ActionList::AL_trans) { + DSMTransition* t = dynamic_cast(&(*stack.back())); + if (!t) { + ERROR("no DSMTransition for action list\n"); + delete al; + return false; + } + t->actions = al->actions; + } else { + ERROR("internal: unknown transition list type\n"); + } + delete al; + continue; } - if (token == "{") { - continue; - } - if ((token == "}") || (token == "->")) { - stack.pop_back(); - if (stack.empty()) { - ERROR("no item for action list\n"); - delete al; - return false; - } - - if (al->al_type == ActionList::AL_enter || - al->al_type == ActionList::AL_exit) { - State* s = dynamic_cast(&(*stack.back())); - if (!s) { - ERROR("no State for action list\n"); - delete al; - return false; - } - if (al->al_type == ActionList::AL_enter) - s->pre_actions = al->actions; - else if (al->al_type == ActionList::AL_exit) - s->post_actions = al->actions; - } else if (al->al_type == ActionList::AL_trans) { - DSMTransition* t = dynamic_cast(&(*stack.back())); - if (!t) { - ERROR("no DSMTransition for action list\n"); - delete al; - return false; - } - t->actions = al->actions; - } else { - ERROR("internal: unknown transition list type\n"); - } - delete al; - continue; - } - - // token is action - // DBG("adding action '%s'\n", token.c_str()); - DSMAction* a = actionFromToken(token); - if (!a) - return false; - owner->transferElem(a); - al->actions.push_back(a); - continue; - } + + if (token == "if") { + //token is condition tree + stack.push_back(new DSMConditionTree()); + continue; + } else { + // token is action + DBG("adding action '%s'\n", token.c_str()); + + DSMAction* a = actionFromToken(token); + if (!a) + return false; + owner->transferElem(a); + al->actions.push_back(a); + continue; + } + } + DSMConditionList* cl = dynamic_cast(stack_top); if (cl) { if (token == ";") - continue; + continue; if ((token == "{") || (token == "}")) { - // readability - continue; + // readability + continue; } - if ((token == "/") || (token == "->")) { - // end of condition list - stack.pop_back(); - if (stack.empty()) { - ERROR("no transition to apply conditions to\n"); - delete cl; - return false; - } - DSMTransition* tr = dynamic_cast(&(*stack.back())); - if (!tr) { - ERROR("no transition to apply conditions to\n"); - delete cl; - return false; - } - - tr->precond = cl->conditions; - tr->is_exception = cl->is_exception; - delete cl; - - // start AL_trans action list - if (token == "/") { - stack.push_back(new ActionList(ActionList::AL_trans)); - } - continue; + if ((token == "/") || (token == "->") || (token == "]")) { + // end of condition list + stack.pop_back(); + if (stack.empty()) { + ERROR("nothing to apply conditions to\n"); + delete cl; + return false; + } + + DSMElement* el = &(*stack.back()); + + DSMTransition* tr = dynamic_cast(el); + DSMConditionTree* ct = dynamic_cast(el); + if (tr) { + tr->precond = cl->conditions; + tr->is_exception = cl->is_exception; + } else if (ct) { + ct->conditions = cl->conditions; + ct->is_exception = cl->is_exception; + } else { + ERROR("no transition or condition list to apply conditions to\n"); + delete cl; + return false; + } + + delete cl; + + // start AL_trans action list + if (token == "/") { + stack.push_back(new ActionList(ActionList::AL_trans)); + } + continue; } if (token == "not") { - cl->invert_next = !cl->invert_next; - continue; + cl->invert_next = !cl->invert_next; + continue; } if (token == "exception") { - cl->is_exception = true; - continue; + cl->is_exception = true; + continue; } - // DBG("new condition: '%s'\n", token.c_str()); + DBG("new condition: '%s'\n", token.c_str()); DSMCondition* c = conditionFromToken(token, cl->invert_next); cl->invert_next = false; if (!c) - return false; + return false; owner->transferElem(c); cl->conditions.push_back(c); continue; } + DSMTransition* tr = dynamic_cast(stack_top); if (tr) { if (!tr->name.length()) { diff --git a/apps/dsm/DSMChartReader.h b/apps/dsm/DSMChartReader.h index 1f663de6..b6dd48bc 100644 --- a/apps/dsm/DSMChartReader.h +++ b/apps/dsm/DSMChartReader.h @@ -57,7 +57,9 @@ class ActionList : public DSMElement { enum AL_type { AL_enter, AL_exit, - AL_trans + AL_trans, + AL_if, + AL_else }; AL_type al_type; @@ -65,7 +67,7 @@ class ActionList : public DSMElement { ActionList(AL_type al_type) : al_type(al_type) { } - vector actions; + vector actions; }; struct DSMConditionList : public DSMElement { diff --git a/apps/dsm/DSMStateEngine.cpp b/apps/dsm/DSMStateEngine.cpp index 4a17593a..053143d7 100644 --- a/apps/dsm/DSMStateEngine.cpp +++ b/apps/dsm/DSMStateEngine.cpp @@ -46,11 +46,11 @@ DSMStateDiagram::~DSMStateDiagram() { void DSMStateDiagram::addState(const State& state, bool is_initial) { DBG("adding state '%s'\n", state.name.c_str()); - for (vector::const_iterator it= + for (vector::const_iterator it= state.pre_actions.begin(); it != state.pre_actions.end(); it++) { DBG(" pre-action '%s'\n", (*it)->name.c_str()); } - for (vector::const_iterator it= + for (vector::const_iterator it= state.post_actions.begin(); it != state.post_actions.end(); it++) { DBG(" post-action '%s'\n", (*it)->name.c_str()); } @@ -75,7 +75,7 @@ bool DSMStateDiagram::addTransition(const DSMTransition& trans) { DBG(" DSMCondition %s'%s'\n", (*it)->invert?"not ":"", (*it)->name.c_str()); } - for (vector::const_iterator it= + for (vector::const_iterator it= trans.actions.begin(); it != trans.actions.end(); it++) { DBG(" Action '%s'\n", (*it)->name.c_str()); } @@ -224,42 +224,70 @@ void DSMStateEngine::onBeforeDestroy(DSMSession* sc_sess, AmSession* sess) { (*it)->onBeforeDestroy(sc_sess, sess); } -bool DSMStateEngine::runactions(vector::iterator from, - vector::iterator to, +bool DSMStateEngine::runactions(vector::iterator from, + vector::iterator to, AmSession* sess, DSMSession* sc_sess, DSMCondition::EventType event, map* event_params, bool& is_consumed) { // DBG("running %zd actions\n", to - from); - for (vector::iterator it=from; it != to; it++) { - DBG("executing '%s'\n", (*it)->name.c_str()); - if ((*it)->execute(sess, sc_sess, event, event_params)) { - string se_modifier; - switch ((*it)->getSEAction(se_modifier, - sess, sc_sess, event, event_params)) { - case DSMAction::Repost: - is_consumed = false; - break; - case DSMAction::Jump: - DBG("jumping to %s\n", se_modifier.c_str()); - if (jumpDiag(se_modifier, sess, sc_sess, event, event_params)) { - // is_consumed = false; - return true; - } break; - case DSMAction::Call: - DBG("calling %s\n", se_modifier.c_str()); - if (callDiag(se_modifier, sess, sc_sess, event, event_params)) { - // is_consumed = false; - return true; - } break; - case DSMAction::Return: - if (returnDiag(sess, sc_sess)) { - //is_consumed = false; - return true; - } break; - default: break; + for (vector::iterator it=from; it != to; it++) { + + DSMConditionTree* cond_tree = dynamic_cast(*it); + if (cond_tree) { + DBG("checking conditions\n"); + vector::iterator con=cond_tree->conditions.begin(); + while (con!=cond_tree->conditions.end()) { + if (!(*con)->_match(sess, sc_sess, event, event_params)) + break; + con++; + } + if (con == cond_tree->conditions.end()) { + DBG("condition tree matched.\n"); + if (runactions(cond_tree->run_if_true.begin(), cond_tree->run_if_true.end(), + sess, sc_sess, event, event_params, is_consumed)) + return true; + } else { + if(runactions(cond_tree->run_if_false.begin(), cond_tree->run_if_false.end(), + sess, sc_sess, event, event_params, is_consumed)) + return true; } } + + DSMAction* dsm_act = dynamic_cast(*it); + + if (dsm_act) { + DBG("executing '%s'\n", (dsm_act)->name.c_str()); + if ((dsm_act)->execute(sess, sc_sess, event, event_params)) { + string se_modifier; + switch ((dsm_act)->getSEAction(se_modifier, + sess, sc_sess, event, event_params)) { + case DSMAction::Repost: + is_consumed = false; + break; + case DSMAction::Jump: + DBG("jumping to %s\n", se_modifier.c_str()); + if (jumpDiag(se_modifier, sess, sc_sess, event, event_params)) { + // is_consumed = false; + return true; + } + break; + case DSMAction::Call: + DBG("calling %s\n", se_modifier.c_str()); + if (callDiag(se_modifier, sess, sc_sess, event, event_params)) { + // is_consumed = false; + return true; + } + break; + case DSMAction::Return: + if (returnDiag(sess, sc_sess)) { + //is_consumed = false; + return true; + } + break; + default: break; + } + } + } } - return false; } diff --git a/apps/dsm/DSMStateEngine.h b/apps/dsm/DSMStateEngine.h index fc1d8dfa..fde30f9d 100644 --- a/apps/dsm/DSMStateEngine.h +++ b/apps/dsm/DSMStateEngine.h @@ -141,8 +141,8 @@ class State public: State(); ~State(); - vector pre_actions; - vector post_actions; + vector pre_actions; + vector post_actions; vector transitions; }; @@ -154,13 +154,22 @@ class DSMTransition ~DSMTransition(); vector precond; - vector actions; + vector actions; string from_state; string to_state; bool is_exception; }; +class DSMConditionTree +: public DSMElement { + public: + vector conditions; + vector run_if_true; + vector run_if_false; + bool is_exception; +}; + class DSMModule; class DSMStateDiagram { @@ -224,8 +233,8 @@ class DSMStateEngine { DSMCondition::EventType event, map* event_params); bool returnDiag(AmSession* sess, DSMSession* sc_sess); - bool runactions(vector::iterator from, - vector::iterator to, + bool runactions(vector::iterator from, + vector::iterator to, AmSession* sess, DSMSession* sc_sess, DSMCondition::EventType event, map* event_params, bool& is_consumed); From be62fe1ca5eb72332c5a5c226e007837ba5c91ff Mon Sep 17 00:00:00 2001 From: Matthew Williams Date: Thu, 9 Dec 2010 21:58:49 +0000 Subject: [PATCH 02/12] implementation of functions in DSM --- apps/dsm/DSMChartReader.cpp | 113 +++++++++++++++++++++++++++++------- apps/dsm/DSMChartReader.h | 6 +- apps/dsm/DSMStateEngine.cpp | 2 +- apps/dsm/DSMStateEngine.h | 7 +++ 4 files changed, 106 insertions(+), 22 deletions(-) diff --git a/apps/dsm/DSMChartReader.cpp b/apps/dsm/DSMChartReader.cpp index 90c52f3e..0b54b186 100644 --- a/apps/dsm/DSMChartReader.cpp +++ b/apps/dsm/DSMChartReader.cpp @@ -32,6 +32,9 @@ #include using std::vector; +#include +using std::string; + DSMChartReader::DSMChartReader() { } @@ -128,6 +131,24 @@ DSMAction* DSMChartReader::actionFromToken(const string& str) { return NULL; } +DSMFunction* DSMChartReader::functionFromToken(const string& str) { + string cmd; + size_t b_pos = str.find('('); + if (b_pos != string::npos) { + cmd = str.substr(0, b_pos); + } else { + return NULL; + } + + for (vector::iterator it=funcs.begin(); it!= funcs.end(); it++) { + if((*it)->name == cmd) { + DBG("found function '%s' in fuction list\n", cmd.c_str()); + return *it; + } + } + return NULL; +} + DSMCondition* DSMChartReader::conditionFromToken(const string& str, bool invert) { for (vector::iterator it= mods.begin(); it!= mods.end(); it++) { @@ -205,6 +226,11 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, continue; } + if (token == "function") { + stack.push_back(new DSMFunction()); + continue; + } + if (token == "initial") { stack.push_back(new AttribInitial()); continue; @@ -229,6 +255,35 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, DSMElement* stack_top = &(*stack.back()); + DSMFunction* f = dynamic_cast(stack_top); + + if (f) { + if (f->name.length()==0) { + size_t b_pos = token.find('('); + if (b_pos != string::npos) { + f->name = token.substr(0, b_pos); + continue; + } else { + ERROR("Parse error -- function declarations must have a name followed by parentheses, e.g., 'function foo()'\n"); + return false; + } + } + + if (token == "{") { + stack.push_back(new ActionList(ActionList::AL_func)); + continue; + } + if (token == ";") { + owner->transferElem(f); + funcs.push_back(f); + DBG("Adding DSMFunction '%s' to funcs\n", f->name.c_str()); + continue; + } + + DBG("Unknown token: %s\n", token.c_str()); + return false; + } + DSMConditionTree* ct = dynamic_cast(stack_top); if (ct) { if (token == "[") { @@ -307,13 +362,21 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, return false; } - if (al->al_type == ActionList::AL_if || + if (al->al_type == ActionList::AL_func) { + DSMFunction* f = dynamic_cast(&(*stack.back())); + if (!f) { + ERROR("no DSMFunction for action list\n"); + delete al; + return false; + } + f->actions = al->actions; + } else if (al->al_type == ActionList::AL_if || al->al_type == ActionList::AL_else) { DSMConditionTree* ct = dynamic_cast(&(*stack.back())); if (!ct) { - ERROR("no DSMConditionTree for action list\n"); - delete al; - return false; + ERROR("no DSMConditionTree for action list\n"); + delete al; + return false; } if (al->al_type == ActionList::AL_if) { @@ -344,27 +407,37 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, } t->actions = al->actions; } else { - ERROR("internal: unknown transition list type\n"); + ERROR("internal: unknown transition list type\n"); } delete al; continue; } - if (token == "if") { - //token is condition tree - stack.push_back(new DSMConditionTree()); - continue; - } else { - // token is action - DBG("adding action '%s'\n", token.c_str()); - - DSMAction* a = actionFromToken(token); - if (!a) - return false; - owner->transferElem(a); - al->actions.push_back(a); - continue; - } + if (token == "if") { + //token is condition tree + stack.push_back(new DSMConditionTree()); + continue; + } else { + DSMFunction* f = functionFromToken(token); + if (f) { + DBG("adding actions from function '%s'\n", f->name.c_str()); + DBG("al.size is %zd before", al->actions.size()); + for (vector::iterator it=f->actions.begin(); it != f->actions.end(); it++) { + DSMElement* a = *it; + owner->transferElem(a); + al->actions.push_back(a); + } + DBG("al.size is %zd after", al->actions.size()); + } else { + DBG("adding action '%s'\n", token.c_str()); + DSMAction* a = actionFromToken(token); + if (!a) + return false; + owner->transferElem(a); + al->actions.push_back(a); + } + continue; + } } diff --git a/apps/dsm/DSMChartReader.h b/apps/dsm/DSMChartReader.h index b6dd48bc..03518775 100644 --- a/apps/dsm/DSMChartReader.h +++ b/apps/dsm/DSMChartReader.h @@ -59,7 +59,8 @@ class ActionList : public DSMElement { AL_exit, AL_trans, AL_if, - AL_else + AL_else, + AL_func }; AL_type al_type; @@ -83,6 +84,7 @@ class DSMChartReader { bool is_snt(const char c); string getToken(string str, size_t& pos); + DSMFunction* functionFromToken(const string& str); DSMAction* actionFromToken(const string& str); DSMCondition* conditionFromToken(const string& str, bool invert); @@ -90,6 +92,8 @@ class DSMChartReader { vector mods; DSMCoreModule core_mod; + vector funcs; + public: DSMChartReader(); ~DSMChartReader(); diff --git a/apps/dsm/DSMStateEngine.cpp b/apps/dsm/DSMStateEngine.cpp index 053143d7..e6cb64e6 100644 --- a/apps/dsm/DSMStateEngine.cpp +++ b/apps/dsm/DSMStateEngine.cpp @@ -228,7 +228,7 @@ bool DSMStateEngine::runactions(vector::iterator from, vector::iterator to, AmSession* sess, DSMSession* sc_sess, DSMCondition::EventType event, map* event_params, bool& is_consumed) { -// DBG("running %zd actions\n", to - from); + DBG("running %zd actions\n", to - from); for (vector::iterator it=from; it != to; it++) { DSMConditionTree* cond_tree = dynamic_cast(*it); diff --git a/apps/dsm/DSMStateEngine.h b/apps/dsm/DSMStateEngine.h index fde30f9d..a5fa6a76 100644 --- a/apps/dsm/DSMStateEngine.h +++ b/apps/dsm/DSMStateEngine.h @@ -170,6 +170,13 @@ class DSMConditionTree bool is_exception; }; +class DSMFunction +: public DSMElement { + public: + string name; + vector actions; +}; + class DSMModule; class DSMStateDiagram { From 3b67569f6973e280fab61b7b3cc87f882a560212 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Sun, 23 Jan 2011 01:48:31 +0100 Subject: [PATCH 03/12] reindent --- apps/dsm/DSMChartReader.cpp | 175 ++++++++++++++++++------------------ apps/dsm/DSMStateEngine.h | 24 ++--- 2 files changed, 99 insertions(+), 100 deletions(-) diff --git a/apps/dsm/DSMChartReader.cpp b/apps/dsm/DSMChartReader.cpp index 0b54b186..7069e18d 100644 --- a/apps/dsm/DSMChartReader.cpp +++ b/apps/dsm/DSMChartReader.cpp @@ -264,7 +264,8 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, f->name = token.substr(0, b_pos); continue; } else { - ERROR("Parse error -- function declarations must have a name followed by parentheses, e.g., 'function foo()'\n"); + ERROR("Parse error -- function declarations must have a name followed " + "by parentheses, e.g., 'function foo()'\n"); return false; } } @@ -285,7 +286,7 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, } DSMConditionTree* ct = dynamic_cast(stack_top); - if (ct) { + if (ct) { if (token == "[") { stack.push_back(new DSMConditionList()); continue; @@ -308,9 +309,7 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, } continue; } - } - - + } State* state = dynamic_cast(stack_top); if (state) { @@ -345,100 +344,100 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, continue; } - ActionList* al = dynamic_cast(stack_top); - if (al) { - if (token == ";") { - continue; - } - if (token == "{") { - continue; - } + ActionList* al = dynamic_cast(stack_top); + if (al) { + if (token == ";") { + continue; + } + if (token == "{") { + continue; + } - if ((token == "}") || (token == "->")) { + if ((token == "}") || (token == "->")) { stack.pop_back(); if (stack.empty()) { - ERROR("no item for action list\n"); - delete al; - return false; + ERROR("no item for action list\n"); + delete al; + return false; } - if (al->al_type == ActionList::AL_func) { - DSMFunction* f = dynamic_cast(&(*stack.back())); - if (!f) { - ERROR("no DSMFunction for action list\n"); - delete al; - return false; - } - f->actions = al->actions; - } else if (al->al_type == ActionList::AL_if || - al->al_type == ActionList::AL_else) { - DSMConditionTree* ct = dynamic_cast(&(*stack.back())); - if (!ct) { - ERROR("no DSMConditionTree for action list\n"); - delete al; - return false; - } + if (al->al_type == ActionList::AL_func) { + DSMFunction* f = dynamic_cast(&(*stack.back())); + if (!f) { + ERROR("no DSMFunction for action list\n"); + delete al; + return false; + } + f->actions = al->actions; + } else if (al->al_type == ActionList::AL_if || + al->al_type == ActionList::AL_else) { + DSMConditionTree* ct = dynamic_cast(&(*stack.back())); + if (!ct) { + ERROR("no DSMConditionTree for action list\n"); + delete al; + return false; + } - if (al->al_type == ActionList::AL_if) { - ct->run_if_true = al->actions; - } else if (al->al_type == ActionList::AL_else) { - ct->run_if_false = al->actions; + if (al->al_type == ActionList::AL_if) { + ct->run_if_true = al->actions; + } else if (al->al_type == ActionList::AL_else) { + ct->run_if_false = al->actions; } - } else if (al->al_type == ActionList::AL_enter || - al->al_type == ActionList::AL_exit) { - State* s = dynamic_cast(&(*stack.back())); - if (!s) { - ERROR("no State for action list\n"); - delete al; - return false; - } - - if (al->al_type == ActionList::AL_enter) { - s->pre_actions = al->actions; - } else if (al->al_type == ActionList::AL_exit) { - s->post_actions = al->actions; + } else if (al->al_type == ActionList::AL_enter || + al->al_type == ActionList::AL_exit) { + State* s = dynamic_cast(&(*stack.back())); + if (!s) { + ERROR("no State for action list\n"); + delete al; + return false; + } + + if (al->al_type == ActionList::AL_enter) { + s->pre_actions = al->actions; + } else if (al->al_type == ActionList::AL_exit) { + s->post_actions = al->actions; } } else if (al->al_type == ActionList::AL_trans) { - DSMTransition* t = dynamic_cast(&(*stack.back())); - if (!t) { - ERROR("no DSMTransition for action list\n"); - delete al; - return false; - } - t->actions = al->actions; - } else { - ERROR("internal: unknown transition list type\n"); - } - delete al; - continue; + DSMTransition* t = dynamic_cast(&(*stack.back())); + if (!t) { + ERROR("no DSMTransition for action list\n"); + delete al; + return false; + } + t->actions = al->actions; + } else { + ERROR("internal: unknown transition list type\n"); + } + delete al; + continue; } - if (token == "if") { - //token is condition tree - stack.push_back(new DSMConditionTree()); - continue; - } else { - DSMFunction* f = functionFromToken(token); - if (f) { - DBG("adding actions from function '%s'\n", f->name.c_str()); - DBG("al.size is %zd before", al->actions.size()); - for (vector::iterator it=f->actions.begin(); it != f->actions.end(); it++) { - DSMElement* a = *it; - owner->transferElem(a); - al->actions.push_back(a); - } - DBG("al.size is %zd after", al->actions.size()); - } else { - DBG("adding action '%s'\n", token.c_str()); - DSMAction* a = actionFromToken(token); - if (!a) - return false; - owner->transferElem(a); - al->actions.push_back(a); - } - continue; - } - } + if (token == "if") { + //token is condition tree + stack.push_back(new DSMConditionTree()); + continue; + } else { + DSMFunction* f = functionFromToken(token); + if (f) { + DBG("adding actions from function '%s'\n", f->name.c_str()); + DBG("al.size is %zd before", al->actions.size()); + for (vector::iterator it=f->actions.begin(); it != f->actions.end(); it++) { + DSMElement* a = *it; + owner->transferElem(a); + al->actions.push_back(a); + } + DBG("al.size is %zd after", al->actions.size()); + } else { + DBG("adding action '%s'\n", token.c_str()); + DSMAction* a = actionFromToken(token); + if (!a) + return false; + owner->transferElem(a); + al->actions.push_back(a); + } + continue; + } + } DSMConditionList* cl = dynamic_cast(stack_top); diff --git a/apps/dsm/DSMStateEngine.h b/apps/dsm/DSMStateEngine.h index a5fa6a76..c2150d42 100644 --- a/apps/dsm/DSMStateEngine.h +++ b/apps/dsm/DSMStateEngine.h @@ -136,7 +136,7 @@ class DSMAction class DSMTransition; -class State +class State : public DSMElement { public: State(); @@ -147,7 +147,7 @@ class State vector transitions; }; -class DSMTransition +class DSMTransition : public DSMElement { public: DSMTransition(); @@ -161,20 +161,20 @@ class DSMTransition bool is_exception; }; -class DSMConditionTree +class DSMConditionTree : public DSMElement { - public: - vector conditions; - vector run_if_true; - vector run_if_false; - bool is_exception; + public: + vector conditions; + vector run_if_true; + vector run_if_false; + bool is_exception; }; -class DSMFunction +class DSMFunction : public DSMElement { - public: - string name; - vector actions; + public: + string name; + vector actions; }; class DSMModule; From 3e563d335db201bd58c0d9f5b17c861fee329f58 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Sun, 23 Jan 2011 02:57:12 +0100 Subject: [PATCH 04/12] reindent --- apps/dsm/DSMStateEngine.cpp | 86 ++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/apps/dsm/DSMStateEngine.cpp b/apps/dsm/DSMStateEngine.cpp index e6cb64e6..1a20be66 100644 --- a/apps/dsm/DSMStateEngine.cpp +++ b/apps/dsm/DSMStateEngine.cpp @@ -231,62 +231,62 @@ bool DSMStateEngine::runactions(vector::iterator from, DBG("running %zd actions\n", to - from); for (vector::iterator it=from; it != to; it++) { - DSMConditionTree* cond_tree = dynamic_cast(*it); - if (cond_tree) { - DBG("checking conditions\n"); - vector::iterator con=cond_tree->conditions.begin(); - while (con!=cond_tree->conditions.end()) { - if (!(*con)->_match(sess, sc_sess, event, event_params)) - break; - con++; - } - if (con == cond_tree->conditions.end()) { - DBG("condition tree matched.\n"); + DSMConditionTree* cond_tree = dynamic_cast(*it); + if (cond_tree) { + DBG("checking conditions\n"); + vector::iterator con=cond_tree->conditions.begin(); + while (con!=cond_tree->conditions.end()) { + if (!(*con)->_match(sess, sc_sess, event, event_params)) + break; + con++; + } + if (con == cond_tree->conditions.end()) { + DBG("condition tree matched.\n"); if (runactions(cond_tree->run_if_true.begin(), cond_tree->run_if_true.end(), - sess, sc_sess, event, event_params, is_consumed)) - return true; + sess, sc_sess, event, event_params, is_consumed)) + return true; } else { if(runactions(cond_tree->run_if_false.begin(), cond_tree->run_if_false.end(), - sess, sc_sess, event, event_params, is_consumed)) - return true; + sess, sc_sess, event, event_params, is_consumed)) + return true; } } - DSMAction* dsm_act = dynamic_cast(*it); + DSMAction* dsm_act = dynamic_cast(*it); if (dsm_act) { DBG("executing '%s'\n", (dsm_act)->name.c_str()); if ((dsm_act)->execute(sess, sc_sess, event, event_params)) { string se_modifier; switch ((dsm_act)->getSEAction(se_modifier, - sess, sc_sess, event, event_params)) { - case DSMAction::Repost: - is_consumed = false; - break; - case DSMAction::Jump: - DBG("jumping to %s\n", se_modifier.c_str()); - if (jumpDiag(se_modifier, sess, sc_sess, event, event_params)) { - // is_consumed = false; - return true; - } - break; - case DSMAction::Call: - DBG("calling %s\n", se_modifier.c_str()); - if (callDiag(se_modifier, sess, sc_sess, event, event_params)) { - // is_consumed = false; - return true; - } - break; - case DSMAction::Return: - if (returnDiag(sess, sc_sess)) { - //is_consumed = false; - return true; - } - break; - default: break; - } + sess, sc_sess, event, event_params)) { + case DSMAction::Repost: + is_consumed = false; + break; + case DSMAction::Jump: + DBG("jumping to %s\n", se_modifier.c_str()); + if (jumpDiag(se_modifier, sess, sc_sess, event, event_params)) { + // is_consumed = false; + return true; + } + break; + case DSMAction::Call: + DBG("calling %s\n", se_modifier.c_str()); + if (callDiag(se_modifier, sess, sc_sess, event, event_params)) { + // is_consumed = false; + return true; + } + break; + case DSMAction::Return: + if (returnDiag(sess, sc_sess)) { + //is_consumed = false; + return true; + } + break; + default: break; + } } - } + } } return false; } From b12da91f642bd0ee187547016f648a7b2f8024cc Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Sun, 23 Jan 2011 03:00:06 +0100 Subject: [PATCH 05/12] dsm: execution reordered (small optimization) --- apps/dsm/DSMStateEngine.cpp | 46 ++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/apps/dsm/DSMStateEngine.cpp b/apps/dsm/DSMStateEngine.cpp index 1a20be66..47295f1d 100644 --- a/apps/dsm/DSMStateEngine.cpp +++ b/apps/dsm/DSMStateEngine.cpp @@ -228,32 +228,10 @@ bool DSMStateEngine::runactions(vector::iterator from, vector::iterator to, AmSession* sess, DSMSession* sc_sess, DSMCondition::EventType event, map* event_params, bool& is_consumed) { - DBG("running %zd actions\n", to - from); + DBG("running %zd DSM action elements\n", to - from); for (vector::iterator it=from; it != to; it++) { - DSMConditionTree* cond_tree = dynamic_cast(*it); - if (cond_tree) { - DBG("checking conditions\n"); - vector::iterator con=cond_tree->conditions.begin(); - while (con!=cond_tree->conditions.end()) { - if (!(*con)->_match(sess, sc_sess, event, event_params)) - break; - con++; - } - if (con == cond_tree->conditions.end()) { - DBG("condition tree matched.\n"); - if (runactions(cond_tree->run_if_true.begin(), cond_tree->run_if_true.end(), - sess, sc_sess, event, event_params, is_consumed)) - return true; - } else { - if(runactions(cond_tree->run_if_false.begin(), cond_tree->run_if_false.end(), - sess, sc_sess, event, event_params, is_consumed)) - return true; - } - } - DSMAction* dsm_act = dynamic_cast(*it); - if (dsm_act) { DBG("executing '%s'\n", (dsm_act)->name.c_str()); if ((dsm_act)->execute(sess, sc_sess, event, event_params)) { @@ -287,6 +265,28 @@ bool DSMStateEngine::runactions(vector::iterator from, } } } + + DSMConditionTree* cond_tree = dynamic_cast(*it); + if (cond_tree) { + DBG("checking conditions\n"); + vector::iterator con=cond_tree->conditions.begin(); + while (con!=cond_tree->conditions.end()) { + if (!(*con)->_match(sess, sc_sess, event, event_params)) + break; + con++; + } + if (con == cond_tree->conditions.end()) { + DBG("condition tree matched.\n"); + if (runactions(cond_tree->run_if_true.begin(), cond_tree->run_if_true.end(), + sess, sc_sess, event, event_params, is_consumed)) + return true; + } else { + if(runactions(cond_tree->run_if_false.begin(), cond_tree->run_if_false.end(), + sess, sc_sess, event, event_params, is_consumed)) + return true; + } + } + } return false; } From d90e76a7d3a977519b02cf0027cb6a3527ce6766 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Sun, 23 Jan 2011 04:13:17 +0100 Subject: [PATCH 06/12] DSM: "for (x in array)" and "for (k,v in struct)" Development sponsored by TelTech Systems Inc. --- apps/dsm/DSMChartReader.cpp | 126 ++++++++++++++++++++++++++++++------ apps/dsm/DSMChartReader.h | 6 +- apps/dsm/DSMStateEngine.cpp | 97 +++++++++++++++++++++++++++ apps/dsm/DSMStateEngine.h | 9 +++ 4 files changed, 218 insertions(+), 20 deletions(-) diff --git a/apps/dsm/DSMChartReader.cpp b/apps/dsm/DSMChartReader.cpp index 7069e18d..94c89540 100644 --- a/apps/dsm/DSMChartReader.cpp +++ b/apps/dsm/DSMChartReader.cpp @@ -26,6 +26,7 @@ */ #include "DSMChartReader.h" #include "log.h" +#include "AmUtils.h" #include // dlopen & friends @@ -149,6 +150,39 @@ DSMFunction* DSMChartReader::functionFromToken(const string& str) { return NULL; } +bool DSMChartReader::forFromToken(DSMArrayFor& af, const string& token) { + string forhdr = token; + if (forhdr.length() < 2 || forhdr[0] != '(' || forhdr[forhdr.length()-1] != ')') { + ERROR("syntax error in 'for %s': expected 'for (x in array)'\n", + forhdr.c_str()); + return false; + } + forhdr = forhdr.substr(1, forhdr.length()-2); + // q&d + vector forh_v = explode(forhdr, " in "); + if (forh_v.size() != 2) { + ERROR("syntax error in 'for %s': expected 'for (x in array)' " + "or 'for (k,v in struct)'\n", + forhdr.c_str()); + return false; + } + + af.array_struct = forh_v[1]; + + vector kv = explode(forh_v[0], ","); + if (kv.size() == 2) { + af.k = kv[0]; + af.v = kv[1]; + DBG("for (%s,%s in %s) {\n", af.k.c_str(), af.v.c_str(), af.array_struct.c_str()); + } else { + af.k = forh_v[0]; + DBG("for (%s in %s) {\n", af.k.c_str(), af.array_struct.c_str()); + } + + + return true; +} + DSMCondition* DSMChartReader::conditionFromToken(const string& str, bool invert) { for (vector::iterator it= mods.begin(); it!= mods.end(); it++) { @@ -245,7 +279,7 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, stack.push_back(new DSMTransition()); continue; } - + if (stack.empty()) { if (token == ";") continue; @@ -288,27 +322,27 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, DSMConditionTree* ct = dynamic_cast(stack_top); if (ct) { if (token == "[") { - stack.push_back(new DSMConditionList()); - continue; - } + stack.push_back(new DSMConditionList()); + continue; + } if (token == "{") { stack.push_back(new ActionList(ActionList::AL_if)); continue; } - if (token == ";") { - stack.pop_back(); - ActionList* al = dynamic_cast(&(*stack.back())); - if (al) { - owner->transferElem(ct); - al->actions.push_back(ct); - DBG("Added DSMConditionTree to ActionList\n"); - } else { - ERROR("no ActionList for DSMConditionTree\n"); - delete al; - return false; - } + if (token == ";") { + stack.pop_back(); + ActionList* al = dynamic_cast(&(*stack.back())); + if (al) { + owner->transferElem(ct); + al->actions.push_back(ct); + DBG("Added DSMConditionTree to ActionList\n"); + } else { + ERROR("no ActionList for DSMConditionTree\n"); + delete al; + return false; + } continue; - } + } } State* state = dynamic_cast(stack_top); @@ -405,6 +439,26 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, return false; } t->actions = al->actions; + } else if (al->al_type == ActionList::AL_for) { + DSMArrayFor* af = dynamic_cast(&(*stack.back())); + if (!af) { + ERROR("no DSMArrayFor for action list\n"); + delete al; + return false; + } + af->actions = al->actions; + + stack.pop_back(); + + ActionList* b_al = dynamic_cast(&(*stack.back())); + if (!b_al) { + ERROR("internal error: no ActionList for 'for'\n"); + return false; + } + b_al->actions.push_back(af); + DBG("} // end for (%s%s in %s) {\n", + af->k.c_str(), af->v.empty() ? "" : (","+af->v).c_str(), + af->array_struct.c_str()); } else { ERROR("internal: unknown transition list type\n"); } @@ -416,12 +470,23 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, //token is condition tree stack.push_back(new DSMConditionTree()); continue; + } else if (token.substr(0, 3) == "for") { + // token is for loop + DSMArrayFor* af = new DSMArrayFor(); + if (token.length() > 3) { + if (!forFromToken(*af, token.substr(3))) + return false; + } + + stack.push_back(af); + continue; } else { DSMFunction* f = functionFromToken(token); if (f) { DBG("adding actions from function '%s'\n", f->name.c_str()); DBG("al.size is %zd before", al->actions.size()); - for (vector::iterator it=f->actions.begin(); it != f->actions.end(); it++) { + for (vector::iterator it=f->actions.begin(); + it != f->actions.end(); it++) { DSMElement* a = *it; owner->transferElem(a); al->actions.push_back(a); @@ -553,6 +618,31 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, } continue; } + + DSMArrayFor* af = dynamic_cast(stack_top); + if (af) { + if (af->array_struct.length() || af->k.length()) { + // expecting body + if (token == "}") { + DBG("close for\n"); + ERROR("sounds wrong!!!\n"); + stack.pop_back(); + continue; + } + + if (token == "{") { + // start action list for 'for' + stack.push_back(new ActionList(ActionList::AL_for)); + continue; + } + } else { + if (!forFromToken(*af, token)) + return false; + } + + continue; + } + } for (vector::iterator it= diff --git a/apps/dsm/DSMChartReader.h b/apps/dsm/DSMChartReader.h index 03518775..366fe630 100644 --- a/apps/dsm/DSMChartReader.h +++ b/apps/dsm/DSMChartReader.h @@ -59,8 +59,9 @@ class ActionList : public DSMElement { AL_exit, AL_trans, AL_if, - AL_else, - AL_func + AL_else, + AL_func, + AL_for }; AL_type al_type; @@ -87,6 +88,7 @@ class DSMChartReader { DSMFunction* functionFromToken(const string& str); DSMAction* actionFromToken(const string& str); DSMCondition* conditionFromToken(const string& str, bool invert); + bool forFromToken(DSMArrayFor& af, const string& token); bool importModule(const string& mod_cmd, const string& mod_path); vector mods; diff --git a/apps/dsm/DSMStateEngine.cpp b/apps/dsm/DSMStateEngine.cpp index 47295f1d..2de1cfa0 100644 --- a/apps/dsm/DSMStateEngine.cpp +++ b/apps/dsm/DSMStateEngine.cpp @@ -264,6 +264,7 @@ bool DSMStateEngine::runactions(vector::iterator from, default: break; } } + continue; } DSMConditionTree* cond_tree = dynamic_cast(*it); @@ -285,8 +286,104 @@ bool DSMStateEngine::runactions(vector::iterator from, sess, sc_sess, event, event_params, is_consumed)) return true; } + continue; } + DSMArrayFor* array_for = dynamic_cast(*it); + if (array_for) { + DBG("running for (%s%s in %s) {\n", + array_for->k.c_str(), array_for->v.empty() ? "" : (","+array_for->v).c_str(), + array_for->array_struct.c_str()); + + string array_name = array_for->array_struct; + string k_name = array_for->k; + string v_name = array_for->v; + + if (!array_name.length() || !k_name.length()) { + WARN("empty array or counter name in for\n"); + continue; + } + + if (array_name[0] == '$') array_name.erase(0, 1); + if (k_name[0] == '$') k_name.erase(0, 1); + bool is_kv = !v_name.empty(); + if (is_kv && v_name[0] == '$') v_name.erase(0, 1); + + + vector > cnt_values; + + // get the counter values + if (is_kv) { + VarMapT::iterator lb = sc_sess->var.lower_bound(array_name); + while (lb != sc_sess->var.end()) { + if ((lb->first.length() < array_name.length()) || + strncmp(lb->first.c_str(), array_name.c_str(), array_name.length())) + break; + + string varname = lb->first.substr(array_name.length()+1); + string valname = lb->second; + cnt_values.push_back(make_pair(varname, valname)); + DBG(" '%s,%s'\n", varname.c_str(), valname.c_str()); + lb++; + } + } else { + unsigned int a_index = 0; + while (true) { + VarMapT::iterator v = sc_sess->var.find(array_name+"["+int2str(a_index)+"]"); + if (v == sc_sess->var.end()) + break; + cnt_values.push_back(make_pair(v->second, "")); + DBG(" '%s'\n", v->second.c_str()); + a_index++; + } + } + + // save counter + VarMapT::iterator c_it = sc_sess->var.find(k_name); + bool k_exists = c_it != sc_sess->var.end(); + string k_save = k_exists ? c_it->second : string(""); + + bool v_exists = false; string v_save; + if (is_kv) { + c_it = sc_sess->var.find(v_name); + v_exists = c_it != sc_sess->var.end(); + if (v_exists) + v_save = c_it->second; + } + + // run the loop + DBG("running for loop with %zd items\n", cnt_values.size()); + for (vector >::iterator f_it= + cnt_values.begin(); f_it != cnt_values.end(); f_it++) { + if (is_kv) { + DBG("setting $%s=%s, $%s=%s\n", k_name.c_str(), f_it->first.c_str(), + v_name.c_str(), f_it->second.c_str()); + sc_sess->var[k_name] = f_it->first; + sc_sess->var[v_name] = f_it->second; + } else { + DBG("setting $%s=%s\n", k_name.c_str(), f_it->first.c_str()); + sc_sess->var[k_name] = f_it->first; + } + runactions(array_for->actions.begin(), array_for->actions.end(), + sess, sc_sess, event, event_params, is_consumed); + } + // restore the counter[s] + if (k_exists) + sc_sess->var[k_name] = k_save; + else + sc_sess->var.erase(k_name); + + if (is_kv) { + if (v_exists) + sc_sess->var[v_name] = v_save; + else + sc_sess->var.erase(v_name); + } + + continue; + } + + ERROR("DSMElement typenot understood\n"); } return false; } diff --git a/apps/dsm/DSMStateEngine.h b/apps/dsm/DSMStateEngine.h index c2150d42..97edd2fa 100644 --- a/apps/dsm/DSMStateEngine.h +++ b/apps/dsm/DSMStateEngine.h @@ -177,6 +177,15 @@ class DSMFunction vector actions; }; +class DSMArrayFor +: public DSMElement { + public: + string k; // for(k in array) + string v; // if set, for(k,v in struct) + string array_struct; // array or struct name + vector actions; +}; + class DSMModule; class DSMStateDiagram { From 26db3fae3371e2ad2eb1ff107334911153468a63 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Sun, 23 Jan 2011 18:33:31 +0100 Subject: [PATCH 07/12] DSM: implement for ($x in range(2, 5)) Development sponsored by TelTech Systems Inc. --- apps/dsm/DSMChartReader.cpp | 30 ++++++++++++-- apps/dsm/DSMStateEngine.cpp | 79 +++++++++++++++++++++++++------------ apps/dsm/DSMStateEngine.h | 12 +++++- 3 files changed, 92 insertions(+), 29 deletions(-) diff --git a/apps/dsm/DSMChartReader.cpp b/apps/dsm/DSMChartReader.cpp index 94c89540..08358bc2 100644 --- a/apps/dsm/DSMChartReader.cpp +++ b/apps/dsm/DSMChartReader.cpp @@ -167,19 +167,43 @@ bool DSMChartReader::forFromToken(DSMArrayFor& af, const string& token) { return false; } - af.array_struct = forh_v[1]; - vector kv = explode(forh_v[0], ","); if (kv.size() == 2) { + af.for_type = DSMArrayFor::Struct; af.k = kv[0]; af.v = kv[1]; + af.array_struct = forh_v[1]; DBG("for (%s,%s in %s) {\n", af.k.c_str(), af.v.c_str(), af.array_struct.c_str()); + } else if (forh_v[1].length() > 7 && + forh_v[1].substr(0,6)=="range(" && + forh_v[1][forh_v[1].length()-1] == ')') { + af.for_type = DSMArrayFor::Range; + string range_s = forh_v[1].substr(6, forh_v[1].length()-7); + vector range_v = explode(range_s, ","); + if (range_v.size() == 2) { + if (!str2int(range_v[0], af.range[0]) || + !str2int(range_v[1], af.range[1])) { + ERROR("range(%s,%s) not understood in for\n", + range_v[0].c_str(), range_v[1].c_str()); + return false; + } + } else { + af.range[0] = 0; + if (!str2int(range_s, af.range[1])) { + ERROR("range(%s) not understood in for\n", range_s.c_str()); + return false; + } + } + af.k = forh_v[0]; + DBG("for (%s in range(%d, %d) {\n", + af.k.c_str(), af.range[0], af.range[1]); } else { + af.for_type = DSMArrayFor::Array; + af.array_struct = forh_v[1]; af.k = forh_v[0]; DBG("for (%s in %s) {\n", af.k.c_str(), af.array_struct.c_str()); } - return true; } diff --git a/apps/dsm/DSMStateEngine.cpp b/apps/dsm/DSMStateEngine.cpp index 2de1cfa0..2466bd36 100644 --- a/apps/dsm/DSMStateEngine.cpp +++ b/apps/dsm/DSMStateEngine.cpp @@ -291,29 +291,39 @@ bool DSMStateEngine::runactions(vector::iterator from, DSMArrayFor* array_for = dynamic_cast(*it); if (array_for) { - DBG("running for (%s%s in %s) {\n", - array_for->k.c_str(), array_for->v.empty() ? "" : (","+array_for->v).c_str(), - array_for->array_struct.c_str()); + if (array_for->for_type == DSMArrayFor::Range) { + DBG("running for (%s in range(%d, %d) {\n", + array_for->k.c_str(), array_for->range[0], array_for->range[1]); + } else { + DBG("running for (%s%s in %s) {\n", + array_for->k.c_str(), array_for->v.empty() ? "" : (","+array_for->v).c_str(), + array_for->array_struct.c_str()); + } string array_name = array_for->array_struct; string k_name = array_for->k; string v_name = array_for->v; - if (!array_name.length() || !k_name.length()) { - WARN("empty array or counter name in for\n"); + if (!k_name.length()) { + ERROR("empty counter name in for\n"); + continue; + } + + if (array_for->for_type != DSMArrayFor::Range && !array_name.length()) { + ERROR("empty array name in for\n"); continue; } if (array_name[0] == '$') array_name.erase(0, 1); if (k_name[0] == '$') k_name.erase(0, 1); - bool is_kv = !v_name.empty(); - if (is_kv && v_name[0] == '$') v_name.erase(0, 1); + if (array_for->for_type == DSMArrayFor::Struct && v_name[0] == '$') + v_name.erase(0, 1); vector > cnt_values; // get the counter values - if (is_kv) { + if (array_for->for_type == DSMArrayFor::Struct) { VarMapT::iterator lb = sc_sess->var.lower_bound(array_name); while (lb != sc_sess->var.end()) { if ((lb->first.length() < array_name.length()) || @@ -326,7 +336,7 @@ bool DSMStateEngine::runactions(vector::iterator from, DBG(" '%s,%s'\n", varname.c_str(), valname.c_str()); lb++; } - } else { + } else if (array_for->for_type == DSMArrayFor::Array) { unsigned int a_index = 0; while (true) { VarMapT::iterator v = sc_sess->var.find(array_name+"["+int2str(a_index)+"]"); @@ -338,13 +348,14 @@ bool DSMStateEngine::runactions(vector::iterator from, } } - // save counter + // save counter k VarMapT::iterator c_it = sc_sess->var.find(k_name); bool k_exists = c_it != sc_sess->var.end(); string k_save = k_exists ? c_it->second : string(""); + // save counter v for Struct bool v_exists = false; string v_save; - if (is_kv) { + if (array_for->for_type == DSMArrayFor::Struct) { c_it = sc_sess->var.find(v_name); v_exists = c_it != sc_sess->var.end(); if (v_exists) @@ -352,28 +363,46 @@ bool DSMStateEngine::runactions(vector::iterator from, } // run the loop - DBG("running for loop with %zd items\n", cnt_values.size()); - for (vector >::iterator f_it= - cnt_values.begin(); f_it != cnt_values.end(); f_it++) { - if (is_kv) { - DBG("setting $%s=%s, $%s=%s\n", k_name.c_str(), f_it->first.c_str(), - v_name.c_str(), f_it->second.c_str()); - sc_sess->var[k_name] = f_it->first; - sc_sess->var[v_name] = f_it->second; - } else { - DBG("setting $%s=%s\n", k_name.c_str(), f_it->first.c_str()); - sc_sess->var[k_name] = f_it->first; + if (array_for->for_type == DSMArrayFor::Range) { + int cnt = array_for->range[0]; + while (cnt != array_for->range[1]) { + sc_sess->var[k_name] = int2str(cnt); + DBG("setting $%s=%s\n", k_name.c_str(), sc_sess->var[k_name].c_str()); + + runactions(array_for->actions.begin(), array_for->actions.end(), + sess, sc_sess, event, event_params, is_consumed); + + if (array_for->range[1] > array_for->range[0]) + cnt++; + else + cnt--; + } + + } else { + DBG("running for loop with %zd items\n", cnt_values.size()); + for (vector > ::iterator f_it= + cnt_values.begin(); f_it != cnt_values.end(); f_it++) { + if (array_for->for_type == DSMArrayFor::Struct) { + DBG("setting $%s=%s, $%s=%s\n", k_name.c_str(), f_it->first.c_str(), + v_name.c_str(), f_it->second.c_str()); + sc_sess->var[k_name] = f_it->first; + sc_sess->var[v_name] = f_it->second; + } else { + DBG("setting $%s=%s\n", k_name.c_str(), f_it->first.c_str()); + sc_sess->var[k_name] = f_it->first; + } + runactions(array_for->actions.begin(), array_for->actions.end(), + sess, sc_sess, event, event_params, is_consumed); } - runactions(array_for->actions.begin(), array_for->actions.end(), - sess, sc_sess, event, event_params, is_consumed); } + // restore the counter[s] if (k_exists) sc_sess->var[k_name] = k_save; else sc_sess->var.erase(k_name); - if (is_kv) { + if (array_for->for_type == DSMArrayFor::Struct) { if (v_exists) sc_sess->var[v_name] = v_save; else diff --git a/apps/dsm/DSMStateEngine.h b/apps/dsm/DSMStateEngine.h index 97edd2fa..118cda4a 100644 --- a/apps/dsm/DSMStateEngine.h +++ b/apps/dsm/DSMStateEngine.h @@ -180,8 +180,18 @@ class DSMFunction class DSMArrayFor : public DSMElement { public: + DSMArrayFor() { } + ~DSMArrayFor() { } + + enum DSMForType { + Range, + Array, + Struct + } for_type; + string k; // for(k in array) - string v; // if set, for(k,v in struct) + string v; // for(k,v in struct) + int range[2]; string array_struct; // array or struct name vector actions; }; From c7c96a2f5e529a5629fe9c3c6b08fe8b8b0ecb64 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Mon, 24 Jan 2011 01:34:26 +0100 Subject: [PATCH 08/12] DSM: parsing of "else", if conditions without [] --- apps/dsm/DSMChartReader.cpp | 155 +++++++++++++++++++++++++--------- apps/dsm/DSMChartReader.h | 3 +- apps/dsm/DSMElemContainer.cpp | 4 +- apps/dsm/DSMElemContainer.h | 6 +- 4 files changed, 121 insertions(+), 47 deletions(-) diff --git a/apps/dsm/DSMChartReader.cpp b/apps/dsm/DSMChartReader.cpp index 08358bc2..6c9892f4 100644 --- a/apps/dsm/DSMChartReader.cpp +++ b/apps/dsm/DSMChartReader.cpp @@ -346,20 +346,22 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, DSMConditionTree* ct = dynamic_cast(stack_top); if (ct) { if (token == "[") { - stack.push_back(new DSMConditionList()); + DSMConditionList* cl = new DSMConditionList(); + cl->is_if = true; + stack.push_back(cl); continue; - } + } if (token == "{") { stack.push_back(new ActionList(ActionList::AL_if)); continue; } - if (token == ";") { + + if (token == ";" || token == "}") { stack.pop_back(); ActionList* al = dynamic_cast(&(*stack.back())); if (al) { owner->transferElem(ct); al->actions.push_back(ct); - DBG("Added DSMConditionTree to ActionList\n"); } else { ERROR("no ActionList for DSMConditionTree\n"); delete al; @@ -367,6 +369,9 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, } continue; } + + ERROR("syntax error: got '%s' without context\n", token.c_str()); + return false; } State* state = dynamic_cast(stack_top); @@ -418,7 +423,7 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, delete al; return false; } - + if (al->al_type == ActionList::AL_func) { DSMFunction* f = dynamic_cast(&(*stack.back())); if (!f) { @@ -427,22 +432,47 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, return false; } f->actions = al->actions; - } else if (al->al_type == ActionList::AL_if || - al->al_type == ActionList::AL_else) { + delete al; + continue; + } + + if (al->al_type == ActionList::AL_if || + al->al_type == ActionList::AL_else) { DSMConditionTree* ct = dynamic_cast(&(*stack.back())); if (!ct) { ERROR("no DSMConditionTree for action list\n"); delete al; return false; } - - if (al->al_type == ActionList::AL_if) { + + if (al->al_type == ActionList::AL_if) ct->run_if_true = al->actions; - } else if (al->al_type == ActionList::AL_else) { + else ct->run_if_false = al->actions; - } - } else if (al->al_type == ActionList::AL_enter || - al->al_type == ActionList::AL_exit) { + + stack.pop_back(); + ActionList* al_parent = dynamic_cast(&(*stack.back())); + if (al_parent) { + owner->transferElem(ct); + al_parent->actions.push_back(ct); + } else { + ERROR("no ActionList for DSMConditionTree\n"); + delete al; + return false; + } + if (al->al_type == ActionList::AL_if) + DBG("} // end if\n"); + else + DBG("} // end else\n"); + + delete al; + + continue; + + } + + if (al->al_type == ActionList::AL_enter || + al->al_type == ActionList::AL_exit) { State* s = dynamic_cast(&(*stack.back())); if (!s) { ERROR("no State for action list\n"); @@ -455,7 +485,11 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, } else if (al->al_type == ActionList::AL_exit) { s->post_actions = al->actions; } - } else if (al->al_type == ActionList::AL_trans) { + delete al; + continue; + } + + if (al->al_type == ActionList::AL_trans) { DSMTransition* t = dynamic_cast(&(*stack.back())); if (!t) { ERROR("no DSMTransition for action list\n"); @@ -463,7 +497,11 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, return false; } t->actions = al->actions; - } else if (al->al_type == ActionList::AL_for) { + delete al; + continue; + } + + if (al->al_type == ActionList::AL_for) { DSMArrayFor* af = dynamic_cast(&(*stack.back())); if (!af) { ERROR("no DSMArrayFor for action list\n"); @@ -483,18 +521,38 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, DBG("} // end for (%s%s in %s) {\n", af->k.c_str(), af->v.empty() ? "" : (","+af->v).c_str(), af->array_struct.c_str()); - } else { - ERROR("internal: unknown transition list type\n"); + delete al; + continue; } - delete al; - continue; + + ERROR("internal: unknown transition list type\n"); + return false; } - + if (token == "if") { - //token is condition tree + DBG("if ...\n"); + // start condition tree stack.push_back(new DSMConditionTree()); + DSMConditionList* cl = new DSMConditionList(); + cl->is_if = true; + stack.push_back(cl); + continue; + } + + if (token == "else") { + DBG(" ... else ...\n"); + DSMConditionTree* ct = dynamic_cast(al->actions.back()); + if (NULL == ct) { + ERROR("syntax error: else without if block\n"); + return false; + } + stack.push_back(ct); + stack.push_back(new ActionList(ActionList::AL_else)); + al->actions.pop_back(); continue; - } else if (token.substr(0, 3) == "for") { + } + + if (token.substr(0, 3) == "for") { // token is for loop DSMArrayFor* af = new DSMArrayFor(); if (token.length() > 3) { @@ -504,36 +562,51 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart, stack.push_back(af); continue; - } else { - DSMFunction* f = functionFromToken(token); - if (f) { - DBG("adding actions from function '%s'\n", f->name.c_str()); - DBG("al.size is %zd before", al->actions.size()); - for (vector::iterator it=f->actions.begin(); - it != f->actions.end(); it++) { - DSMElement* a = *it; - owner->transferElem(a); - al->actions.push_back(a); - } - DBG("al.size is %zd after", al->actions.size()); - } else { - DBG("adding action '%s'\n", token.c_str()); - DSMAction* a = actionFromToken(token); - if (!a) - return false; + } + + DSMFunction* f = functionFromToken(token); + if (f) { + DBG("adding actions from function '%s'\n", f->name.c_str()); + DBG("al.size is %zd before", al->actions.size()); + for (vector::iterator it=f->actions.begin(); + it != f->actions.end(); it++) { + DSMElement* a = *it; owner->transferElem(a); al->actions.push_back(a); } + DBG("al.size is %zd after", al->actions.size()); continue; } - } + + DBG("adding action '%s'\n", token.c_str()); + DSMAction* a = actionFromToken(token); + if (!a) + return false; + owner->transferElem(a); + al->actions.push_back(a); + } // actionlist DSMConditionList* cl = dynamic_cast(stack_top); if (cl) { - if (token == ";") + if (token == ";" || token == "[") continue; + if (cl->is_if && token == "{") { + // end of condition list for if + stack.pop_back(); + DSMConditionTree* ct = dynamic_cast(&(*stack.back())); + if (!ct) { + ERROR("internal error: condition list without condition tree\n"); + return false; + } + DBG("{\n"); + ct->conditions = cl->conditions; + ct->is_exception = cl->is_exception; + stack.push_back(new ActionList(ActionList::AL_if)); + continue; + } + if ((token == "{") || (token == "}")) { // readability continue; diff --git a/apps/dsm/DSMChartReader.h b/apps/dsm/DSMChartReader.h index 366fe630..04530efb 100644 --- a/apps/dsm/DSMChartReader.h +++ b/apps/dsm/DSMChartReader.h @@ -73,10 +73,11 @@ class ActionList : public DSMElement { }; struct DSMConditionList : public DSMElement { - DSMConditionList() : invert_next(false), is_exception(false) { } + DSMConditionList() : invert_next(false), is_exception(false), is_if(false) { } vector conditions; bool invert_next; bool is_exception; + bool is_if; }; class DSMChartReader { diff --git a/apps/dsm/DSMElemContainer.cpp b/apps/dsm/DSMElemContainer.cpp index 431224b8..ac2cefb9 100644 --- a/apps/dsm/DSMElemContainer.cpp +++ b/apps/dsm/DSMElemContainer.cpp @@ -32,11 +32,11 @@ DSMElemContainer::DSMElemContainer() { } DSMElemContainer::~DSMElemContainer() { - for (vector::iterator it= + for (set::iterator it= owned_elems.begin(); it != owned_elems.end(); it++) delete *it; } void DSMElemContainer::transferElem(DSMElement* elem) { - owned_elems.push_back(elem); + owned_elems.insert(elem); } diff --git a/apps/dsm/DSMElemContainer.h b/apps/dsm/DSMElemContainer.h index a3b741c0..c622fb36 100644 --- a/apps/dsm/DSMElemContainer.h +++ b/apps/dsm/DSMElemContainer.h @@ -28,11 +28,11 @@ #define _SC_ELEM_CONTAINER_H class DSMElement; -#include -using std::vector; +#include +using std::set; class DSMElemContainer { - vector owned_elems; + set owned_elems; public: DSMElemContainer(); virtual ~DSMElemContainer(); From d5ebf27e02cd8f4f09e8b022a126932e4e62893d Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Tue, 25 Jan 2011 19:54:29 +0100 Subject: [PATCH 09/12] DSM: fix for ($bar in array) for structs Example: set($foo[0].a="a0"); set($foo[0].b="b0"); set($foo[1].a="a1"); set($foo[1].b="b1"); for ($bar in $foo) { log(1, $bar); } --- apps/dsm/DSMStateEngine.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/apps/dsm/DSMStateEngine.cpp b/apps/dsm/DSMStateEngine.cpp index 2466bd36..d46b7473 100644 --- a/apps/dsm/DSMStateEngine.cpp +++ b/apps/dsm/DSMStateEngine.cpp @@ -338,14 +338,24 @@ bool DSMStateEngine::runactions(vector::iterator from, } } else if (array_for->for_type == DSMArrayFor::Array) { unsigned int a_index = 0; - while (true) { - VarMapT::iterator v = sc_sess->var.find(array_name+"["+int2str(a_index)+"]"); - if (v == sc_sess->var.end()) - break; + VarMapT::iterator v = sc_sess-> + var.lower_bound(array_name+"["+int2str(a_index)+"]"); + + while (v != sc_sess->var.end()) { + string this_index = array_name+"["+int2str(a_index)+"]"; + if (v->first.substr(0, this_index.length()) != this_index) { + a_index++; + this_index = array_name+"["+int2str(a_index)+"]"; + if (v->first.substr(0, this_index.length()) != this_index) { + break; + } + } + cnt_values.push_back(make_pair(v->second, "")); DBG(" '%s'\n", v->second.c_str()); - a_index++; + v++; } + } // save counter k From 721f6ecf7323e54cf05ede64414733774443c0fc Mon Sep 17 00:00:00 2001 From: Mathew Williams Date: Wed, 26 Jan 2011 02:10:30 +0000 Subject: [PATCH 10/12] added [] to chars not allowed in var names --- apps/dsm/DSMCoreModule.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/dsm/DSMCoreModule.cpp b/apps/dsm/DSMCoreModule.cpp index 189045bf..107ec85b 100644 --- a/apps/dsm/DSMCoreModule.cpp +++ b/apps/dsm/DSMCoreModule.cpp @@ -545,9 +545,9 @@ string replaceParams(const string& q, AmSession* sess, DSMSession* sc_sess, res[rstart+1] == '"' || res[rstart+1] == '\'' )) - rend = res.find_first_of(" ,()$#@\t;:'\"", rstart+2); + rend = res.find_first_of(" ,()[]$#@\t;:'\"", rstart+2); else - rend = res.find_first_of(" ,()$#@\t;:'\"", rstart+1); + rend = res.find_first_of(" ,()[]$#@\t;:'\"", rstart+1); if (rend==string::npos) rend = res.length(); string keyname = res.substr(rstart+1, rend-rstart-1); From dd467a96ef4b0d7543613b1f50763efb9973c45e Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Thu, 27 Jan 2011 02:11:31 +0100 Subject: [PATCH 11/12] DSM: size($arrayname, $dst) action size($arrayname, $dst); set variable $dst to size of array (e.g. $arrayname[0], $arrayname[1] set, $dst set to 2) --- apps/dsm/DSMCoreModule.cpp | 26 ++++++++++++++++++++++++++ apps/dsm/DSMCoreModule.h | 1 + doc/dsm/dsm_syntax.txt | 4 ++++ 3 files changed, 31 insertions(+) diff --git a/apps/dsm/DSMCoreModule.cpp b/apps/dsm/DSMCoreModule.cpp index 107ec85b..3de108c4 100644 --- a/apps/dsm/DSMCoreModule.cpp +++ b/apps/dsm/DSMCoreModule.cpp @@ -86,6 +86,7 @@ DSMAction* DSMCoreModule::getAction(const string& from_str) { DEF_CMD("log", SCLogAction); DEF_CMD("clear", SCClearAction); DEF_CMD("clearArray", SCClearArrayAction); + DEF_CMD("size", SCSizeAction); DEF_CMD("logVars", SCLogVarsAction); DEF_CMD("logParams", SCLogParamsAction); DEF_CMD("logSelects", SCLogSelectsAction); @@ -691,6 +692,31 @@ EXEC_ACTION_START(SCClearArrayAction) { } EXEC_ACTION_END; +CONST_ACTION_2P(SCSizeAction, ',', false); +EXEC_ACTION_START(SCSizeAction) { + string array_name = par1; + if (array_name.length() && array_name[0]=='$') + array_name.erase(0,1); + + string dst_name = par2; + if (dst_name.length()&&dst_name[0]=='$') + dst_name.erase(0,1); + + + unsigned int a_size = 0; + while (true) { + string ai_name = array_name+"["+int2str(a_size)+"]"; + VarMapT::iterator lb = sc_sess->var.lower_bound(ai_name); + if (lb == sc_sess->var.end() || + lb->first.substr(0,ai_name.length()) != ai_name) + break; + a_size++; + } + string res = int2str(a_size); + sc_sess->var[dst_name] = res; + DBG("set $%s=%s\n", dst_name.c_str(), res.c_str()); +} EXEC_ACTION_END; + CONST_ACTION_2P(SCAppendAction,',', false); EXEC_ACTION_START(SCAppendAction) { diff --git a/apps/dsm/DSMCoreModule.h b/apps/dsm/DSMCoreModule.h index 67a3d3c4..c00c2581 100644 --- a/apps/dsm/DSMCoreModule.h +++ b/apps/dsm/DSMCoreModule.h @@ -84,6 +84,7 @@ DEF_ACTION_2P(SCSubStrAction); DEF_ACTION_1P(SCIncAction); DEF_ACTION_1P(SCClearAction); DEF_ACTION_1P(SCClearArrayAction); +DEF_ACTION_2P(SCSizeAction); DEF_ACTION_2P(SCSetTimerAction); DEF_ACTION_1P(SCRemoveTimerAction); DEF_ACTION_1P(SCRemoveTimersAction); diff --git a/doc/dsm/dsm_syntax.txt b/doc/dsm/dsm_syntax.txt index 7acfd637..162b5d9c 100644 --- a/doc/dsm/dsm_syntax.txt +++ b/doc/dsm/dsm_syntax.txt @@ -145,6 +145,10 @@ sendDTMFSequence(sequence [, duration_ms]) append($var, @select); append($var, $var2); substr($var, pos) e.g. substr($myvar, 5); + + size($arrayname, $dst); + set variable $dst to size of array + (e.g. $arrayname[0], $arrayname[1] set, $dst set to 2) inc($var) clear($var) From 5026ab7f50fe641cac281cdc165c3501fa77f6a6 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Thu, 27 Jan 2011 02:59:50 +0100 Subject: [PATCH 12/12] DSM: support variables in range, e.g. range($myvar) Example: set($a=0); set($b=-5); for ($x in range($a, $b)) { log(1, $x); }; --- apps/dsm/DSMChartReader.cpp | 19 ++++++------------- apps/dsm/DSMStateEngine.cpp | 28 +++++++++++++++++++++------- apps/dsm/DSMStateEngine.h | 5 ++--- 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/apps/dsm/DSMChartReader.cpp b/apps/dsm/DSMChartReader.cpp index 6c9892f4..6c67657c 100644 --- a/apps/dsm/DSMChartReader.cpp +++ b/apps/dsm/DSMChartReader.cpp @@ -181,22 +181,15 @@ bool DSMChartReader::forFromToken(DSMArrayFor& af, const string& token) { string range_s = forh_v[1].substr(6, forh_v[1].length()-7); vector range_v = explode(range_s, ","); if (range_v.size() == 2) { - if (!str2int(range_v[0], af.range[0]) || - !str2int(range_v[1], af.range[1])) { - ERROR("range(%s,%s) not understood in for\n", - range_v[0].c_str(), range_v[1].c_str()); - return false; - } + af.v = trim(range_v[0], " "); + af.array_struct = trim(range_v[1], " "); } else { - af.range[0] = 0; - if (!str2int(range_s, af.range[1])) { - ERROR("range(%s) not understood in for\n", range_s.c_str()); - return false; - } + af.v = "0"; + af.array_struct = trim(range_s, " "); } af.k = forh_v[0]; - DBG("for (%s in range(%d, %d) {\n", - af.k.c_str(), af.range[0], af.range[1]); + DBG("for (%s in range(%s, %s) {\n", + af.k.c_str(), af.v.c_str(), af.array_struct.c_str()); } else { af.for_type = DSMArrayFor::Array; af.array_struct = forh_v[1]; diff --git a/apps/dsm/DSMStateEngine.cpp b/apps/dsm/DSMStateEngine.cpp index d46b7473..13a6a58c 100644 --- a/apps/dsm/DSMStateEngine.cpp +++ b/apps/dsm/DSMStateEngine.cpp @@ -292,8 +292,8 @@ bool DSMStateEngine::runactions(vector::iterator from, DSMArrayFor* array_for = dynamic_cast(*it); if (array_for) { if (array_for->for_type == DSMArrayFor::Range) { - DBG("running for (%s in range(%d, %d) {\n", - array_for->k.c_str(), array_for->range[0], array_for->range[1]); + DBG("running for (%s in range(%s, %s) {\n", + array_for->k.c_str(), array_for->v.c_str(), array_for->array_struct.c_str()); } else { DBG("running for (%s%s in %s) {\n", array_for->k.c_str(), array_for->v.empty() ? "" : (","+array_for->v).c_str(), @@ -321,7 +321,7 @@ bool DSMStateEngine::runactions(vector::iterator from, v_name.erase(0, 1); vector > cnt_values; - + int range[2] = {0,0}; // get the counter values if (array_for->for_type == DSMArrayFor::Struct) { VarMapT::iterator lb = sc_sess->var.lower_bound(array_name); @@ -355,7 +355,21 @@ bool DSMStateEngine::runactions(vector::iterator from, DBG(" '%s'\n", v->second.c_str()); v++; } - + } else if (array_for->for_type == DSMArrayFor::Range) { + string s_range = resolveVars(array_for->v, sess, sc_sess, event_params); + if (!str2int(s_range, range[0])) { + WARN("Error converting lower bound range(%s,%s)\n", + array_for->v.c_str(), array_for->array_struct.c_str()); + range[0]=0; + } else { + s_range = resolveVars(array_for->array_struct, sess, sc_sess, event_params); + + if (!str2int(s_range, range[1])) { + WARN("Error converting upper bound range(%s,%s)\n", + array_for->v.c_str(), array_for->array_struct.c_str()); + range[0]=0; range[1]=0; + } + } } // save counter k @@ -374,15 +388,15 @@ bool DSMStateEngine::runactions(vector::iterator from, // run the loop if (array_for->for_type == DSMArrayFor::Range) { - int cnt = array_for->range[0]; - while (cnt != array_for->range[1]) { + int cnt = range[0]; + while (cnt != range[1]) { sc_sess->var[k_name] = int2str(cnt); DBG("setting $%s=%s\n", k_name.c_str(), sc_sess->var[k_name].c_str()); runactions(array_for->actions.begin(), array_for->actions.end(), sess, sc_sess, event, event_params, is_consumed); - if (array_for->range[1] > array_for->range[0]) + if (range[1] > range[0]) cnt++; else cnt--; diff --git a/apps/dsm/DSMStateEngine.h b/apps/dsm/DSMStateEngine.h index 118cda4a..e3351094 100644 --- a/apps/dsm/DSMStateEngine.h +++ b/apps/dsm/DSMStateEngine.h @@ -190,9 +190,8 @@ class DSMArrayFor } for_type; string k; // for(k in array) - string v; // for(k,v in struct) - int range[2]; - string array_struct; // array or struct name + string v; // for(k,v in struct), or range lower bound + string array_struct; // array or struct name, or range upper bound vector actions; };