diff options
Diffstat (limited to 'src/usr/hwpf/ifcompiler/initRpn.C')
-rwxr-xr-x | src/usr/hwpf/ifcompiler/initRpn.C | 1396 |
1 files changed, 0 insertions, 1396 deletions
diff --git a/src/usr/hwpf/ifcompiler/initRpn.C b/src/usr/hwpf/ifcompiler/initRpn.C deleted file mode 100755 index 1679d38c6..000000000 --- a/src/usr/hwpf/ifcompiler/initRpn.C +++ /dev/null @@ -1,1396 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/usr/hwpf/ifcompiler/initRpn.C $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2011,2014 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* 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 -// camvanng 01/06/12 Support for writing an attribute to a SCOM register -// camvanng 01/20/12 Support for using a range of indexes for array attributes -// camvanng 04/16/12 Support defines for SCOM address -// Support defines for bits, scom_data and attribute columns -// Delete obsolete code for defines support -// camvanng 05/07/12 Support for associated target attributes -// camvanng 05/22/12 Ability to do simple operations on attributes -// in the scom_data column -// SW146714 camvanng 06/08/12 Use two bytes to store row rpn sequence byte count -// camvanng 06/15/12 Ability to do bitwise OR and AND operations -// camvanng 06/27/12 Improve error and debug tracing -// End Change Log ********************************************************************************* -// $Id: initRpn.C,v 1.11 2014/06/30 19:56:40 thi Exp $ -/** - * @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> -#include <cstring> -#include <fapiHwpInitFileInclude.H> // Requires file from hwpf - -extern void yyerror(const char * s); - -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 - "BITWISEAND", - "BITWISEOR", -}; - -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 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); - - iv_rpnstack.push_back(rpn_id); - - //If this is an associated target's attribute, - //Add the target number as a numerical literal - size_t pos = s.find(ASSOC_TGT_ATTR); - if (pos != string::npos) - { - size_t len = ASSOC_TGT_ATTR.length(); - pos = s.find('.'); - if ((pos != string::npos) && (pos > len)) - { - uint32_t targetNum = strtoul(s.substr(len, pos-len).c_str(), NULL, 0); - //printf("Rpn::push_id: Target# %u\n", targetNum); - push_int(targetNum); - } - else - { - std::ostringstream oss; - oss << "Rpn::push_id: Invalid associated target attribute " << i_id.c_str(); - yyerror(oss.str().c_str()); - } - } -} - -//------------------------------------------------------------------------------------------------- - -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_num_idx = 0; - std::vector<string> l_idxstr; - - // find index strings in comma separated list and save in vector - size_t l_pos = 0; - l_pos = l_idx.find(','); - while(l_pos != string::npos) - { - l_idxstr.push_back(l_idx.substr(0, l_pos)); - l_idx = l_idx.substr(l_pos+1); - l_pos = l_idx.find(','); - } - - // Push back the original idx string or the last string in the list - l_idxstr.push_back(l_idx); - - uint32_t l_array_val = 0, l_array_val2 = 0; - uint32_t rpn_id = 0; - for (size_t i = 0; i < l_idxstr.size(); i++) - { - //Is it a range? - l_pos = l_idxstr.at(i).find(".."); - if (l_pos != string::npos) - { - l_array_val = atoi(l_idxstr.at(i).substr(0,l_pos).c_str()); - l_array_val2 = atoi(l_idxstr.at(i).substr(l_pos + 2).c_str()); - //printf("I>Rpn::push_array_index: %u..%u\n", l_array_val, l_array_val2); - if (l_array_val >= l_array_val2) - { - std::ostringstream oss; - oss << "Rpn::push_array_index: Invalid attribute array index range: " - << l_idxstr.at(i); - yyerror(oss.str().c_str()); - } - - for (uint32_t val = l_array_val; val <= l_array_val2; val++) - { - l_num_idx++; - rpn_id = iv_symbols->find_numeric_array_lit(val,4); - iv_rpnstack.push_back(rpn_id); - //printf("Array Index: %u rpn_id:0x%8X\n", val, rpn_id); - } - } - else - { - l_num_idx++; - l_array_val = atoi(l_idxstr.at(i).c_str()); - 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_idxstr.at(i).c_str(),l_array_val,rpn_id); - } - } - - // Save the index range for this rpn - if (iv_array_idx_range.size()) - { - if (iv_array_idx_range.back() != l_num_idx) - { - std::ostringstream oss; - oss << "Rpn::push_array_index: Array attribute has different range of index " - << "for each dimension: " << i_array_idx << " iv_array_idx_range: " - << iv_array_idx_range.back() << " l_num_idx: " << l_num_idx; - yyerror(oss.str().c_str()); - } - } - else - { - iv_array_idx_range.push_back(l_num_idx); - } - - //printf("Rpn::push_array_index: %s, iv_array_idx_range.size %u\n", i_array_idx.c_str(), iv_array_idx_range.size()); -} - -//------------------------------------------------------------------------------------------------- - -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(); - iv_array_idx_range.clear(); - return merge(i_rpn); // merge deletes i_rpn - } - if(i_rpn->isFalse() || this->isFalse()) - { - iv_rpnstack.clear(); - iv_array_idx_range.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(); - iv_array_idx_range.clear(); - return merge(i_rpn); // merge deletes i_rpn - } - if(i_rpn->isTrue() || this->isTrue()) - { - iv_rpnstack.clear(); - iv_array_idx_range.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(); - iv_array_idx_range.clear(); - push_op(TRUE_OP); - delete i_rpn; - return result; - } - if((op == EQ && *i_rpn == r3) || (op == NE && *i_rpn == r2)) - { - iv_rpnstack.clear(); - iv_array_idx_range.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()); - for (size_t i = 0; i < i_rpn->iv_array_idx_range.size(); i++) - { - iv_array_idx_range.push_back(i_rpn->iv_array_idx_range.at(i)); - } - 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()); - for (size_t i = 0; i < i_rpn->iv_array_idx_range.size(); i++) - { - iv_array_idx_range.push_back(i_rpn->iv_array_idx_range.at(i)); - } - delete i_rpn; - return this; -} - -//------------------------------------------------------------------------------------------------- -// See header file for contract -void Rpn::bin_read(BINSEQ::const_iterator & bli, uint16_t i_size, Symbols * symbols) -{ - - if(symbols) iv_symbols = symbols; - iv_rpnstack.clear(); - iv_array_idx_range.clear(); - - while(i_size) - { - uint32_t v = *bli++; - --i_size; - if(v < LAST_OP) // operator - { - if(v == LIST) - { - --i_size; - v |= (*bli++) << 8; - } - iv_rpnstack.push_back(v | OPERATION); - } - else // tag - { - v = (v << 8) + (*bli++); - --i_size; - - uint32_t l_rpn_id = iv_symbols->get_rpn_id(v); - iv_rpnstack.push_back(l_rpn_id); - - //Check for attribute of array type - if (v & IF_ATTR_TYPE) - { - //Check for associated target attribute - if ((v & IF_TYPE_MASK) == IF_ASSOC_TGT_ATTR_TYPE) - { - v = *bli++; - v = (v << 8) + (*bli++); - i_size -= 2; - iv_rpnstack.push_back(iv_symbols->get_rpn_id(v)); - //printf("Rpn::bin_read: Assoc target attribute id 0x%x\n", v); - } - - //Get the attribute dimension & shift it to the LS nibble - uint32_t l_type = iv_symbols->get_attr_type(l_rpn_id); - uint8_t l_attrDimension = (static_cast<uint8_t>(l_type) & ATTR_DIMENSION_MASK) >> 4; - for(uint8_t i=0; i < l_attrDimension; i++) - { - v = *bli++; - v = (v << 8) + (*bli++); - iv_rpnstack.push_back(iv_symbols->get_rpn_id(v)); - i_size -= 2; - } - } - } - } -} - -//------------------------------------------------------------------------------------------------- -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::bin_read_one_id(BINSEQ::const_iterator & io_bli, Symbols * i_symbols) -{ - if(i_symbols) iv_symbols = i_symbols; - - uint32_t v = *io_bli++; - if(v < LAST_OP) // operator - { - std::ostringstream errss; - errss << "Rpn::bin_read_one_id: This is an op 0x" << hex << v << endl; - throw std::invalid_argument(errss.str()); - } - - // not op - always two bytes - v = (v << 8) + (*io_bli++); - - uint32_t l_rpn_id = iv_symbols->get_rpn_id(v); - iv_rpnstack.push_back(l_rpn_id); - - //Check for attribute of array type - if (v & IF_ATTR_TYPE) - { - //Check for associated target attribute - if ((v & IF_TYPE_MASK) == IF_ASSOC_TGT_ATTR_TYPE) - { - v = *io_bli++; - v = (v << 8) + (*io_bli++); - iv_rpnstack.push_back(iv_symbols->get_rpn_id(v)); - //printf("Rpn::bin_read_one_id: Assoc target attribute id 0x%x\n", v); - } - - //Get the attribute dimension & shift it to the LS nibble - uint32_t l_type = iv_symbols->get_attr_type(l_rpn_id); - uint8_t l_attrDimension = (static_cast<uint8_t>(l_type) & ATTR_DIMENSION_MASK) >> 4; - for(uint8_t i=0; i < l_attrDimension; i++) - { - v = *io_bli++; - v = (v << 8) + (*io_bli++); - iv_rpnstack.push_back(iv_symbols->get_rpn_id(v)); - } - } -} - -//------------------------------------------------------------------------------------------------- - -void Rpn::append(const Rpn & i_rpn) -{ - iv_rpnstack.insert(iv_rpnstack.end(), i_rpn.iv_rpnstack.begin(), i_rpn.iv_rpnstack.end()); - for (size_t i = 0; i < i_rpn.iv_array_idx_range.size(); i++) - { - iv_array_idx_range.push_back(i_rpn.iv_array_idx_range.at(i)); - } -} - -//------------------------------------------------------------------------------------------------- - -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' << "Numerical Literal" << std::endl; - } - } - else if((*i) & ARRAY_INDEX) - { - uint32_t size = 0; - uint64_t data = iv_symbols->get_numeric_array_data(*i,size); - if(i_final) - { - uint32_t tag = iv_symbols->get_numeric_array_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' << "Numerical Literal (array index)" << 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); - - if (val & 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; - } - } - - //Skip size and desc for empty desc string and SYMBOL literal - if(i_desc && (0 == strlen(i_desc)) && (iv_rpnstack.front() & SYMBOL)) - { - 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(); -} - -//------------------------------------------------------------------------------------------------- - -// binary version to write to file -void Rpn::bin_str(BINSEQ & o_blist, uint32_t i_num_addrs, uint32_t i_addr_num, - bool i_prepend_count, bool i_one_byte_count) -{ - BINSEQ blist; - uint32_t count = 0; - uint32_t l_num_idx = 0; //number of array index in the range - uint32_t l_num_array_attrs = 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)); - } - l_num_idx = 0; //reset - break; - - case SYMBOL: tag = iv_symbols->get_tag(v); - blist.push_back((uint8_t)(tag >> 8)); - blist.push_back((uint8_t) tag); - count += 2; - l_num_idx = 0; //reset - 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; - l_num_idx = 0; //reset - break; - case ARRAY_INDEX: - //Check if this rpn has any array attribute with a range of index specified - if ((0 == l_num_idx) && iv_array_idx_range.size()) - { - if (iv_array_idx_range.size() > l_num_array_attrs) - { - l_num_idx = iv_array_idx_range.at(l_num_array_attrs); - l_num_array_attrs++; - - //Error if index range is not equal to address range - if ((1 < l_num_idx) && (l_num_idx != i_num_addrs)) - { - std::ostringstream errss; - errss << "Rpn::bin_str: Index range " << l_num_idx - << " != Address range " << i_num_addrs << endl; - throw std::invalid_argument(errss.str()); - } - } - } - - if (0 == l_num_idx) - { - //Error if no index range specified - std::ostringstream errss; - errss << "Rpn::bin_str: No index range specified for array attribute\n"; - throw std::invalid_argument(errss.str()); - } - - if (1 < l_num_idx) - { - v = *(i + i_addr_num); - if ((v & TYPE_MASK) != ARRAY_INDEX) - { - std::ostringstream errss; - errss << "Rpn::bin_str: Rpn 0x" << hex << v - << " is not array index " << endl; - throw std::invalid_argument(errss.str()); - } - } - tag = iv_symbols->get_numeric_array_tag(v); - blist.push_back((uint8_t)(tag >> 8)); - blist.push_back((uint8_t) tag); - count += 2; - if (1 < l_num_idx) //Skip the other indexes in the range - { - i += l_num_idx - 1; - } - break; - - default: - std::ostringstream errss; - errss << "Rpn::bin_str: Invalid Rpn type: 0x" << hex << v << endl; - throw std::invalid_argument(errss.str()); - break; - } - } - - //std::cout << "Rpn::bit_str(): iv_rpnstack size: " << iv_rpnstack.size() << std::endl; - //std::cout << " Rpn::bit_str(): rpn byte count: " << count << std::endl; - if (i_prepend_count) - { - if (true == i_one_byte_count) - { - //Expect count <= 255 - if (0xFF < count) - { - std::ostringstream errss; - errss << "Rpn::bin_str: count " << count << " > 0xFF\n"; - throw std::invalid_argument(errss.str()); - } - - o_blist.push_back((uint8_t) count); - } - else - { - //Expect count <= 65535 - if (0xFFFF < count) - { - std::ostringstream errss; - errss << "Rpn::bin_str: count " << count << " > 0xFFFF\n"; - throw std::invalid_argument(errss.str()); - } - - o_blist.push_back((uint8_t)(count >> 8)); - 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 = 0; - val += (uint8_t)(*bli++); - return val; -} - - -//------------------------------------------------------------------------------------------------- - -uint16_t Rpn::extract16(BINSEQ::const_iterator & bli) -{ - uint16_t val = 0; - 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)); -} - - -//------------------------------------------------------------------------------------------------- - - |