summaryrefslogtreecommitdiffstats
path: root/src/usr/hwpf/ifcompiler/initRpn.C
diff options
context:
space:
mode:
authorMike Jones <mjjones@us.ibm.com>2011-11-17 19:38:31 -0600
committerMIKE J. JONES <mjjones@us.ibm.com>2011-11-21 12:07:50 -0600
commit11c80c5abcf203e5a65098ea047fd6d2a6e607cc (patch)
tree1e1a5246e8ed0b25b66e6e1e34bba7622f63bbea /src/usr/hwpf/ifcompiler/initRpn.C
parentb9d93e82a069b6650f3bd7b43abe6aecc0bf2e4e (diff)
downloadblackbird-hostboot-11c80c5abcf203e5a65098ea047fd6d2a6e607cc.tar.gz
blackbird-hostboot-11c80c5abcf203e5a65098ea047fd6d2a6e607cc.zip
HWPF: Only support initfile attributes in fapiGetInitFileAttr()
Change-Id: Ia1ffa854d55b68f0e32595080bba323cd52e23a3 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/503 Tested-by: Jenkins Server Reviewed-by: Andrew J. Geissler <andrewg@us.ibm.com> Reviewed-by: CAMVAN T. NGUYEN <ctnguyen@us.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/hwpf/ifcompiler/initRpn.C')
-rwxr-xr-xsrc/usr/hwpf/ifcompiler/initRpn.C1136
1 files changed, 1136 insertions, 0 deletions
diff --git a/src/usr/hwpf/ifcompiler/initRpn.C b/src/usr/hwpf/ifcompiler/initRpn.C
new file mode 100755
index 000000000..39af931a1
--- /dev/null
+++ b/src/usr/hwpf/ifcompiler/initRpn.C
@@ -0,0 +1,1136 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/ifcompiler/initRpn.C,v $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2010,2010
+//
+//UNDEFINED
+//
+// Origin: UNDEFINED
+//
+// IBM_PROLOG_END_TAG
+// Change Log *************************************************************************************
+//
+// Flag Reason Userid Date Description
+// ----- -------- -------- -------- -------------------------------------------------------------
+// D754106 dgilbert 06/14/10 Create
+// dg002 SW039868 dgilbert 10/15/10 Add support to filter unneeded inits by EC
+// dg003 SW047506 dgilbert 12/09/10 SERIES filtering
+// andrewg 05/24/11 Port over for VPL/PgP
+// andrewg 09/19/11 Updates based on review
+// camvanng 11/08/11 Added support for attribute enums
+// andrewg 11/09/11 Multi-dimensional array and move to common fapi include
+// End Change Log *********************************************************************************
+
+/**
+ * @file initRpn.C
+ * @brief Definition of the initRpn class. Handles Reverse Polish Notation equations for initfiles
+ */
+#include <initRpn.H>
+#include <initSymbols.H>
+//#include <initSpy.H>
+#include <stdlib.h>
+#include <sstream>
+#include <iomanip>
+#include <iostream>
+#include <stdexcept>
+
+using namespace init;
+
+const char * OP_TXT[] =
+{
+ "PUSH",
+ "AND",
+ "OR",
+ "NOT",
+ "EQ",
+ "NE",
+ "GT",
+ "GE",
+ "LT",
+ "LE",
+ "PLUS",
+ "MINUS",
+ "MULT",
+ "DIVIDE",
+ "MOD",
+ "LIST",
+ "SHIFTLEFT",
+ "SHIFTRIGHT",
+ "FALSE", //dg003a
+ "TRUE", //dg003a
+};
+
+std::string Rpn::cv_empty_str;
+
+//-------------------------------------------------------------------------------------------------
+
+Rpn::Rpn(uint32_t i_uint,Symbols * symbols) : iv_symbols(symbols)
+{ push_int(i_uint);}
+
+//-------------------------------------------------------------------------------------------------
+
+Rpn::Rpn(std::string i_id, Symbols * symbols, TYPE i_type) : iv_symbols(symbols)
+{ push_id(i_id, i_type); }
+
+//-------------------------------------------------------------------------------------------------
+
+Rpn::Rpn(uint64_t i_uint, Symbols * symbols) : iv_symbols(symbols)
+{
+ push_int64(i_uint);
+}
+
+//-------------------------------------------------------------------------------------------------
+
+bool Rpn::operator==(const Rpn & r)
+{
+ bool result = false;
+ if (iv_rpnstack.size() == r.iv_rpnstack.size())
+ {
+ if (iv_symbols == r.iv_symbols)
+ {
+ result = true;
+ RPNSTACK::const_iterator c1 = iv_rpnstack.begin();
+ RPNSTACK::const_iterator c2 = r.iv_rpnstack.begin();
+ for (; c1 != iv_rpnstack.end(); ++c1, ++c2)
+ {
+ if (*c1 != *c2)
+ {
+ result = false;
+ break;
+ }
+ }
+ }
+ else // they have different symbol tables
+ {
+ result = true;
+ RPNSTACK::const_iterator c1 = iv_rpnstack.begin();
+ RPNSTACK::const_iterator c2 = r.iv_rpnstack.begin();
+ for (; c1 != iv_rpnstack.end(); ++c1, ++c2)
+ {
+ uint32_t t1 = (*c1) & TYPE_MASK;
+ uint32_t t2 = (*c2) & TYPE_MASK;
+ if(t1 != t2)
+ {
+ result = false;
+ break;
+ }
+ switch (t1)
+ {
+ case DEFINE:
+ {
+ Rpn r1 = iv_symbols->get_define_rpn(*c1);
+ Rpn r2 = r.iv_symbols->get_define_rpn(*c2);
+ if (r1 != r2) result = false;
+ }
+ break;
+ case SYMBOL:
+ {
+ string s1 = iv_symbols->find_name(*c1);
+ string s2 = (r.iv_symbols)->find_name(*c2);
+ if(s1 != s2) result = false;
+ }
+ break;
+ case NUMBER:
+ {
+ uint32_t size = 0;
+ uint64_t data1 = iv_symbols->get_numeric_data(*c1,size);
+ uint64_t data2 = (r.iv_symbols)->get_numeric_data(*c2,size);
+ // do we care if the size is different only the value?
+ if(data1 != data2) result = false;
+ }
+ break;
+ case OPERATION: // independent of symbol table - just compare
+ default: // just compare
+ if(*c1 != *c2) result = false;
+ break;
+ }
+ if(result == false) break;
+ }
+ }
+ }
+ return result;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void Rpn::push_int(uint32_t i_uint)
+{
+ uint32_t rpn_id = iv_symbols->find_numeric_lit(i_uint,4);
+ iv_rpnstack.push_back(rpn_id);
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void Rpn::push_int64(uint64_t i_uint)
+{
+ uint32_t rpn_id = iv_symbols->find_numeric_lit(i_uint,8);
+ iv_rpnstack.push_back(rpn_id);
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void Rpn::push_id(std::string & i_id, TYPE i_type)
+{
+ uint32_t rpn_id = 0;
+ std::string s(i_id);
+
+ for (std::string::iterator c = s.begin(); c != s.end(); ++c)
+ {
+ *c = toupper(*c);
+ }
+
+ rpn_id = iv_symbols->use_symbol(s);
+
+ if (rpn_id & DEFINE)
+ {
+ Rpn r = iv_symbols->get_define_rpn(rpn_id);
+ append(r);
+ }
+ else
+ {
+ iv_rpnstack.push_back(rpn_id);
+ }
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void Rpn::push_array_index(std::string &i_array_idx)
+{
+ string l_idx = i_array_idx;
+ // strip of leading "[" and last "]"
+ l_idx = l_idx.substr(1,(l_idx.length() - 2));
+ uint32_t l_array_val = atoi(l_idx.c_str());
+
+ uint32_t rpn_id = iv_symbols->find_numeric_array_lit(l_array_val,4);
+ iv_rpnstack.push_back(rpn_id);
+
+ // printf("Array Index: %s decimal:%u rpn_id:0x%8X\n",l_idx.c_str(),l_array_val,rpn_id);
+
+}
+
+//-------------------------------------------------------------------------------------------------
+void Rpn::push_attr_enum(std::string &i_attr_enum)
+{
+ uint64_t l_attr_enum_val = iv_symbols->get_attr_enum_val(i_attr_enum);
+
+ uint32_t rpn_id = iv_symbols->find_numeric_lit(l_attr_enum_val,8);
+ iv_rpnstack.push_back(rpn_id);
+
+ //printf("Attribute Enum name: %s Value:%u rpn_id:0x%8X\n",i_attr_enum.c_str(),l_attr_enum_val,rpn_id);
+}
+
+//-------------------------------------------------------------------------------------------------
+
+bool Rpn::isTrue() const //dg003a
+{
+ if((iv_rpnstack.size() == 1) && (iv_rpnstack[0] == (TRUE_OP | OPERATION))) return true;
+ return false;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+bool Rpn::isFalse() const //dg003a
+{
+ if((iv_rpnstack.size() == 1) && (iv_rpnstack[0] == (FALSE_OP | OPERATION))) return true;
+ return false;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+Rpn * Rpn::push_op(IfRpnOp op)
+{
+ uint32_t v = op;
+ if(op == LIST) // calculate list size
+ {
+ uint32_t count = 0;
+ for(RPNSTACK::const_reverse_iterator r = iv_rpnstack.rbegin(); r != iv_rpnstack.rend(); ++r)
+ {
+ if(((*r) & TYPE_MASK) == OPERATION) break;
+ ++count;
+ }
+ v |= (count << 8);
+ }
+ iv_rpnstack.push_back(v | OPERATION);
+
+ return this;
+}
+
+//-------------------------------------------------------------------------------------------------
+// @post i_rpn is deleted
+
+Rpn * Rpn::push_merge(Rpn * i_rpn, IfRpnOp op)
+{
+ //dg003a begin
+ Rpn * result = this;
+
+ // oportunity for Rpn optimization
+ // rpn && true, -> rpn
+ // rpn && false, -> false
+ // rpn || false, -> rpn
+ // rpn || true, -> true
+ if(op == AND)
+ {
+ if(i_rpn->isTrue())
+ {
+ delete i_rpn;
+ return result; // leave this RPN alone
+ }
+ if(this->isTrue())
+ {
+ iv_rpnstack.clear();
+ return merge(i_rpn); // merge deletes i_rpn
+ }
+ if(i_rpn->isFalse() || this->isFalse())
+ {
+ iv_rpnstack.clear();
+ delete i_rpn;
+ push_op(FALSE_OP);
+ return result;
+ }
+ }
+ else if(op == OR)
+ {
+ if(i_rpn->isFalse())
+ {
+ delete i_rpn;
+ return result;
+ }
+ if(this->isFalse())
+ {
+ iv_rpnstack.clear();
+ return merge(i_rpn); // merge deletes i_rpn
+ }
+ if(i_rpn->isTrue() || this->isTrue())
+ {
+ iv_rpnstack.clear();
+ delete i_rpn;
+ push_op(TRUE_OP);
+ return result;
+ }
+ }
+
+ // Filter out SERIES calculations since this is for SERIES_IP only
+ // There might be a better place/way to do this??
+ // TODO - No idea what this is really
+#if 0
+ Rpn r1("SERIES",iv_symbols);
+ Rpn r2("SERIES_IP",iv_symbols);
+ Rpn r3("SERIES_Z",iv_symbols);
+ if( *this == r1)
+ {
+ if((op == EQ && *i_rpn == r2) || (op == NE && *i_rpn == r3))
+ {
+ iv_rpnstack.clear();
+ push_op(TRUE_OP);
+ delete i_rpn;
+ return result;
+ }
+ if((op == EQ && *i_rpn == r3) || (op == NE && *i_rpn == r2))
+ {
+ iv_rpnstack.clear();
+ push_op(FALSE_OP);
+ delete i_rpn;
+ return result;
+ }
+ }
+#endif
+ // These two expressions are seen as a result of macro expansion
+ // Reduce (expr1 == expr2) == 0 -> expr1 != expr2
+ // Reduce (expr1 == expr2) == 1 -> expr1 == expr2
+ // Reduce for any logic operation
+ if(op == EQ)
+ {
+ Rpn r_zero((uint32_t)0,iv_symbols);
+ Rpn r_one((uint32_t)1, iv_symbols);
+
+ if ((*i_rpn) == r_zero)
+ {
+ if((*this) == r_zero)
+ {
+ delete i_rpn;
+ iv_rpnstack.pop_back();
+ push_op(TRUE_OP);
+ return result;
+ }
+ if((*this) == r_one)
+ {
+ delete i_rpn;
+ iv_rpnstack.pop_back();
+ push_op(FALSE_OP);
+ return result;
+ }
+ // else check for logical op
+ switch (iv_rpnstack.back())
+ {
+ case (AND | OPERATION):
+ case (OR | OPERATION):
+ push_op(NOT);
+ delete i_rpn;
+ return result;
+
+ case (NOT | OPERATION): // untie the NOT
+ iv_rpnstack.pop_back();
+ delete i_rpn;
+ return result;
+
+ case (EQ | OPERATION):
+ iv_rpnstack.back() = (NE | OPERATION);
+ delete i_rpn;
+ return result;
+
+ case (NE | OPERATION):
+ iv_rpnstack.back() = (EQ | OPERATION);
+ delete i_rpn;
+ return result;
+
+ case (GT | OPERATION):
+ iv_rpnstack.back() = (LE | OPERATION);
+ delete i_rpn;
+ return result;
+
+ case (GE | OPERATION):
+ iv_rpnstack.back() = (LT | OPERATION);
+ delete i_rpn;
+ return result;
+
+ case (LT | OPERATION):
+ iv_rpnstack.back() = (GE | OPERATION);
+ delete i_rpn;
+ return result;
+
+ case (LE | OPERATION):
+ iv_rpnstack.back() = (GT | OPERATION);
+ delete i_rpn;
+ return result;
+
+ case (TRUE_OP | OPERATION):
+ iv_rpnstack.back() = (FALSE_OP | OPERATION);
+ delete i_rpn;
+ return result;
+
+ case (FALSE_OP | OPERATION):
+ iv_rpnstack.back() = (TRUE_OP | OPERATION);
+ delete i_rpn;
+ return result;
+
+ default: // Not a logic operation - leave it alone
+ break;
+ }
+ }
+ else if((*i_rpn) == r_one)
+ {
+ if((*this) == r_one)
+ {
+ delete i_rpn;
+ iv_rpnstack.pop_back();
+ push_op(TRUE_OP);
+ return result;
+ }
+ if((*this) == r_zero)
+ {
+ delete i_rpn;
+ iv_rpnstack.pop_back();
+ push_op(FALSE_OP);
+ return result;
+ }
+ // else check for logical op - leave it as is
+ uint32_t l_op = iv_rpnstack.back();
+ if((l_op == (AND | OPERATION)) ||
+ (l_op == (OR | OPERATION)) ||
+ (l_op == (NOT | OPERATION)) ||
+ (l_op == (EQ | OPERATION)) ||
+ (l_op == (NE | OPERATION)) ||
+ (l_op == (GT | OPERATION)) ||
+ (l_op == (GE | OPERATION)) ||
+ (l_op == (LT | OPERATION)) ||
+ (l_op == (LE | OPERATION)) ||
+ (l_op == (TRUE_OP | OPERATION)) ||
+ (l_op == (FALSE_OP | OPERATION)))
+ {
+ delete i_rpn;
+ return result;
+ }
+ }
+ }
+
+ // other stuff i've seen TODO
+ // (0 == 1) == 1 , reduced already to (0 == 1) used to turn off a row - Could eliminate the row?
+ //
+
+
+ //dg003a end
+
+ iv_rpnstack.insert(iv_rpnstack.end(), i_rpn->iv_rpnstack.begin(), i_rpn->iv_rpnstack.end());
+ result = push_op(op);
+
+ delete i_rpn;
+ return result;
+}
+
+//-------------------------------------------------------------------------------------------------
+// @post i_rpn is deleted
+
+Rpn * Rpn::merge(Rpn * i_rpn)
+{
+ iv_rpnstack.insert(iv_rpnstack.end(), i_rpn->iv_rpnstack.begin(), i_rpn->iv_rpnstack.end());
+ delete i_rpn;
+ return this;
+}
+
+//-------------------------------------------------------------------------------------------------
+// See header file for contract
+void Rpn::bin_read(BINSEQ::const_iterator & bli, Symbols * symbols)
+{
+
+ uint32_t size = 2; // Size is always 2 for symbols
+
+ if(symbols) iv_symbols = symbols;
+ iv_rpnstack.clear();
+
+ while(size)
+ {
+ uint32_t v = *bli++;
+ if(v < LAST_OP) // operator
+ {
+ if(v == LIST)
+ {
+ --size;
+ v |= (*bli++) << 8;
+ }
+ iv_rpnstack.push_back(v | OPERATION);
+ --size;
+ }
+ else // tag
+ {
+ v = (v << 8) + (*bli++);
+ --size;
+ if(size == 0)
+ {
+ std::ostringstream errss;
+ errss << "Rpn::bin_read Invalid RPN binary sequence\n";
+ throw std::invalid_argument(errss.str());
+ }
+ --size;
+ iv_rpnstack.push_back(iv_symbols->get_rpn_id(v));
+ }
+ }
+}
+
+//-------------------------------------------------------------------------------------------------
+BINSEQ::const_iterator Rpn::bin_read_one_op(BINSEQ::const_iterator & bli, Symbols * symbols)
+{
+ if(symbols) iv_symbols = symbols;
+ while(true)
+ {
+ uint32_t v = *bli++;
+ if(v < LAST_OP) // operator
+ {
+ if(v == LIST) // list has a size and another OP associated with it.
+ {
+ v |= (*bli++) << 8; // merge size into LIST op
+ iv_rpnstack.push_back(v | OPERATION);
+ v = *bli++; // get the list operation (EQ or NE)
+ }
+ iv_rpnstack.push_back(v | OPERATION);
+ // we are done
+ break;
+ }
+ // not op - always two bytes
+ v = (v << 8) + (*bli++);
+ iv_rpnstack.push_back(iv_symbols->get_rpn_id(v));
+ }
+ return bli;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void Rpn::append(const Rpn & i_rpn)
+{
+ iv_rpnstack.insert(iv_rpnstack.end(), i_rpn.iv_rpnstack.begin(), i_rpn.iv_rpnstack.end());
+}
+
+//-------------------------------------------------------------------------------------------------
+
+std::string Rpn::symbol_names() const
+{
+ std::string result;
+ for(RPNSTACK::const_iterator i = iv_rpnstack.begin(); i != iv_rpnstack.end(); ++i)
+ {
+ if((*i) & SYMBOL)
+ {
+ if(result.size()) result.append(" "); // space or lf??
+ result.append(iv_symbols->find_name(*i));
+ }
+ }
+ return result;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+std::string Rpn::listing(const char * i_desc, const std::string & spyname, bool i_final)
+{
+ std::ostringstream odesc;
+ std::ostringstream oss;
+ uint32_t rpn_byte_size = 0;
+
+
+ oss << std::hex << std::setfill('0');
+
+ //oss << "0x" << std::setw(2) << iv_rpnstack.size() << '\t' << i_desc << std::endl;
+ for(RPNSTACK::iterator i = iv_rpnstack.begin(); i != iv_rpnstack.end(); ++i)
+ {
+ if( (*i) & OPERATION ) // operator
+ {
+ ++rpn_byte_size;
+ uint32_t op_id = (*i) - OPERATION;
+ uint32_t count = op_id >> 8; // NOTE: only the LIST operator has a count
+ op_id &= OP_MASK;
+
+ if(op_id < LAST_OP)
+ {
+ oss << "0x" << std::setw(2) << op_id << "\t\t" << OP_TXT[op_id] << std::endl;
+ if(op_id == LIST)
+ {
+ ++rpn_byte_size;
+ oss << "0x" << std::setw(2) << count << "\t\t"
+ << std::dec << count << std::hex << std::endl;
+ }
+ }
+ else
+ {
+ oss << "0x" << op_id << "\t\t" << "INVALID OPERATION" << std::endl;
+ }
+ }
+ else if((*i) & NUMBER)
+ {
+ uint32_t size = 0;
+ uint64_t data = iv_symbols->get_numeric_data(*i,size);
+ if(i_final)
+ {
+ uint32_t tag = iv_symbols->get_numeric_tag(*i);
+ rpn_byte_size += 2;
+ oss << "0x" << std::setw(4) << tag << "\t\t" << "PUSH 0x"
+ << std::setw(size*2) << data << std::endl;
+ }
+ else
+ {
+ rpn_byte_size += size;
+ oss << "0x" << std::setw(size * 2) << data << '\t' << "Numerica Literal" << std::endl;
+ }
+ }
+ else if((*i) & SYMBOL)
+ {
+ std::string name = iv_symbols->find_name(*i);
+
+ if(i_final)
+ {
+ uint32_t val = iv_symbols->get_tag(*i);
+ uint32_t type = val & IF_TYPE_MASK;
+
+ if (type == IF_ATTR_TYPE)
+ {
+ rpn_byte_size += 2;
+ oss << "0x" << std::setw(4) << val << "\t\t" << "PUSH " << name << std::endl;
+ }
+ else
+ {
+ rpn_byte_size +=4;
+ oss << "0x" << std::setw(8) << val << '\t' << name << "\tUnresolved!" << std::endl;
+ }
+ }
+ else // debug listing
+ {
+ rpn_byte_size +=2;
+ //oss << "0x" << std::setw(8) << *i << '\t'
+ oss << "\t\t" << "PUSH " << name << std::endl;
+
+ }
+ }
+ else
+ {
+ oss << "0x" << std::setw(8) << *i << '\t' << "Unknown RPN id" << std::endl;
+ }
+ }
+
+ if((iv_rpnstack.size() == 1) && (iv_rpnstack.front() & SYMBOL)) // skip size and desc
+ {
+ odesc << oss.str();
+ }
+ else
+ {
+ odesc << std::hex << std::setfill('0')
+ << "0x" << std::setw(4) << rpn_byte_size << "\t\t";
+ if(i_desc) odesc << i_desc;
+ else odesc << std::dec << rpn_byte_size << " BYTES";
+ odesc << std::endl;
+ odesc << oss.str();
+ }
+
+ return odesc.str();
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void Rpn::bin_str(BINSEQ & o_blist, bool i_prepend_count) // binary version to write to file
+{
+ BINSEQ blist;
+ uint32_t count = 0;
+
+
+ for(RPNSTACK::iterator i = iv_rpnstack.begin(); i != iv_rpnstack.end(); ++i)
+ {
+ uint32_t v = *i;
+ uint32_t type = v & TYPE_MASK;
+ uint16_t tag;
+
+ switch (type)
+ {
+ case OPERATION: blist.push_back((uint8_t)v);
+ ++count;
+ if((v & OP_MASK) == LIST)
+ {
+ ++count;
+ blist.push_back((uint8_t)(v >> 8));
+ }
+ break;
+
+ case SYMBOL: tag = iv_symbols->get_tag(v);
+ blist.push_back((uint8_t)(tag >> 8));
+ blist.push_back((uint8_t) tag);
+ count += 2;
+ break;
+
+ case NUMBER: tag = iv_symbols->get_numeric_tag(v);
+ blist.push_back((uint8_t)(tag >> 8));
+ blist.push_back((uint8_t) tag);
+ count += 2;
+ break;
+ case ARRAY_INDEX:
+ tag = iv_symbols->get_numeric_array_tag(v);
+ blist.push_back((uint8_t)(tag >> 8));
+ blist.push_back((uint8_t) tag);
+ count += 2;
+ break;
+
+ default:
+ std::cerr << "ERROR! Rpn::bit_str() Invalid Rpn type: " << v << std::endl;
+ break;
+ }
+ }
+
+ if (i_prepend_count)
+ {
+ o_blist.push_back((uint8_t) count);
+ }
+
+ o_blist.insert(o_blist.end(), blist.begin(), blist.end());
+}
+
+//-------------------------------------------------------------------------------------------------
+// Used for RPN filtering (resolve())
+void Rpn::pop_bool(EVAL_STACK & i_stack, RPN_VALUE & o_value) //dg002a
+{
+ // convert numbers or any to bool
+ if(i_stack.size())
+ {
+ o_value = i_stack.back();
+ i_stack.pop_back();
+ if(o_value.type == RPN_NUMBER)
+ {
+ if(o_value.data == 0) o_value.type = RPN_FALSE;
+ else
+ {
+ o_value.type = RPN_TRUE;
+ if(o_value.data != 1)
+ {
+ cerr << "Was expecting a bool, got a number - assume true" << endl;
+ }
+ }
+ }
+ else if(o_value.type == RPN_ANY) o_value.type = RPN_TRUE;
+ // else already a bool
+ }
+ else
+ {
+ o_value.type = RPN_TRUE;
+ cerr << "Empty stack!" << endl;
+ }
+}
+//-------------------------------------------------------------------------------------------------
+
+void Rpn::pop_number(EVAL_STACK & i_stack, RPN_VALUE & o_value) //dg002a
+{
+ // Convert bools to ANY if a number is expected (eg true == 1)
+ if(i_stack.size())
+ {
+ o_value = i_stack.back();
+ i_stack.pop_back();
+ //if(o_value.type != RPN_NUMBER && o_value.type != RPN_ANY)
+ //{
+ // if(o_value.type == RPN_FALSE) o_value.data = 0;
+ // else if(o_value.type == RPN_TRUE) o_value.data = 1;
+ // //o_value.type = RPN_NUMBER; // not safe when just checking EC
+ // o_value.type = RPN_ANY;
+ //}
+ // else leave as is
+ }
+ else
+ {
+ o_value.type = RPN_ANY;
+ cerr << "Empty stack!" << endl;
+ }
+}
+
+//-------------------------------------------------------------------------------------------------
+
+bool Rpn::resolve_ec(uint32_t i_ec) //dg002a
+{
+ SYMBOL_VAL_LIST v;
+ SYMBOL_VAL_PAIR p(string("EC"),i_ec);
+ v.push_back(p);
+
+ //SYMBOL_VAL_PAIR p1(string("SERIES"),0xA000006C);
+ //SYMBOL_VAL_PAIR p2(string("SERIES_IP"),0xA000006C);
+ //SYMBOL_VAL_PAIR p3(string("SERIES_Z"),0xA000006D);
+ //v.push_back(p1);
+ //v.push_back(p2);
+ //v.push_back(p3);
+
+ return resolve(v);
+}
+
+//-------------------------------------------------------------------------------------------------
+// Tries to resolve as much of the RPN as possible
+// @return false means that based on the given varlist, the RPN will never evaluate to true.
+// eg. unconditionally false
+// true means RPN either evaluated to true or there is not enough information to evaluate the RPN
+// @note SPY RPNs are not supported
+//
+bool Rpn::resolve(SYMBOL_VAL_LIST & i_varlist)
+{
+
+ bool result = true;
+
+ EVAL_STACK stack;
+ RPN_VALUE rpn_true(RPN_TRUE);
+ RPN_VALUE rpn_false(RPN_FALSE);
+ RPN_VALUE r1;
+ RPN_VALUE r2;
+
+ for(RPNSTACK::const_iterator i = iv_rpnstack.begin(); i != iv_rpnstack.end(); ++i)
+ {
+ if( (*i) & OPERATION )
+ {
+ uint32_t op = (*i) - OPERATION;
+ uint32_t count = op >> 8;
+ op &= OP_MASK;
+
+ switch(op)
+ {
+ case AND:
+ pop_bool(stack,r1);
+ pop_bool(stack,r2);
+ if(r1.type == RPN_TRUE && r2.type == RPN_TRUE) stack.push_back(rpn_true);
+ else stack.push_back(rpn_false);
+ break;
+
+ case OR:
+ pop_bool(stack,r1);
+ pop_bool(stack,r2);
+ if(r1.type == RPN_TRUE || r2.type == RPN_TRUE) stack.push_back(rpn_true);
+ else stack.push_back(rpn_false);
+ break;
+
+ case NOT:
+ pop_bool(stack,r1);
+ if(r1.type == RPN_TRUE) stack.push_back(rpn_false);
+ else if(r1.type == RPN_FALSE) stack.push_back(rpn_true);
+ break;
+
+ case EQ:
+ pop_number(stack,r1);
+ pop_number(stack,r2);
+ if(r1.type == RPN_ANY || r2.type == RPN_ANY) stack.push_back(rpn_true);
+ else if(r1.type == RPN_NUMBER && r2.type == RPN_NUMBER)
+ {
+ if(r1.data == r2.data) stack.push_back(rpn_true);
+ else stack.push_back(rpn_false);
+ }
+ else if(r1.type == RPN_TRUE && r2.type == RPN_NUMBER)
+ {
+ if(r2.data == 0) stack.push_back(rpn_false);
+ else stack.push_back(rpn_true);
+ }
+ else if(r2.type == RPN_TRUE && r1.type == RPN_NUMBER)
+ {
+ if(r1.data == 0) stack.push_back(rpn_false);
+ else stack.push_back(rpn_true);
+ }
+ else if(r1.type == RPN_FALSE && r2.type == RPN_NUMBER)
+ {
+ if(r2.data == 0) stack.push_back(rpn_true);
+ else stack.push_back(rpn_false);
+ }
+ else if(r2.type == RPN_FALSE && r1.type == RPN_NUMBER)
+ {
+ if(r1.data == 0) stack.push_back(rpn_true);
+ else stack.push_back(rpn_false);
+ }
+ else if((r1.type == RPN_TRUE && r2.type == RPN_FALSE) ||
+ (r1.type == RPN_FALSE && r2.type == RPN_TRUE)) stack.push_back(rpn_false);
+ else stack.push_back(rpn_true);
+ break;
+
+ case NE:
+ pop_number(stack,r1);
+ pop_number(stack,r2);
+ if(r1.type == RPN_ANY || r2.type == RPN_ANY) stack.push_back(rpn_true);
+ else
+ {
+ if(r1.data != r2.data) stack.push_back(rpn_true);
+ else stack.push_back(rpn_false);
+ }
+ break;
+
+ case GT:
+ pop_number(stack,r1);
+ pop_number(stack,r2);
+ if(r1.type == RPN_ANY || r2.type == RPN_ANY) stack.push_back(rpn_true);
+ else
+ {
+ if(r2.data > r1.data) stack.push_back(rpn_true);
+ else stack.push_back(rpn_false);
+ }
+ break;
+
+ case GE:
+ pop_number(stack,r1);
+ pop_number(stack,r2);
+ if(r1.type == RPN_ANY || r2.type == RPN_ANY) stack.push_back(rpn_true);
+ else
+ {
+ if(r2.data >= r1.data) stack.push_back(rpn_true);
+ else stack.push_back(rpn_false);
+ }
+ break;
+
+ case LT:
+ pop_number(stack,r1);
+ pop_number(stack,r2);
+ if(r1.type == RPN_ANY || r2.type == RPN_ANY) stack.push_back(rpn_true);
+ else
+ {
+ if(r2.data < r1.data) stack.push_back(rpn_true);
+ else stack.push_back(rpn_false);
+ }
+ break;
+
+ case LE:
+ pop_number(stack,r1);
+ pop_number(stack,r2);
+ if(r1.type == RPN_ANY || r2.type == RPN_ANY) stack.push_back(rpn_true);
+ else
+ {
+ if(r2.data <= r1.data) stack.push_back(rpn_true);
+ else stack.push_back(rpn_false);
+ }
+ break;
+
+ case PLUS:
+ r1 = stack.back(); stack.pop_back();
+ r2 = stack.back(); stack.pop_back();
+ if(r1.type == RPN_NUMBER && r2.type == RPN_NUMBER)
+ stack.push_back(RPN_VALUE(r1.data + r2.data,RPN_NUMBER));
+ else cerr << "Was not expecting a non-numeric value for operator +" << endl;
+ break;
+
+ case MINUS:
+ r1 = stack.back(); stack.pop_back();
+ r2 = stack.back(); stack.pop_back();
+ if(r1.type == RPN_NUMBER && r2.type == RPN_NUMBER)
+ stack.push_back(RPN_VALUE(r2.data - r1.data,RPN_NUMBER));
+ else cerr << "Was not expecting a non-numeric value for operator -" << endl;
+ break;
+
+ case MULT:
+ r1 = stack.back(); stack.pop_back();
+ r2 = stack.back(); stack.pop_back();
+ if(r1.type == RPN_NUMBER && r2.type == RPN_NUMBER)
+ stack.push_back(RPN_VALUE(r2.data * r1.data,RPN_NUMBER));
+ else cerr << "Was not expecting a non-numeric value for operator *" << endl;
+ break;
+
+ case DIVIDE:
+ r1 = stack.back(); stack.pop_back();
+ r2 = stack.back(); stack.pop_back();
+ if(r1.type == RPN_NUMBER && r2.type == RPN_NUMBER)
+ stack.push_back(RPN_VALUE(r2.data / r1.data,RPN_NUMBER));
+ else cerr << "Was not expecting a non-numeric value for operator /" << endl;
+ break;
+
+ case MOD:
+ r1 = stack.back(); stack.pop_back();
+ r2 = stack.back(); stack.pop_back();
+ if(r1.type == RPN_NUMBER && r2.type == RPN_NUMBER)
+ stack.push_back(RPN_VALUE(r2.data % r1.data,RPN_NUMBER));
+ else cerr << "Was not expecting a non-numeric value for operator %" << endl;
+ break;
+
+ case LIST: // lists are always true - TODO look for EC list ??
+ ++i;
+ while(count--) stack.pop_back();
+ stack.push_back(rpn_true);
+ break;
+
+ case SHIFTLEFT:
+ r1 = stack.back(); stack.pop_back();
+ r2 = stack.back(); stack.pop_back();
+ if(r1.type == RPN_NUMBER && r2.type == RPN_NUMBER)
+ stack.push_back(RPN_VALUE(r2.data << r1.data,RPN_NUMBER));
+ else cerr << "Was not expecting a non-numeric value for operator <<" << endl;
+ break;
+
+ case SHIFTRIGHT:
+ r1 = stack.back(); stack.pop_back();
+ r2 = stack.back(); stack.pop_back();
+ if(r1.type == RPN_NUMBER && r2.type == RPN_NUMBER)
+ stack.push_back(RPN_VALUE(r2.data >> r1.data,RPN_NUMBER));
+ else cerr << "Was not expecting a non-numeric value for operator >>" << endl;
+ break;
+
+ case TRUE_OP: //dg003a
+ stack.push_back(rpn_true);
+ break;
+
+ case FALSE_OP: //dg003a
+ stack.push_back(rpn_false);
+ break;
+
+ default:
+ cerr << "Invalid operator " << op << endl;
+ break;
+ }
+ }
+ else if((*i) & NUMBER)
+ {
+ uint32_t size = 0;
+ uint64_t data = iv_symbols->get_numeric_data(*i,size);
+ stack.push_back(RPN_VALUE(data,RPN_NUMBER));
+ }
+ else if((*i) & SYMBOL) // variables and cini enums
+ {
+ std::string name = iv_symbols->find_name(*i);
+ SYMBOL_VAL_LIST::iterator vvi = i_varlist.begin();
+ for(; vvi != i_varlist.end(); ++vvi)
+ {
+ if(name == vvi->first)
+ {
+ // cerr << name << " = " << vvi->second << endl;
+ stack.push_back(RPN_VALUE((uint64_t)vvi->second,RPN_NUMBER));
+ break;
+ }
+ }
+ if(vvi == i_varlist.end())
+ {
+ // cerr << name << " = ANY" << endl;
+ stack.push_back(RPN_VALUE(RPN_ANY));
+ }
+ }
+ }
+ // an empty RPN is true, if it's not empty then check for false
+ if(stack.size())
+ {
+ RPN_VALUE r = stack.back();
+ if(r.type == RPN_FALSE) result = false;
+ }
+ return result;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+uint8_t Rpn::extract8(BINSEQ::const_iterator & bli)
+{
+ uint8_t val;
+ val += (uint8_t)(*bli++);
+ return val;
+}
+
+
+//-------------------------------------------------------------------------------------------------
+
+uint16_t Rpn::extract16(BINSEQ::const_iterator & bli)
+{
+ uint16_t val;
+ val = ((uint16_t)(*bli++)) << 8;
+ val += (uint16_t)(*bli++);
+ return val;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+uint32_t Rpn::extract32(BINSEQ::const_iterator & bli)
+{
+ uint32_t val = extract16(bli);
+ val <<= 16;
+ val += extract16(bli);
+ return val;
+}
+
+
+//-------------------------------------------------------------------------------------------------
+
+uint64_t Rpn::extract64(BINSEQ::const_iterator & bli)
+{
+ uint64_t val = extract32(bli);
+ val <<= 32;
+ val += extract32(bli);
+ return val;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void Rpn::set8(BINSEQ & bl, uint8_t v)
+{
+ bl.push_back((uint8_t)(v));
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void Rpn::set16(BINSEQ & bl, uint16_t v)
+{
+ bl.push_back((uint8_t)(v >> 8));
+ bl.push_back((uint8_t)(v));
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void Rpn::set32(BINSEQ & bl, uint32_t v)
+{
+ bl.push_back((uint8_t)(v >> 24));
+ bl.push_back((uint8_t)(v >> 16));
+ bl.push_back((uint8_t)(v >> 8));
+ bl.push_back((uint8_t)(v));
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void Rpn::set64(BINSEQ & bl, uint64_t v)
+{
+ bl.push_back((uint8_t)(v >> 56));
+ bl.push_back((uint8_t)(v >> 48));
+ bl.push_back((uint8_t)(v >> 40));
+ bl.push_back((uint8_t)(v >> 32));
+ bl.push_back((uint8_t)(v >> 24));
+ bl.push_back((uint8_t)(v >> 16));
+ bl.push_back((uint8_t)(v >> 8));
+ bl.push_back((uint8_t)(v));
+}
+
+
+//-------------------------------------------------------------------------------------------------
+
+
OpenPOWER on IntegriCloud