summaryrefslogtreecommitdiffstats
path: root/src/usr/hwpf/ifcompiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/hwpf/ifcompiler')
-rwxr-xr-xsrc/usr/hwpf/ifcompiler/initCompiler.C311
-rwxr-xr-xsrc/usr/hwpf/ifcompiler/initCompiler.H106
-rwxr-xr-xsrc/usr/hwpf/ifcompiler/initCompiler.lex364
-rwxr-xr-xsrc/usr/hwpf/ifcompiler/initCompiler.y299
-rwxr-xr-xsrc/usr/hwpf/ifcompiler/initRpn.C1136
-rwxr-xr-xsrc/usr/hwpf/ifcompiler/initRpn.H303
-rwxr-xr-xsrc/usr/hwpf/ifcompiler/initScom.C1372
-rwxr-xr-xsrc/usr/hwpf/ifcompiler/initScom.H247
-rwxr-xr-xsrc/usr/hwpf/ifcompiler/initSymbols.C1056
-rwxr-xr-xsrc/usr/hwpf/ifcompiler/initSymbols.H269
10 files changed, 5463 insertions, 0 deletions
diff --git a/src/usr/hwpf/ifcompiler/initCompiler.C b/src/usr/hwpf/ifcompiler/initCompiler.C
new file mode 100755
index 000000000..de8553e6c
--- /dev/null
+++ b/src/usr/hwpf/ifcompiler/initCompiler.C
@@ -0,0 +1,311 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/ifcompiler/initCompiler.C,v $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2010,2010
+//
+//UNDEFINED
+//
+// Origin: UNDEFINED
+//
+// IBM_PROLOG_END_TAG
+// Change Log *************************************************************************************
+//
+// Flag Track Userid Date Description
+// ----- -------- -------- -------- -------------------------------------------------------------
+// D754106 dgilbert 06/14/10 Create
+// dg002 SW039868 dgilbert 10/15/10 Add support to filter unneeded inits by EC
+// dg003 D779902 dgilbert 12/08/10 Add ability to specify ouput if file
+// andrewg 05/24/11 Port over for VPL/PgP
+// andrewg 09/19/11 Updates based on review
+// mjjones 11/17/11 Output attribute listing
+// End Change Log *********************************************************************************
+
+/**
+ * @file initCompiler.C
+ * @brief Compile an initfile into bytecode.
+ */
+#include <stdint.h>
+#include <stdio.h>
+#include <string>
+#include <sstream>
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+#include <map>
+#include <stdexcept>
+#include <initCompiler.H>
+#include <initRpn.H>
+#include <initSymbols.H>
+#include <initScom.H>
+//#include <initSpy.H>
+
+using namespace init;
+using namespace std;
+
+//Globals
+
+int yyline = 1;
+init::ScomList * yyscomlist = NULL;
+
+ostringstream init::dbg;
+ostringstream init::erros;
+ostringstream init::stats; // TODO move to Parser
+
+// Main
+int main(int narg, char ** argv)
+{
+ int rc = 0;
+
+#if 0
+ yyin = fopen("sample.initfile","r");
+ if(!yyin)
+ {
+ std::cerr << "\nERROR: Failed to open sample.initfile! " << std::endl;
+ exit(-1);
+ }
+ yyparse();
+ fclose(yyin);
+#endif
+
+ try
+ {
+ // Parser:
+ // - Parse args
+ // - Set up source location and source type
+ // - Load & parse Symbols & Spy/Array tables
+ // - Load & parse the initfile (if there is one)
+ //
+ Parser parsed(narg,argv);
+
+ string initfile = parsed.source_fn();
+ uint32_t type = parsed.get_source_type();
+
+ BINSEQ bin_seq;
+ bin_seq.reserve(0x38000);
+
+ if(type == Parser::IF_TYPE) // input is binary *.if file - build listing from it.
+ {
+
+ //for(SPY_LIST::iterator i = yyspylist->begin(); i != yyspylist->end(); ++i)
+ //{
+ // cout << (*i)->listing() << endl;
+ //}
+
+ ifstream ifs(initfile.c_str(), ios_base::in | ios_base::binary);
+ if(!ifs)
+ {
+ string msg("Can't open ");
+ msg.append(initfile);
+ throw invalid_argument(msg);
+ }
+ while(1)
+ {
+ int ch = ifs.get();
+ if (!(ifs.good())) break;
+ bin_seq.push_back(ch);
+ }
+ ifs.close();
+
+ yyscomlist->listing(bin_seq, cout);
+
+ erros << parsed.get_scomlist()->get_symbols()->not_found_listing();
+
+ }
+ else // normal initfile processing
+ {
+ // Already parsed
+ yyscomlist->compile(bin_seq);
+
+
+ std::cerr << "Compiled size = " << std::dec << bin_seq.size() << endl;
+
+ // if there are missing symbols, SpyList::listing() will add duplicates
+ // So get the listing now
+ erros << parsed.get_scomlist()->get_symbols()->not_found_listing();
+
+ string if_fn = parsed.binseq_fn();
+ ofstream ofs(if_fn.c_str(), ios_base::out | ios_base::binary);
+ if(!ofs)
+ {
+ erros << "ERROR - Could not open" << if_fn << endl;
+ throw invalid_argument(if_fn);
+ }
+ else
+ {
+ for(BINSEQ::const_iterator bli = bin_seq.begin(); bli != bin_seq.end(); ++bli)
+ ofs.put((char)(*bli));
+
+ ofs.close();
+ }
+ //cout << dbg << std::endl;
+ printf("Generate Listing\n");
+ // This builds a listing from the compiled binary sequence
+ yyscomlist->listing(bin_seq, parsed.listing_ostream());
+ yyscomlist->attr_listing(bin_seq, parsed.attr_listing_ostream());
+
+ // open if file and read in to new SpyList
+
+ printf("Generate Stats\n");
+ stats << "*********************************************************\n";
+
+ cerr << stats.str() << endl; // TODO -> cout
+
+ }
+
+ printf("Generate Debug\n");
+ parsed.capture_dbg();
+ //if(parsed.debug_mode()) cout << dbg.str() << endl;
+ }
+ catch(exception & e)
+ {
+ cerr << "ERROR! exception caught: " << e.what() << endl;
+ rc = 2;
+ }
+
+ if(erros.str().size())
+ {
+ rc = 1;
+ cerr << erros.str() << endl;
+ }
+ return rc;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Parser:
+// Check the args and build the symbol table
+// -----------------------------------------------------------------------------------------------
+
+Parser::Parser(int narg, char ** argv)
+: iv_type(0), iv_scomlist(NULL), iv_dbg(false), iv_ec(0xFFFFFFFF) //dg002c
+{
+ set<string> header_files;
+ iv_prog_name = argv[0];
+
+ stats << iv_prog_name << endl;
+ --narg; ++argv;
+
+ string type;
+
+ pair<string,string> compare;
+
+ for(int i = 0; i < narg; ++i)
+ {
+ string arg(argv[i]);
+ if(arg.compare(0,5,"-init") == 0) iv_source_path = argv[++i];
+ else if (arg.compare(0,3,"-kw") == 0 ||
+ arg.compare(0,4,"-spy") == 0 ||
+ arg.compare(0,5,"-attr") == 0 ||
+ arg.compare(0,6,"-array") == 0 ) header_files.insert(string(argv[++i]));
+ else if (arg.compare(0,7,"-outdir") == 0) iv_outdir = argv[++i];
+ else if (arg.compare(0,2,"-o") == 0) iv_outfile = argv[++i]; //dg003a
+ else if (arg.compare(0,3,"-if") == 0) iv_source_path = argv[++i];
+ else if (arg.compare(0,3,"-ec") == 0) iv_ec = strtoul(argv[++i],NULL,16); //dg002a
+ else if (arg.compare(0,9,"--compare") == 0)
+ {
+ compare.first = argv[++i];
+ compare.second = argv[++i];
+ }
+ else if (arg.compare(0,7,"--debug") == 0) iv_dbg = true;
+
+ }
+ if(iv_source_path.size() == 0) iv_source_path = compare.first;
+
+ if(!narg) // TEST MODE
+ {
+ iv_source_path = "p7.initfile";
+ header_files.insert("p7_init_spies.h");
+ header_files.insert("p7_init_arrays.h");
+ header_files.insert("ciniIfSymbols.H");
+ }
+
+ size_t pos = iv_source_path.rfind('.');
+ if(pos != string::npos)
+ {
+ string type = iv_source_path.substr(pos+1);
+ if(type.compare(0,2,"if") == 0) iv_type = IF_TYPE;
+ else if(type.compare(0,8,"initfile") == 0) iv_type = INITFILE_TYPE;
+
+ size_t pos1 = iv_source_path.rfind('/',pos);
+ if(pos1 == string::npos) pos1 = 0;
+ else ++pos1;
+
+ iv_initfile = iv_source_path.substr(pos1,pos-pos1);
+ }
+
+ if(iv_outdir.length() == 0) iv_outdir.push_back('.');
+ if(iv_outdir.at(iv_outdir.size()-1) != '/') iv_outdir.push_back('/');
+
+ if(iv_outfile.size() == 0)
+ {
+ iv_outfile.append(iv_initfile);
+ iv_outfile.append(".if");
+ }
+
+ iv_outfile.insert(0,iv_outdir);
+
+ stats << "*********************************************************" << endl;
+ stats << "* source: " << iv_source_path << endl;
+ stats << "* listing: " << listing_fn() << endl;
+ stats << "* attr: " << attr_listing_fn() << endl;
+ stats << "* binary: " << binseq_fn() << endl;
+
+ iv_scomlist = new ScomList(iv_source_path, header_files, stats, iv_ec); //dg002c
+ if(compare.second.size())
+ {
+ ScomList cmplist(compare.second, header_files, stats, iv_ec); //dg002c
+ if(iv_scomlist->compare(cmplist))
+ {
+ cout << "Compare SUCCESS" << endl;
+ }
+ else
+ {
+ cout << stats;
+ }
+ }
+
+ iv_list_ostream.open(listing_fn().c_str());
+ if(!iv_list_ostream)
+ {
+ throw invalid_argument(string("ERROR! Could not open ") + listing_fn());
+ }
+
+ iv_attr_list_ostream.open(attr_listing_fn().c_str());
+ if(!iv_attr_list_ostream)
+ {
+ throw invalid_argument(string("ERROR! Could not open ") + attr_listing_fn());
+ }
+}
+
+Parser::~Parser()
+{
+ iv_list_ostream.close();
+ iv_attr_list_ostream.close();
+}
+
+void Parser::capture_dbg()
+{
+ if(iv_dbg)
+ {
+ string fname(iv_outdir);
+ fname.append(iv_initfile);
+ fname.append(".dbg");
+ ofstream dbgfs(fname.c_str());
+ if(!dbgfs)
+ {
+ string msg("Can't open ");
+ msg.append(fname);
+ throw invalid_argument(msg);
+ }
+ dbgfs << dbg.str() << endl;
+ dbgfs.close();
+ }
+}
+
+// TODO
+// - Detect all errors down to a line # ?
+// - bad rows/cols check - have already?
+//
diff --git a/src/usr/hwpf/ifcompiler/initCompiler.H b/src/usr/hwpf/ifcompiler/initCompiler.H
new file mode 100755
index 000000000..d49c8e136
--- /dev/null
+++ b/src/usr/hwpf/ifcompiler/initCompiler.H
@@ -0,0 +1,106 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/ifcompiler/initCompiler.H,v $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2010,2010
+//
+//UNDEFINED
+//
+// Origin: UNDEFINED
+//
+// IBM_PROLOG_END_TAG
+#if !defined(INITCOMPILER_H)
+#define INITCOMPILER_H
+
+// Change Log *************************************************************************************
+//
+// Flag Track Userid Date Description
+// ----- -------- -------- -------- -------------------------------------------------------------
+// D754106 dgilbert 06/14/10 Create
+// dg002 SW039868 dgilbert 10/15/10 Add support to filter unneeded inits by EC
+// dg003 D779902 dgilbert 12/08/10 Ability to specify output if file
+// andrewg 05/24/11 Port over for VPL/PgP
+// andrewg 09/19/11 Updates based on review
+// mjjones 11/17/11 Output attribute listing
+// End Change Log *********************************************************************************
+
+/**
+ * @file initCompiler.H
+ * @brief Compile an initfile into bytecode.
+ */
+
+#include <initRpn.H>
+#include <initScom.H>
+#include <set>
+#include <string>
+#include <fstream>
+
+using namespace std;
+
+
+// bison & flex globals
+
+extern int yyline;
+extern FILE * yyin;
+extern int yyparse();
+void yyerror(const char * s);
+extern init::ScomList * yyscomlist;
+
+namespace init
+{
+
+
+ extern ostringstream dbg; // debug (verbose) output
+ extern ostringstream erros; // error output stream
+ extern ostringstream stats; // Misc info to be displayed
+
+
+
+ class Parser
+ {
+ public:
+
+ enum
+ {
+ IF_TYPE = 1,
+ INITFILE_TYPE = 2
+ };
+
+ Parser(int narg, char ** argv);
+ ~Parser();
+
+ string listing_fn() { return (binseq_fn()).append(".list"); }
+ string attr_listing_fn() { return (binseq_fn()).append(".attr"); }
+ string source_fn() { return iv_source_path; }
+ string binseq_fn() { return iv_outfile; } //dg003a
+ //{ string s(iv_outdir); s.append(iv_initfile); s.append(".if"); return s; } //dg003d
+ uint32_t get_source_type() { return iv_type; }
+
+ ostream & listing_ostream() { return iv_list_ostream; }
+ ostream & attr_listing_ostream() { return iv_attr_list_ostream; }
+
+ ScomList * get_scomlist() { return iv_scomlist; } // TODO refactor this out
+ bool debug_mode() { return iv_dbg; }
+
+ void capture_dbg(); // if iv_dbg then dump the dbg stringstream to a file
+
+ private:
+ string iv_prog_name;
+ string iv_source_path;
+ string iv_initfile;
+ string iv_outdir;
+ string iv_outfile; //dg003a
+ ofstream iv_list_ostream;
+ ofstream iv_attr_list_ostream;
+ uint32_t iv_type;
+ ScomList * iv_scomlist;
+ bool iv_dbg;
+ uint32_t iv_ec; // ec filter (if there is one) dg002a
+
+ };
+}
+
+#endif
diff --git a/src/usr/hwpf/ifcompiler/initCompiler.lex b/src/usr/hwpf/ifcompiler/initCompiler.lex
new file mode 100755
index 000000000..9abdaded3
--- /dev/null
+++ b/src/usr/hwpf/ifcompiler/initCompiler.lex
@@ -0,0 +1,364 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* fips740 src/engd/initfiles/ifcompiler/initCompiler.lex 1.2 */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* OBJECT CODE ONLY SOURCE MATERIALS */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2010 */
+/* All Rights Reserved */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/* Change Log *************************************************************************************
+//
+// Flag Track Userid Date Description
+// ---- -------- -------- -------- -------------------------------------------------------------
+// D754106 dgilbert 06/14/10 Create
+// dg01 D766229 dgilbert 08/03/10 add check for hex/bin data > 64 bits
+// dg02 SW058986 dgilbert 02/28/11 More noticeable fail for missing col headers
+// andrewg 09/19/11 Updates based on review
+// camvanng 11/08/11 Added support for attribute enums
+// End Change Log *********************************************************************************/
+/**
+ * @file initCompiler.lex
+ * @brief Contains the rules for the lex/flex lexical scanner for scanning initfiles
+ *
+ * This code runs as part of the build process to generate a
+ * byte-coded representation of an initfile
+ */
+%{
+#include <stdint.h>
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+#include <vector>
+#include <initRpn.H>
+#include <y.tab.h>
+
+uint64_t bits2int( const char * bitString);
+uint64_t hexs2int(const char * hexString, int32_t size);
+void pushBackScomBody();
+void push_col(const char *s);
+void lex_err(const char *s );
+
+std::ostringstream oss;
+std::ostringstream t_oss;
+
+typedef std::vector<std::ostringstream *> OSS_LIST;
+OSS_LIST g_colstream;
+
+inline void clear_colstream()
+{ for( OSS_LIST::iterator i = g_colstream.begin(); i != g_colstream.end(); ++i) delete *i;
+ g_colstream.clear();
+}
+uint32_t g_scomcol;
+uint32_t g_coltype = 0;
+uint32_t g_scomtype = 0;
+uint32_t g_paren_level = 0;
+bool g_equation = false; // equation inside scomv col
+std::string g_scomname; // dg02
+
+extern int yyline;
+
+%}
+
+
+
+
+NEWLINE \n
+FILENAME [A-Za-z][A-Za-z0-9_\.]*
+ID [A-Za-z][A-Za-z0-9_]*
+ID2 [A-Za-z][A-Za-z0-9_]*
+ID3 [0-9]+[A-Za-z_]+[0-9]*
+DIGIT [0-9]
+COMMENT #.*\n
+OP "="|"+"|"-"|"|"|"<"|">"|"*"|"/"|"%"
+FLOAT [0-9]+"."[0-9]*
+BINARY 0[bB][0-1]+
+SCOM_DATA [ ]*[scom_data][ ]+
+HEX 0[xX][A-Fa-f0-9]+
+SINGLE_HEX [A-Fa-f0-9]
+ATTRIBUTE [\[[A-Fa-f0-9]\]]
+MULTI_DIGIT [0-9]+
+
+%x scomop
+%x scomop_array
+%x scomop_suffix
+%x scomdata
+%x when_kw
+%x when_expr
+%x scomcolname
+%x scomrow
+%x list
+%x enumcol
+%x fnames
+%x target
+%x attribute
+%x array
+
+
+%%
+
+{COMMENT} ++yyline; /* toss comments - need first line */
+\$Id:.*\n ++yyline; /* toss this - read by initCompiler.C */
+
+ /* Special end-of-file character. */
+<<EOF>> { return 0; }
+
+SyntaxVersion return INIT_VERSION;
+
+ /* The list of initfile versions is just copied into the *.if file
+ * so just make it one chunk of string data */
+Versions BEGIN(fnames);
+<fnames>[=] oss.str("");
+<fnames>{FLOAT} oss << yytext;
+<fnames>[:] oss << yytext;
+<fnames>[,] oss << ", ";
+<fnames>{FILENAME} oss << yytext;
+<fnames>{NEWLINE} { ++yyline;
+ yylval.str_ptr = new std::string(oss.str());
+ BEGIN(INITIAL);
+ return INIT_VERSIONS;
+ }
+
+define { return INIT_DEFINE;}
+
+
+scom { BEGIN(scomop); oss.str(""); return INIT_SCOM; }
+
+<scomop>{HEX} {
+ yylval.str_ptr = new std::string(yytext);
+ oss.str("");
+ return INIT_SCOM_ADDR;
+ }
+
+<scomop>[\(] {BEGIN(scomop_array); return yytext[0];}
+
+<scomop_array>{SINGLE_HEX}+ {
+ yylval.str_ptr = new std::string(yytext);
+ oss.str("");
+ return INIT_INT64_STR;
+ }
+
+<scomop_array>[\)] {BEGIN(scomop_suffix); return(yytext[0]);}
+
+<scomop_suffix>{SINGLE_HEX}+ {
+ yylval.str_ptr = new std::string(yytext);
+ oss.str("");
+ BEGIN(scomop);
+ return INIT_SCOM_SUFFIX;
+ }
+
+<scomop>[:;\[] { BEGIN(INITIAL); g_coltype = 0; return yytext[0]; }
+<scomop>{NEWLINE} { BEGIN(INITIAL); ++yyline; }
+
+<scomop,scomop_suffix>[\{] {
+ oss.str("");
+ BEGIN(scomcolname);
+ return yytext[0];
+ }
+
+
+
+ /* The column & row format is really hard to handle in the parser,
+ * especially since each column can have different parsing rules.
+ * So fix it here in the scanner by converting the format to
+ * coltitle1 , row1, row2, ..., row n ;
+ * coltitle2 , row1, row2, ..., row n ;
+ * then push it all back into the input stream and scan the new format
+ */
+
+<scomcolname>{COMMENT} ++yyline;
+<scomcolname>\n ++yyline;
+<scomcolname>{ID} {
+ g_colstream.push_back(new std::ostringstream());
+ *(g_colstream.back()) << yytext;
+ }
+<scomcolname>, {}
+<scomcolname>; { BEGIN(scomrow); g_scomcol = 0; }
+
+<scomrow>{COMMENT} ++yyline;
+<scomrow>{NEWLINE} ++yyline;
+<scomrow>[^,;\n#\{\}]+ push_col(yytext);
+<scomrow>[,] ++g_scomcol;
+<scomrow>[;] g_scomcol = 0;
+<scomrow>[\}] {
+ pushBackScomBody(); // create new format and put it back on yyin
+ BEGIN(INITIAL);
+ }
+
+
+ /* The scombody is the modified format - don't track yyline as it's already
+ * accounted for. Any errors in here will point back to the last line in the
+ * 'real' scombody
+ */
+
+bits { g_coltype = INIT_BITS; return INIT_BITS;}
+expr { g_coltype = INIT_EXPR; return INIT_EXPR;}
+scom_data { g_coltype = INIT_SCOMD; return INIT_SCOMD;}
+
+ /*HEX and Binary numbers in the scombody can be up to 64bit,
+ * decimal numbers will always fit in 32bit int */
+
+{BINARY} { yylval.uint64 = bits2int(yytext); return INIT_INT64; }
+
+<*>; { g_coltype = 0; return ';'; }
+
+END_INITFILE return INIT_ENDINITFILE;
+
+<*>ENUM_{ID} {
+ yylval.str_ptr = new std::string(yytext); return ATTRIBUTE_ENUM;
+ }
+
+<*>{ID} {
+ yylval.str_ptr = new std::string(yytext); return INIT_ID;
+ }
+
+<*>{DIGIT}+ {
+ sscanf(yytext, "%d", &yylval.integer); return INIT_INTEGER;
+ }
+
+<*>{HEX} {
+ // normal right-justified 64 bit hex integer
+ yylval.uint64 = hexs2int(yytext,yyleng);
+ return INIT_INT64;
+ }
+
+<*>"&&" return INIT_LOGIC_AND;
+<*>"||" return INIT_LOGIC_OR;
+<*>"==" return INIT_EQ;
+<*>"!=" return INIT_NE;
+<*>"<=" return INIT_LE;
+<*>">=" return INIT_GE;
+<*>">>" return INIT_SHIFT_RIGHT;
+<*>"<<" return INIT_SHIFT_LEFT;
+
+<*>{OP} { g_equation = true; return yytext[0]; }
+<*>[\(] { ++g_paren_level; return yytext[0]; }
+<*>[\)] { --g_paren_level; return yytext[0]; }
+
+<*>\[{MULTI_DIGIT}\] { yylval.str_ptr = new std::string(yytext); return ATTRIBUTE_INDEX; }
+
+<*>[\[\]\{\},:] {g_equation = false; return yytext[0]; }
+
+<*>[ \t\r]+ /* Eat up whitespace */
+[\n] { BEGIN(INITIAL);++yyline;}
+
+<*>. lex_err(yytext);
+
+%%
+
+int yywrap() { return 1; }
+
+void lex_err(const char *s )
+{
+ std::cerr << "\nERROR: " << s << " -line " << yyline << std::endl;
+}
+
+// Convert left justified bitstring to 64 bit integer
+uint64_t bits2int( const char * bitString)
+{
+ uint32_t idx = 0;
+ uint64_t mask = 0x8000000000000000ull;
+ uint64_t val = 0;
+ do
+ {
+ if( (bitString[0] != '0') ||
+ ((bitString[1] != 'b') && (bitString[1] != 'B')))
+ {
+ lex_err("Invalid bit string");
+ break;
+ }
+ idx = 2;
+
+ while( bitString[idx] != 0 )
+ {
+ char c = bitString[idx];
+ if( c == '1') val |= mask;
+ else if(c != '0')
+ {
+ lex_err("Invalid bit string");
+ break;
+ }
+ ++idx;
+ mask >>= 1;
+ }
+ if(idx > 66) //dg01a 64bits + "0B" prefix
+ lex_err("Bit string greater than 64 bits!");
+
+ } while (0);
+ return val;
+}
+
+// Convert left justified hex string to 64 bit integer
+uint64_t hexs2int(const char * hexString, int32_t size)
+{
+ uint64_t val = 0;
+ std::string s(hexString);
+ if(size > 18) //dg01a
+ {
+ lex_err("HEX literal greater than 64 bits");
+ size = 18;
+ }
+ s.append(18-size,'0'); // 0x + 16 digits
+ val = strtoull(s.c_str(),NULL,16);
+ return val;
+}
+
+void pushBackScomBody()
+{
+ std::ostringstream ost;
+ for(OSS_LIST::iterator i = g_colstream.begin(); i != g_colstream.end(); ++i)
+ {
+ ost << (*i)->str() << ';';
+ }
+ ost << '}';
+ std::string t = ost.str(); // Was causing weird stuff if I didn't copy the string out first
+ //std::cout << "<lex comment> Pushing:" << t << std::endl;
+ //std::cout << "<lex comment> " << std::endl;
+
+ for(std::string::reverse_iterator r = t.rbegin();
+ r != t.rend();
+ ++r)
+ {
+ //std::cout << *r;
+ unput(*r);
+ }
+ //std::cout << std::endl;
+ clear_colstream();
+}
+
+
+/// help collect column data
+void push_col(const char * s)
+{
+ //dg02a begin
+ while(g_scomcol >= g_colstream.size()) // more data cols than headers cols
+ {
+ // This will force an error in the parser where it can stop the compile.
+ g_colstream.push_back(new std::ostringstream());
+ *(g_colstream.back()) << "MISSING_COLUMN_HEADER";
+ lex_err(g_scomname.c_str());
+ lex_err("Invalid number of scom cols");
+ }
+ //dgxxa end
+ //dgxxd remove if(g_colstream < g_colstream.size()
+
+ std::ostringstream & o = *(g_colstream[g_scomcol]);
+ std::ostringstream token;
+ std::istringstream iss(s);
+ std::string t;
+ //std::cout << "Pushing ";
+ while(iss >> t) token << t; // get rid of white space
+ if(token.str().size()) // don't add blank tokens
+ {
+ //std::cout << "Pushing ," << token.str() << std::endl;
+ o << ',' << token.str();
+ }
+}
diff --git a/src/usr/hwpf/ifcompiler/initCompiler.y b/src/usr/hwpf/ifcompiler/initCompiler.y
new file mode 100755
index 000000000..4c8da2ca3
--- /dev/null
+++ b/src/usr/hwpf/ifcompiler/initCompiler.y
@@ -0,0 +1,299 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* fips730 src/engd/initfiles/ifcompiler/initCompiler.y 1.1 */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* OBJECT CODE ONLY SOURCE MATERIALS */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2010 */
+/* All Rights Reserved */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* IBM_PROLOG_END_TAG */
+// Change Log *************************************************************************************
+//
+// Flag Track Userid Date Description
+// ---- -------- -------- -------- -------------------------------------------------------------
+// D754106 dgilbert 06/14/10 Create
+// D774126 dgilbert 09/30/10 Add ERROR: to yyerror message
+// andrewg 09/19/11 Updates based on review
+// camvanng 11/08/11 Added support for attribute enums
+// andrewg 11/09/11 Refactor to use common include with hwp framework.
+// End Change Log *********************************************************************************
+/**
+ * @file initCompiler.y
+ * @brief Contains the yacc/bison code for parsing an initfile.
+ *
+ * This code runs as part of the build process to generate a
+ * byte-coded representation of an initfile
+ */
+%{
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string>
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+#include <initCompiler.H>
+#include <initSymbols.H>
+
+
+init::Scom * current_scom = NULL;
+
+extern int yylex();
+void yyerror(const char * s);
+
+int scom;
+
+%}
+
+/* Union for the yylval variable in lex or $$ variables in bsion code.
+ * Used to store the data associated with a parsed token.
+ */
+%union{
+ uint32_t integer;
+ uint64_t uint64;
+ std::string * str_ptr;
+ init::Rpn * rpn_ptr;
+}
+
+ /* indicates the name for the start symbol */
+%start input
+
+ /* Define terminal symbols and the union type
+ * associated with each. */
+
+%token <integer> INIT_INTEGER
+%token <uint64> INIT_INT64
+%token <str_ptr> INIT_INT64_STR
+%token <str_ptr> INIT_SCOM_ADDR
+%token <str_ptr> INIT_SCOM_SUFFIX
+%token <uint64> INIT_SCOM_DATA
+%token <str_ptr> INIT_ID
+%token <str_ptr> INIT_VERSIONS
+%token <str_ptr> ATTRIBUTE_INDEX
+%token <str_ptr> ATTRIBUTE_ENUM
+
+
+ /* Define terminal symbols that don't have any associated data */
+
+%token INIT_VERSION
+%token INIT_ENDINITFILE
+%token INIT_BITS
+%token INIT_EXPR
+%token INIT_TARG
+%token INIT_DEFINE
+%token INIT_EQ
+%token INIT_NE
+%token INIT_LE
+%token INIT_GE
+%token INIT_SCANINIT
+%token INIT_SCOMINIT
+%token INIT_SCOM
+%token INIT_SCOMD
+
+
+ /* non-terminal tokens and the union data-type associated with them */
+
+%type <str_ptr> bitsrows
+%type <rpn_ptr> expr id_col num_list
+
+
+
+
+
+/* top is lowest precedent - done last */
+%left ATTRIBUTE_INDEX /* irrelevant precedence, but needed for clean compile */
+%left INIT_LOGIC_OR
+%left INIT_LOGIC_AND
+%left '|' /* bitwise OR */
+%left '^' /* bitwise XOR */
+%left '&' /* bitwise AND */
+%left INIT_EQ INIT_NE
+%left INIT_LE INIT_GE '<' '>'
+%left INIT_SHIFT_RIGHT INIT_SHIFT_LEFT
+%left '-' '+'
+%left '*' '/' '%'
+%right '!' '~' /* logic negation bitwise complement*/
+/* bottom is highest precedent - done first */
+
+
+
+
+%%
+/* Grammars */
+ /* the 'input' is simply all the lines */
+input:
+ | input line
+;
+
+line: scom
+ | cvs_versions
+ | syntax_version
+ | define
+ | INIT_ENDINITFILE { yyscomlist->clear_defines(); }
+;
+
+
+cvs_versions: INIT_VERSIONS
+ {
+ yyscomlist->set_cvs_versions($1); delete $1;
+ }
+;
+
+syntax_version: INIT_VERSION '=' INIT_INTEGER
+ {
+ yyscomlist->set_syntax_version($3);
+ }
+;
+
+scom: INIT_SCOM {current_scom = new init::Scom(yyscomlist->get_symbols(),yyline);}
+ | scom scomaddr '{' scombody '}'
+ {
+ /* printf("Found an INIT_SCOM!\n"); */
+ /* current_scom = new init::Scom(yyscomlist->get_symbols(),yyline); */
+ }
+;
+
+scomaddr:
+ | INIT_SCOM_ADDR {
+ /*printf("Found an INIT_SCOM_ADDR 0x%X!\n",$1);*/
+ current_scom->set_scom_address(*($1)); delete $1;
+ yyscomlist->insert(current_scom);
+ }
+ | scomaddr '(' scom_list ')' { }
+ | scomaddr '(' scom_list ')' INIT_SCOM_SUFFIX { current_scom->set_scom_suffix(*($5)); delete $5; }
+;
+
+
+scom_list: INIT_INT64_STR { current_scom->dup_scom_address(*($1));delete $1;}
+ | scom_list ',' INIT_INT64_STR { current_scom->dup_scom_address(*($3));delete $3;}
+;
+
+
+ /* The scombody was reformatted by the scanner
+ * colname1 , row1 , row 2, ... , row n ;
+ * colname2 , row1 , row 2, ... , row n ;
+ */
+
+scombody: scombodyline ';' {}
+ | scombody scombodyline ';' {}
+;
+
+scombodyline: INIT_SCOMD ',' scomdrows {}
+ | INIT_BITS ',' bitsrows {}
+ | INIT_EXPR ',' exprrows { init::dbg << "Add col EXPR" << endl; current_scom->add_col("EXPR"); }
+ | INIT_ID ',' idrows {
+ current_scom->add_col(*($1));
+ init::dbg << "Add col " << *($1) << endl;
+ delete $1;
+ }
+
+;
+
+
+scomdrows: expr {
+ /*printf("scomdrows - RPN Address:0x%X\n",$1);*/
+ init::dbg << $1->listing("Length scom RPN");
+ current_scom->add_scom_rpn($1);
+ }
+ | scomdrows ',' expr { init::dbg << $3->listing("Length scom RPN"); current_scom->add_scom_rpn($3); }
+;
+
+
+/*
+scomdrows: id_col { printf("scomdrows\n"); }
+;
+*/
+
+bitsrows: bitrange {}
+ | bitsrows ',' bitrange {}
+;
+
+bitrange: INIT_INTEGER { current_scom->add_bit_range($1,$1); }
+ | INIT_INTEGER ':' INIT_INTEGER
+ { current_scom->add_bit_range($1,$3); }
+;
+
+exprrows: expr { init::dbg << $1->listing(NULL); current_scom->add_row_rpn($1); }
+ | exprrows ',' expr
+ { init::dbg << $3->listing(NULL); current_scom->add_row_rpn($3); }
+;
+
+idrows: id_col { init::dbg << $1->listing(NULL); current_scom->add_row_rpn($1); }
+ | idrows ',' id_col { init::dbg << $3->listing(NULL); current_scom->add_row_rpn($3); }
+;
+
+
+ // TODO num_list could be VARs,LITs, or even ranges eg {1,2..5,7}
+
+id_col: INIT_ID { $$ = new init::Rpn(*($1),yyscomlist->get_symbols()); $$->push_op(EQ); delete $1; }
+ | INIT_INTEGER { $$ = new init::Rpn($1,yyscomlist->get_symbols()); $$->push_op(EQ); }
+ | '{' num_list '}' { $$ = $2; $2->push_op(LIST); $2->push_op(EQ); }
+ | ATTRIBUTE_ENUM { $$ = new init::Rpn((yyscomlist->get_symbols())->get_attr_enum_val(*($1)),yyscomlist->get_symbols()); $$->push_op(EQ); delete $1; }
+;
+
+
+
+num_list: INIT_INTEGER { $$ = new init::Rpn($1,yyscomlist->get_symbols()); }
+ | INIT_ID { $$ = new init::Rpn(*($1),yyscomlist->get_symbols()); }
+ | num_list ',' INIT_INTEGER { $$ = $1; $1->merge(new init::Rpn($3,yyscomlist->get_symbols())); }
+ | num_list ',' INIT_ID { $$ = $1; $1->merge(new init::Rpn(*($3),yyscomlist->get_symbols())); }
+ | ATTRIBUTE_ENUM { $$ = new init::Rpn((yyscomlist->get_symbols())->get_attr_enum_val(*($1)),yyscomlist->get_symbols()); }
+;
+
+
+define: INIT_DEFINE INIT_ID '=' expr ';'
+ {
+ init::dbg << $2 << ':' << endl << $4->listing("Length of rpn for Define");
+ yyscomlist->add_define($2,$4);
+ delete $2;
+ }
+;
+
+ /* expr should return an RPN string of some kind */
+expr: INIT_INTEGER { $$= new init::Rpn($1,yyscomlist->get_symbols()); }
+ | INIT_ID { $$= new init::Rpn(*($1),yyscomlist->get_symbols()); delete $1; }
+ | ATTRIBUTE_ENUM { $$= new init::Rpn((yyscomlist->get_symbols())->get_attr_enum_val(*($1)),yyscomlist->get_symbols()); delete $1; }
+ | INIT_INT64 { $$=new init::Rpn($1,yyscomlist->get_symbols()); }
+ | expr ATTRIBUTE_INDEX { $1->push_array_index(*($2));}
+ | expr INIT_LOGIC_OR expr { $$ = $1->push_merge($3,OR); }
+ | expr INIT_LOGIC_AND expr { $$ = $1->push_merge($3,AND); }
+ | expr INIT_EQ expr { $$ = $1->push_merge($3,EQ); }
+ | expr INIT_NE expr { $$ = $1->push_merge($3,NE); }
+ | expr INIT_LE expr { $$ = $1->push_merge($3,LE); }
+ | expr INIT_GE expr { $$ = $1->push_merge($3,GE); }
+ | expr '<' expr { $$ = $1->push_merge($3,LT); }
+ | expr '>' expr { $$ = $1->push_merge($3,GT); }
+ | expr INIT_SHIFT_RIGHT expr { $$ = $1->push_merge($3,SHIFTRIGHT); }
+ | expr INIT_SHIFT_LEFT expr { $$ = $1->push_merge($3,SHIFTLEFT); }
+ | expr '+' expr { $$ = $1->push_merge($3,PLUS); }
+ | expr '-' expr { $$ = $1->push_merge($3,MINUS); }
+ | expr '*' expr { $$ = $1->push_merge($3,MULT); }
+ | expr '/' expr { $$ = $1->push_merge($3,DIVIDE); }
+ | expr '%' expr { $$ = $1->push_merge($3,MOD); }
+ | '!' expr { $$ = $2->push_op(NOT); }
+ | '(' expr ')' { $$ = $2; }
+;
+
+
+%%
+
+void yyerror(const char * s)
+{
+ init::erros << setfill('-') << setw(80) << '-' << endl;
+ init::erros << setfill('0');
+ init::erros << "Parse Error line " << dec << setw(4) << yyline << ": yychar = "
+ << dec << (uint32_t) yychar << " [0x" << hex << (uint32_t) yychar << "] '";
+ if(isprint(yychar)) init::erros << (char)yychar;
+ else init::erros << ' ';
+ init::erros << "' yylval = " << hex << "0x" << setw(8) << yylval.integer << endl;
+ init::erros << "ERROR: " << s << endl;
+ init::erros << setfill('-') << setw(80) << '-' << endl << endl;
+}
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));
+}
+
+
+//-------------------------------------------------------------------------------------------------
+
+
diff --git a/src/usr/hwpf/ifcompiler/initRpn.H b/src/usr/hwpf/ifcompiler/initRpn.H
new file mode 100755
index 000000000..5eba73c62
--- /dev/null
+++ b/src/usr/hwpf/ifcompiler/initRpn.H
@@ -0,0 +1,303 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/ifcompiler/initRpn.H,v $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2010,2010
+//
+//UNDEFINED
+//
+// Origin: UNDEFINED
+//
+// IBM_PROLOG_END_TAG
+#if !defined(INITRPN_H)
+#define INITRPN_H
+
+// Change Log *************************************************************************************
+//
+// Flag Reason Userid Date Description
+// ---- -------- -------- -------- -------------------------------------------------------------
+// D754106 dgilbert 06/14/10 Create
+// dgilbert 10/15/10 Add support to filter unneeded inits by EC
+// dg002 SW039868 dgilbert 10/15/10 Add support to filter unneeded inits by EC
+// dg003 SW047506 dgilbert 12/09/10 SERIES filtering
+// 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.H
+ * @brief Declaration of the initRpn class. Handles Reverse Polish Notation equations for initfiles
+ */
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+#include <map>
+#include <fapiHwpInitFileInclude.H>
+
+
+namespace init
+{
+ class Symbols;
+
+ typedef std::vector<uint8_t> BINSEQ;
+
+ typedef std::pair<std::string,uint32_t> SYMBOL_VAL_PAIR;
+ typedef std::vector<SYMBOL_VAL_PAIR> SYMBOL_VAL_LIST;
+
+ class Rpn
+ {
+ public:
+
+ enum TYPE
+ {
+ DEFINE = 0x08000000,
+ SYMBOL = 0x10000000,
+ NUMBER = 0x20000000,
+ ARRAY_INDEX = 0x40000000,
+ OPERATION = 0x80000000,
+ TYPE_MASK = 0xF8000000,
+
+ };
+
+ /**
+ * @brief Create empty RPN
+ *
+ */
+ Rpn() : iv_symbols(NULL) {}
+
+ /**
+ * @brief Create empty RPN w/ symbol table
+ *
+ * @param[in] i_symbols Pointer to Symbol Table
+ */
+ Rpn(Symbols * i_symbols) : iv_symbols(i_symbols) {}
+
+ /**
+ * @brief Create empty RPN w/ symbol table and input integer
+ *
+ * @param[in] i_int Integer to populate RPN with
+ * @param[in] i_symbols Pointer to Symbol Table
+ */
+ Rpn(uint32_t i_int, Symbols * i_symbols);
+
+ Rpn(uint64_t i_int, Symbols * symbols); //<<< Create RPN with single 64 bit integer
+ Rpn(std::string i_id, Symbols * symbols, TYPE i_type=SYMBOL); //<<< Create RPN with single symbol
+ Rpn(BINSEQ::const_iterator & bli, Symbols * symbols) //<<< Create RPN from binary sequence
+ : iv_symbols(symbols) { bin_read(bli); }
+
+ /**
+ * Compare two Rpn sequences for equivalence
+ * @note Currently the two Rpn sequences must use the same symbol table to be considered equal.
+ * @note TODO: Allow different symbol tables and resolve the symbols before comparing.
+ */
+ bool operator==(const Rpn & r);
+ bool operator!=(const Rpn & r) { return !(this->operator==(r)); }
+
+ void push_int(uint32_t i_val); //<<< Add a 32 bit integer to the Rpn sequence
+ void push_id(std::string & i_id, TYPE i_type=SYMBOL); //<<Add a symbol or Spy enum to the Rpn sequence
+ void push_int64(uint64_t i_uint); //<<< Add a 64 bit integer to the Rpn sequence
+
+ /**
+ * @brief Add an attribute array index
+ *
+ * @param[in] i_array_idx Array index for this attribute
+ *
+ * @return Void
+ */
+ void push_array_index(std::string &i_array_idx);
+
+ /**
+ * @brief Add an attribute enum
+ *
+ * @param[in] i_attr_enum attribute enum name
+ *
+ * @return Void
+ */
+ void push_attr_enum(std::string &i_attr_enum);
+
+ Rpn * push_op(IfRpnOp op); //<<< Add an operation to the Rpn sequence
+
+ /**
+ * @brief Merge an Rpn to this Rpn sequence with input operation
+ *
+ * @param[inout] io_rpn Input RPN to merge into this one. Will be deleted.
+ * @param[in] i_op Operation to perform between the 2 RPN's
+ *
+ * @return Merged RPN
+ */
+ Rpn * push_merge(Rpn * io_rpn, IfRpnOp i_op);
+
+ /**
+ * Merge (append) Rpn with this Rpn sequence
+ * @returns this
+ * @post i_rpn is deleted
+ */
+ Rpn * merge(Rpn * i_rpn);
+
+ /**
+ * Append a copy of an Rpn sequence to this Rpn sequence
+ */
+ void append(const Rpn & i_rpn);
+
+ void append(uint32_t i_rpn_id) { iv_rpnstack.push_back(i_rpn_id); }
+
+ /**
+ * isTrue returns true if the RPN has a single element that is RPN_TRUE
+ * @note Used in RPN optimization
+ */
+ bool isTrue() const; //dg003a
+
+ /**
+ * isFalse returns true if the RPN has a single element that is RPN_FALSE
+ * @note Used in RPN optimization
+ */
+ bool isFalse() const; //dg003a
+
+ void clear() { iv_rpnstack.clear(); } //<<< clear the sequence
+
+ /**
+ * Human readable listing of RPN string
+ * @param String Description to use; NULL -> use default: "n BYTES"
+ * @param bool i_final true: convert cini symbol id's to offset tags
+ * @returns string
+ * @NOTE i_final should never be set to true until all symbols in the
+ * init file have been "looked up"
+ */
+ std::string listing(const char * i_desc,
+ const std::string & spyname = cv_empty_str,
+ bool i_final = false);
+
+ std::string symbol_names() const; //<<< Return a string of all the SYMBOL names in the Rpn
+
+ /**
+ * @brief Push all RPN stack entries of object as numerical values onto input blist
+ *
+ * @param blist Binary string of RPN to write to file
+ * @param i_prepend_count Flag to indicate prepend rpn count to binary string
+ * @PRE should never be called until all symbols in the initfile have been
+ * "looked up" or the binary tags for Symbols and Numbers may not be accurate
+ * @return void
+ */
+ void bin_str(BINSEQ & blist, bool i_prepend_count = false);
+
+ /**
+ * Read binary sequence to recreate this Rpn sequence
+ * @param bineary sequence interator
+ * @param symbol table to use
+ * @pre first byte in binary sequence is the size of the rpn sequence in bytes
+ * @post if symbols != NULL then iv_rpnstack is replaced
+ * @post iv_symbols is replace with symbols
+ */
+ void bin_read(BINSEQ::const_iterator & bli, Symbols * symbols = NULL); // read binary sequence to recreate RPN
+
+ /**
+ * Copy one rpn operation from bli and add to this Rpn sequence
+ * @returns an iterator one past the last byte used.
+ * @param iterator of a binary rpn sequence
+ * @param symbol table to use.
+ * @pre bli points to a valid rpn sequence - ie the correct number of PUSHES for the operand
+ * @post this Rpn sequence is appended
+ * @post Internal symbol table ptr is replace with given symbol table ptr if not NULL
+ * @note Reads byte sequence from bli sequence until an operation is found.
+ * @note The input sequence should NOT have a size byte on the front
+ */
+ BINSEQ::const_iterator bin_read_one_op(BINSEQ::const_iterator & bli, Symbols * symbols = NULL); // read one rpn operation from bli to create Rpn
+
+ //dg002a
+ /**
+ * Resolve the RPN and returns false if the given EC level causes the RPN expression to be false.
+ * @returns true | false
+ * @note This routine will always return true unless the RPN contains an EC comparison that resolves to false.
+ */
+ bool resolve_ec(uint32_t i_ec);
+
+ //dg003a
+ /**
+ * Resove as much of the RPN as possible, given the list of Symbol -> value substitutions. Result is true until proven false.
+ * @returns true | false. False is returned if the Rpn is unconditionally false; otherwise true is returned.
+ * @note Any Symbol found in the RPN not included in i_varlist resolves to ANY. All comparison operands to ANY resolves to true
+ * @code
+ * // Example 1
+ * SYMBOL_VAL_PAIR p(string("EC"),0x10);
+ * SYMBOL_VAL_LIST lst;
+ * lst.push_back(p);
+ * if(anRpn.resolve(lst)) { .... }
+ * // In this example, any instants of the variable "EC" in the RPN will be replaced with the value 0x10.
+ * // Any other variables will be set to ANY and the RPN will be evaluated.
+ * // if the RPN does not contain the variable "EC", it will resolve to true.
+ *
+ * // Example 2
+ * SYMBOL_VAL_PAIR p1(string("SERIES"),0xA000006C);
+ * SYMBOL_VAL_PAIR p2(string("SERIES_IP"),0xA000006C);
+ * SYMBOL_VAL_PAIR p3(string("SERIES_Z"),0xA000006D);
+ * SYMBOL_VAL_LIST lst;
+ * lst.push_back(p1);
+ * lst.push_back(p2);
+ * lst.push_back(p3);
+ * if(anRpn.resolve(lst)) {.....} // resolves to false if rpn contains SERIES == SERIES_Z
+ * // or SERIES != SERIES_IP
+ * @endcode
+ */
+ bool resolve(SYMBOL_VAL_LIST & i_varlist);
+
+
+ uint32_t op_count() const { return iv_rpnstack.size(); }
+
+ // Helper functions in reading and writing binary sequences (compiled initfiles *.if)
+ static uint8_t extract8(BINSEQ::const_iterator & bli);
+ static uint16_t extract16(BINSEQ::const_iterator & bli);
+ static uint32_t extract32(BINSEQ::const_iterator & bli);
+ static uint64_t extract64(BINSEQ::const_iterator & bli);
+ static void set8(BINSEQ & bl, uint8_t v);
+ static void set16(BINSEQ & bl, uint16_t v);
+ static void set32(BINSEQ & bl, uint32_t v);
+ static void set64(BINSEQ & bl, uint64_t v);
+
+ static std::string cv_empty_str;
+
+ private: // types and data
+ typedef std::vector<uint32_t> RPNSTACK;
+
+ RPNSTACK iv_rpnstack; ///< Rpn sequence
+ Symbols * iv_symbols; ///< Symbol table to use
+
+
+
+
+ //dg002a begin Used in resolve operations to interpret the Rpn sequence
+ enum RPN_TYPE
+ {
+ RPN_NUMBER = 0,
+ RPN_FALSE = 1,
+ RPN_TRUE = 2,
+ RPN_ANY = 3,
+ };
+
+ // Used in resolve operations to interpret the Rpn sequence
+ struct RPN_VALUE
+ {
+ uint64_t data;
+ RPN_TYPE type;
+ RPN_VALUE() : data(0), type(RPN_NUMBER) {}
+ RPN_VALUE(RPN_TYPE i_type) : data(0), type(i_type) {}
+ RPN_VALUE(uint64_t i_data, RPN_TYPE i_type) : data(i_data), type(i_type) {}
+ RPN_VALUE(uint64_t i_data) : data(i_data), type(RPN_NUMBER) {}
+ };
+
+ typedef std::vector<RPN_VALUE> EVAL_STACK;
+
+ private: // functions
+
+ // Used in resolve operations to interpret the Rpn sequence
+ static void pop_bool(EVAL_STACK & i_stack, RPN_VALUE & o_value);
+ static void pop_number(EVAL_STACK & i_stack, RPN_VALUE & o_value);
+ // dg002a end
+ };
+};
+
+#endif
diff --git a/src/usr/hwpf/ifcompiler/initScom.C b/src/usr/hwpf/ifcompiler/initScom.C
new file mode 100755
index 000000000..b37c05182
--- /dev/null
+++ b/src/usr/hwpf/ifcompiler/initScom.C
@@ -0,0 +1,1372 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/ifcompiler/initScom.C,v $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2010,2010
+//
+//UNDEFINED
+//
+// Origin: UNDEFINED
+//
+// IBM_PROLOG_END_TAG
+
+// Change Log *************************************************************************************
+//
+// Flag Track Userid Date Description
+// ----- -------- -------- -------- -------------------------------------------------------------
+// D754106 dgilbert 06/14/10 Create
+// dg001 D774126 dgilbert 09/30/10 Check that colname EXPR is last column in spytable
+// dg002 SW039868 dgilbert 10/15/10 Add support to filter unneeded inits by EC
+// dg003 SW047506 dgilbert 12/09/10 More filtering enhancements
+// andrewg 05/24/11 Port over for VPL/PgP
+// andrewg 09/19/11 Updates based on review
+// andrewg 11/09/11 Multi-dimensional array and move to common fapi include
+// mjjones 11/17/11 Output attribute listing
+// End Change Log *********************************************************************************
+
+/**
+ * @file initSpy.C
+ * @brief Definition of the initScom Class. Represents the information parsed from an initfile scom
+ * statement.
+ */
+
+#include <initScom.H>
+#include <initSymbols.H>
+#include <initCompiler.H>
+#include <stdlib.h>
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+#include <fstream>
+#include <set>
+#include <stdexcept>
+
+extern void yyerror(const char * s);
+extern init::ScomList * yyscomlist; // only use this during parsing
+
+namespace init {
+extern ostringstream dbg; // debug output
+};
+
+using namespace init;
+
+Scom::WHEN_SUBTYPE_MAP Scom::cv_when_subtypes;
+
+//-------------------------------------------------------------------------------------------------
+
+Scom::Scom(BINSEQ::const_iterator & bli, Symbols * i_symbols):
+ iv_symbols(i_symbols),
+ iv_when(NONE),
+ iv_scom_length(0),
+ iv_scom_offset(0),
+ iv_when_rpn(i_symbols)
+
+{
+
+ iv_scom_length = Rpn::extract16(bli);
+ iv_scom_offset = Rpn::extract16(bli);
+ uint32_t id = Rpn::extract16(bli);
+ uint32_t numcols = Rpn::extract16(bli);
+ uint32_t numrows = Rpn::extract16(bli);
+
+ numcols &= ~SUBTYPE_MASK;
+
+ // Get our SCOM address
+ uint32_t l_addr_size = 0;
+ iv_scom_addr_hex = iv_symbols->get_numeric_data(iv_symbols->get_rpn_id(id),l_addr_size);
+
+
+ if( iv_scom_length != 0 && iv_scom_length != 0xffff) // most common values
+ {
+ if(iv_scom_length < 65) // max scom len is 64 bits
+ {
+ for(size_t i = 0; i < numrows; ++i)
+ add_bit_range(iv_scom_offset, iv_scom_offset + iv_scom_length - 1);
+ }
+ else // What's this?
+ {
+ ostringstream errs;
+ errs << "ERROR: Invalid scom bit length [" << iv_scom_length << "]" << endl;
+ throw range_error(errs.str());
+ }
+ }
+
+ for(size_t i = 0; i < numrows; ++i)
+ {
+ Rpn rpn(bli,iv_symbols);
+ iv_scom_rpn.push_back(rpn);
+ }
+
+ if(numcols)
+ {
+ for(size_t i = 0; i < numrows; ++i) iv_row_rpn.push_back(Rpn(iv_symbols)); // blank RPNs
+
+ // Read col heads
+ for(size_t i = 0; i < numcols; ++i)
+ {
+ uint32_t var_tag = Rpn::extract16(bli);
+ Rpn col_name_rpn(iv_symbols);
+ col_name_rpn.append(iv_symbols->get_rpn_id(var_tag));
+ iv_col_vars.push_back(col_name_rpn);
+ iv_cols_rpn.push_back(iv_row_rpn); // copy in blank row RPNs for this column
+ }
+
+ for(size_t row_n = 0; row_n < numrows; ++row_n)
+ {
+ COL_LIST::iterator cli = iv_cols_rpn.begin(); // *cli is list of row rpns for col
+ RPN_LIST::iterator rpi = (*cli).begin() + row_n; // *rpi is current row rpn for first col
+ BINSEQ::const_iterator bli_end = bli + (*bli); // end of rpn in bin seq
+ ++bli; ++bli_end; // adjust for first byte being len
+ // The next len bytes belong to this row
+ // Simple cols are divided by OPs
+ // LIST op has two additional bytes (len,op)
+ while(bli < bli_end)
+ {
+ // Last col rpn is not limited to one op if it's "expr" - it gets the rest of the RPN
+ if(cli == (iv_cols_rpn.end() - 1))
+ {
+ while(bli < bli_end) bli = rpi->bin_read_one_op(bli);
+ break;
+ }
+ bli = rpi->bin_read_one_op(bli);
+ ++cli;
+ rpi = (*cli).begin() + row_n;
+ }
+ }
+ }
+ else ++bli;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void Scom::set_when(const string * when_str)
+{
+
+ string s(*when_str);
+ for(string::iterator c = s.begin(); c != s.end(); ++c) *c = toupper(*c);
+ if(s.size())
+ {
+ size_t i = 0;
+ for(size_t i = 1; i < sizeof(when_char)/sizeof(when_char[0]); ++i)
+ {
+ if(s[0] == when_char[i])
+ {
+ set_when((SCOM_WHEN)i);
+ break;
+ }
+ }
+ if(i == sizeof(when_char)/sizeof(when_char[0]))
+ {
+ string errs("Illegal when=");
+ errs.append(s);
+ yyerror(errs.c_str());
+ }
+ s.erase(0,1);
+
+ if(s.size())
+ {
+ WHEN_SUBTYPE_MAP::const_iterator i = cv_when_subtypes.find(s);
+ if(i != cv_when_subtypes.end())
+ {
+ set_sub_when(i->second);
+ }
+ else
+ {
+ std::ostringstream oss;
+ oss << "Illegal 'when=' subvalue: [" << s << ']';
+ yyerror(oss.str().c_str());
+ }
+ }
+ }
+ else
+ {
+ yyerror("Missing 'when =' value");
+ }
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void Scom::add_col(const string & i_colname)
+{
+ string s(i_colname);
+ for(string::iterator i = s.begin(); i != s.end(); ++i) *i = toupper(*i);
+ Rpn col_rpn(s,iv_symbols); // = iv_symbols->use_symbol(s);
+
+ // add check - Can't add any more cols after EXPR column dg001a
+ if(iv_col_vars.size() && s != "EXPR")
+ {
+ Rpn exp_rpn("EXPR",iv_symbols);
+ if(exp_rpn == iv_col_vars.back()) // expr col already added - can't add any more cols
+ {
+ yyerror("EXPR must be the last column");
+ }
+ }
+
+ // if the entire column is unconditionally true it can be left out
+ // This check will be done later as this scom might be split by bit-ranges.
+
+ iv_col_vars.push_back(col_rpn);
+ iv_cols_rpn.push_back(iv_row_rpn); // add the collected row RPNs
+ iv_row_rpn.clear();
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void Scom::add_row_rpn(Rpn * i_rpn)
+{
+ // The row gets parsed before the col name
+ // So collect the row RPNs and apply them when the col name gets added
+
+ // Replace the Rpn "ANY" EQ with TRUE dg003a
+ Rpn any_rpn("ANY",iv_symbols);
+ Rpn true_rpn(iv_symbols);
+ true_rpn.push_op(TRUE_OP);
+
+ // The column EXPR can have an lone "ANY" rpn - so add EQ.
+ if(any_rpn == (*i_rpn)) i_rpn->push_op(EQ);
+ any_rpn.push_op(EQ);
+
+ if(any_rpn == (*i_rpn)) iv_row_rpn.push_back(true_rpn); // Replace col == ANY with TRUE
+ else
+ {
+ iv_row_rpn.push_back(*i_rpn);
+ }
+ delete i_rpn;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void Scom::add_bit_range(uint32_t start, uint32_t end)
+{
+ // make sure they are added in order
+ dbg << "Add bit range " << start << " to " << end;
+ iv_range_list.push_back(RANGE(start,end));
+}
+
+//-------------------------------------------------------------------------------------------------
+// Range gets parsed before the target symbol (k,n,p,c) - so save it
+void Scom::add_target_range(uint32_t r1, uint32_t r2)
+{
+ if(r1 > r2)
+ {
+ uint32_t rt = r1;
+ r1 = r2;
+ r2 = rt;
+ }
+ iv_target_ranges.push_back(RANGE(r1,r2));
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void Scom::make_target(const char * i_symbol)
+{
+ string s(i_symbol);
+ Rpn r(iv_symbols);
+ size_t rsize = iv_target_ranges.size();
+
+ if(rsize == 0)
+ {
+ yyerror("Target given w/o a range");
+ }
+ // if more than one target - use list
+ else
+ {
+ for(RANGE_LIST::iterator iter = iv_target_ranges.begin(); iter != iv_target_ranges.end(); ++iter)
+ {
+ for(uint32_t v = iter->first; v <= iter->second; ++v)
+ {
+ r.push_int(v);
+ }
+ }
+ if(rsize > 1) r.push_op(LIST); // if more than one target
+ r.push_op(EQ);
+ }
+
+ iv_row_rpn.push_back(r);
+ add_col(s);
+ iv_target_ranges.clear();
+}
+
+//-------------------------------------------------------------------------------------------------
+
+string Scom::list_one(RANGE range)
+{
+ ostringstream oss;
+
+ uint32_t numcols = iv_col_vars.size() | (iv_when & SUBTYPE_MASK); // WHEN subtype goes in numcols
+ uint32_t bitlen = range.second + 1 - range.first;
+ if (bitlen)
+ {
+ iv_scom_length = bitlen; // don't overwrite iv_scom_length if bitlen == 0
+ iv_scom_offset = range.first; // don't overwrite iv_scom_offset if bitlen == 0
+ }
+
+ uint32_t allrows = 0;
+ uint32_t numrows = 0;
+
+ if(iv_cols_rpn.size()) allrows = iv_cols_rpn.front().size();
+ if (allrows == 0) allrows = 1;
+
+ // If there is a bit range we need to select only the rows that apply to this spyname
+ if(bitlen)
+ {
+ for(RANGE_LIST::iterator r = iv_range_list.begin(); r != iv_range_list.end(); ++r)
+ {
+ if((*r) == range) ++numrows;
+ }
+ }
+ else numrows = allrows; // else select all the rows
+
+ oss << hex << setfill('0');
+ oss << "------------";
+ oss << " Scom Address: 0x" << setw(16) << iv_scom_addr_hex;
+ if(bitlen)
+ {
+ oss << '~' << dec << range.first;
+ if(range.first != range.second) oss << ':' << range.second;
+ oss << hex;
+ }
+ oss << ' ' << "------------" << endl
+ << "When= " << (iv_when & WHEN_MASK) << endl;
+
+ oss << "0x" << setw(4) << iv_scom_length << "\t\t" << "Scom length" << endl
+ << "0x" << setw(4) << iv_scom_offset << "\t\t" << "Scom offset" << endl;
+
+ //oss << "0x" << setw(8) << iv_symbols->get_spy_id(spyname) << '\t';
+
+ oss << "0x" << setw(4) << numcols << "\t\t" << "Number of columns" << endl
+ << "0x" << setw(4) << numrows << "\t\t" << "Number of rows" << endl;
+
+ // If there is a bit range we need to select only the spyv rows that apply to this spyname
+
+ if(bitlen)
+ {
+ RPN_LIST::iterator i = iv_scom_rpn.begin();
+ for(RANGE_LIST::iterator r = iv_range_list.begin(); r != iv_range_list.end(); ++r,++i)
+ {
+ if ((*r) == range)
+ {
+ oss << i->listing("Length of rpn for spyv",Rpn::cv_empty_str,true);
+ }
+ }
+ }
+ else // get all rows
+ {
+ for(RPN_LIST::iterator i = iv_scom_rpn.begin(); i != iv_scom_rpn.end(); ++i)
+ {
+ oss << i->listing("Length of rpn for spyv",Rpn::cv_empty_str,true);
+ }
+ }
+ oss << endl;
+
+
+ // list the column names that are really CINI VARS
+ for(RPN_LIST::iterator i = iv_col_vars.begin(); i != iv_col_vars.end(); ++i)
+ {
+ oss << i->listing("",Rpn::cv_empty_str,true);
+ //Rpn col_rpn = *i;
+ //string desc = iv_symbols->find_name(rpn_id);
+ //if(desc.size() == 0) desc = "Variable not found!";
+
+ //oss << "0x" << setw(4) << iv_symbols->get_tag(*i) << "\t\t" << desc << endl;
+ }
+ oss << endl << endl;
+
+
+
+ uint32_t usedrows = 0;
+ if(iv_cols_rpn.size() == 0)
+ {
+ oss << "ROW " << 1 << "\n0x00" << "\t\t" << "0 BYTES" << endl;
+ }
+ else
+ {
+ for(size_t n = 0; n < allrows; ++n)
+ {
+ Rpn rpn(iv_symbols);
+ if(bitlen) // only get rows that match the current bitrange
+ {
+ if(iv_range_list[n] != range) continue;
+ }
+ ++usedrows;
+ oss << "ROW " << usedrows << endl;
+
+ // Build up the row Rpn for row n
+ for(COL_LIST::iterator i = iv_cols_rpn.begin(); i != iv_cols_rpn.end(); ++i)
+ {
+ rpn.append(i->at(n));
+ }
+ oss << rpn.listing(NULL,Rpn::cv_empty_str,true) << endl;
+ }
+ }
+
+ return oss.str();
+}
+
+//-------------------------------------------------------------------------------------------------
+
+string Scom::listing()
+{
+ ostringstream oss;
+
+ set<RANGE> ranges;
+ ranges.insert(iv_range_list.begin(),iv_range_list.end());
+
+ //oss << list_one(RANGE(1,0)) << endl;
+ if(ranges.size())
+ {
+ for(set<RANGE>::iterator r = ranges.begin(); r != ranges.end(); ++r)
+ {
+ oss << list_one(*r) << endl;
+ }
+ }
+ else
+ {
+ oss << list_one(RANGE(1,0)) << endl;
+ }
+
+ return oss.str();
+}
+
+//-------------------------------------------------------------------------------------------------
+
+uint32_t Scom::bin_listing(BINSEQ & blist)
+{
+ set<RANGE> ranges;
+ uint32_t scom_count = 0;
+
+ row_optimize(); // delete any rows that are unconditionally false. + merge rows
+
+ ranges.insert(iv_range_list.begin(),iv_range_list.end());
+
+ SCOM_ADDR::iterator i = iv_scom_addr.begin();
+ // if more than one spyname, the first is just the stem of the name - skip it
+ if(iv_scom_addr.size() > 1) ++i;
+
+ for(; i != iv_scom_addr.end(); ++i)
+ {
+ //printf("scom address:%s\n",(*i).c_str());
+ if(ranges.size())
+ {
+ for(set<RANGE>::iterator r = ranges.begin(); r != ranges.end(); ++r)
+ {
+ ++scom_count;
+ //bin_list_one(blist,*i,*r);
+ // The following sequence will optimize the bytecode for this spy
+ // - Compile the spy into bytecode for a range of bits
+ // - Recreate the spy from the bytecode
+ // - Compile the recreated spy back into bytecode.
+ BINSEQ temp;
+ bin_list_one(temp,strtoul((*i).c_str(),NULL,16), *r);
+ BINSEQ::const_iterator bi = temp.begin();
+ Scom s(bi,iv_symbols);
+ s.bin_list_one(blist,strtoul((*i).c_str(),NULL,16), RANGE(1,0));
+ }
+ }
+ else
+ {
+ ++scom_count;
+ bin_list_one(blist,strtoul((*i).c_str(),NULL,16), RANGE(1,0));
+ }
+ }
+
+ return scom_count;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void Scom::bin_list_one(BINSEQ & blist,uint64_t i_addr, RANGE range)
+{
+
+ uint32_t numcols = iv_col_vars.size() | (iv_when & SUBTYPE_MASK); // WHEN subtype goes in numcols
+
+// No range support
+ uint32_t bitlen = range.second + 1 - range.first;
+
+ if (bitlen)
+ {
+ iv_scom_length = bitlen; // don't overwrite iv_scom_length if bitlen == 0
+ iv_scom_offset = range.first; // don't overwrite iv_scom_offset if bitlen == 0
+ }
+
+ uint32_t allrows = 0;
+ uint32_t numrows = 0;
+
+ if(iv_cols_rpn.size()) allrows = iv_cols_rpn.front().size();
+ if (allrows == 0) allrows = 1;
+
+ // If there is a bit range we need to select only the rows that apply to this spyname
+ if(bitlen)
+ {
+ for(RANGE_LIST::iterator r = iv_range_list.begin(); r != iv_range_list.end(); ++r)
+ {
+ if((*r) == range) ++numrows;
+ }
+ }
+ else numrows = allrows; // else select all the rows
+
+ // If every row rpn in a column is unconditionally true then remove the col.
+ if(iv_col_vars.size())
+ {
+ vector< pair<RPN_LIST::iterator, COL_LIST::iterator> > deletes;
+ RPN_LIST::iterator cv = iv_col_vars.begin(); // -> column header Rpn
+ COL_LIST::iterator cr = iv_cols_rpn.begin(); // -> RPN list of row segments for the column
+ for(; cv != iv_col_vars.end(); ++cv,++cr)
+ {
+ bool remove_it = true;
+ for(RPN_LIST::const_iterator r = cr->begin(); r != cr->end(); ++r)
+ {
+ if(!(r->isTrue()))
+ {
+ remove_it = false;
+ break;
+ }
+ }
+ if(remove_it)
+ {
+ deletes.push_back( pair<RPN_LIST::iterator, COL_LIST::iterator>(cv,cr) );
+ }
+ }
+ while(deletes.size())
+ {
+ pair<RPN_LIST::iterator, COL_LIST::iterator> p = deletes.back();
+ deletes.pop_back();
+ dbg << "COL is unconditionally true. Removing column " << (p.first)->symbol_names()
+ << endl;
+ iv_col_vars.erase(p.first);
+ iv_cols_rpn.erase(p.second);
+ --numcols;
+ }
+ }
+
+ Rpn::set16(blist,(uint16_t)iv_scom_length);
+ Rpn::set16(blist,(uint16_t)iv_scom_offset);
+
+ // Just put the SCOM address in place of the spy id
+ //uint32_t id = iv_symbols->get_spy_id(spyname);
+ //Rpn::set32(blist,id);
+ // TODO - Probably need to get scom address id here
+ //Rpn::set32(blist,(uint32_t)iv_address);
+
+ Rpn *l_scom_addr = new init::Rpn(i_addr,yyscomlist->get_symbols());
+ l_scom_addr->bin_str(blist,false);
+ delete l_scom_addr;
+
+
+ Rpn::set16(blist,(uint16_t)numcols);
+ Rpn::set16(blist,(uint16_t)numrows);
+
+ // If there is a bit range we need to select only the spyv rows that apply to this spyname
+ if(bitlen)
+ {
+ RPN_LIST::iterator i = iv_scom_rpn.begin();
+ for(RANGE_LIST::iterator r = iv_range_list.begin(); r != iv_range_list.end(); ++r,++i)
+ {
+ if ((*r) == range)
+ {
+ i->bin_str(blist,false);
+ }
+ }
+ }
+ else // get all rows
+ {
+ for(RPN_LIST::iterator i = iv_scom_rpn.begin(); i != iv_scom_rpn.end(); ++i)
+ {
+ i->bin_str(blist,false);
+ }
+ }
+
+ // list the column names that are really CINI VARS
+ for(RPN_LIST::iterator i = iv_col_vars.begin(); i != iv_col_vars.end(); ++i)
+ {
+ i->bin_str(blist,false); // false means don't prepend an RPN byte count to the binary rpn appended.
+ //uint16_t tag = iv_symbols->get_tag(*i);
+ //blist.push_back((uint8_t)(tag >> 8));
+ //blist.push_back((uint8_t) tag);
+ }
+
+ if(iv_cols_rpn.size() == 0) blist.push_back(0);
+ else
+ {
+ for(size_t n = 0; n < allrows; ++n)
+ {
+ Rpn rpn(iv_symbols);
+ if(bitlen) // only get rows that match the current bitrange
+ {
+ if(iv_range_list[n] != range) continue;
+ }
+
+ // Build up the row Rpn for row n
+ for(COL_LIST::iterator i = iv_cols_rpn.begin(); i != iv_cols_rpn.end(); ++i)
+ {
+ rpn.append(i->at(n));
+ }
+ rpn.bin_str(blist,true);
+ }
+ }
+}
+
+//-------------------------------------------------------------------------------------------------
+// Delete any rows that are unconditionally false
+// Merge rows that can be merged
+//
+void Scom::row_optimize() //dg003a
+{
+ size_t row = 0;
+ if (iv_cols_rpn.size()) row = iv_cols_rpn.front().size();
+ if(row == 0) return;
+
+ // Look for false rows
+ do
+ {
+ bool remove_me = false;
+ --row;
+ for(COL_LIST::iterator i = iv_cols_rpn.begin(); i != iv_cols_rpn.end(); ++i)
+ {
+ if (i->at(row).isFalse())
+ {
+ remove_me = true;
+ break;
+ }
+ }
+ if(remove_me)
+ {
+ iv_scom_rpn.erase(iv_scom_rpn.begin() + row); //remove spyv
+ //Need to remove rpn row segment from each iv_cols_rpn rpn list
+ for(COL_LIST::iterator i = iv_cols_rpn.begin(); i != iv_cols_rpn.end(); ++i)
+ {
+ i->erase(i->begin() + row);
+ }
+ if(iv_range_list.size()) iv_range_list.erase(iv_range_list.begin() + row);
+
+ //dbg << "ROW is unconditionally false. Removing row " << row+1 << " from " << get_key_name() << endl;
+ }
+ } while (row);
+
+ // now look for rows to merge
+ // for now limit to spies with EXPR as the only column
+ // Because the interpreter looks down the rows until it finds one that's "true" then stops, the order
+ // of rows cant't be modified. This means only rows next to each other can be merged.
+ // This makes for very large Rpn strings - turn on later when we have better redundancy reduction in RPNs
+#if defined(__LATER__)
+ Rpn r_expr("EXPR", iv_symbols);
+ row = iv_spyv_rpn.size();
+ if ((row > 1) && (iv_col_vars.size() == 1) && (iv_col_vars.front() == r_expr))
+ {
+ --row;
+ do
+ {
+ size_t row1 = row - 1;
+
+ if (iv_spyv_rpn.at(row) == iv_spyv_rpn.at(row1))
+ {
+ if (iv_range_list.size() == 0 || (iv_range_list.at(row) == iv_range_list.at(row1)))
+ {
+ // merge
+ Rpn * rp = new Rpn(iv_cols_rpn.back().at(row));
+ iv_cols_rpn.back().at(row1).push_merge(rp, Rpn::OR); // this will delete rp
+ iv_spyv_rpn.erase(iv_spyv_rpn.begin() + row);
+ if (iv_range_list.size()) iv_range_list.erase(iv_range_list.begin() + row);
+ for (COL_LIST::iterator i = iv_cols_rpn.begin(); i != iv_cols_rpn.end(); ++i)
+ {
+ i->erase(i->begin() + row);
+ }
+ dbg << "ROW " << row+1 << " and " << row1+1 << " have been merged in " << get_key_name() << endl;
+ }
+ }
+ } while (--row);
+ }
+#endif
+}
+
+
+
+//-------------------------------------------------------------------------------------------------
+
+bool Scom::compare(Scom & that)
+{
+ bool result = false; //true;
+// TODO
+#if 0
+ ostringstream oss;
+ oss << hex << setfill('0');
+ // spyname(s) should have already been tested
+ oss << get_key_name() << endl;
+ if(iv_spy_type != that.iv_spy_type ||
+ iv_when != that.iv_when ||
+ iv_spy_length != that.iv_spy_length ||
+ iv_spy_offset != that.iv_spy_offset ||
+ iv_array_addr != that.iv_array_addr)
+ {
+ result = false;
+ oss << "type: " << setw(8) << iv_spy_type << ' ' << that.iv_spy_type << endl;
+ oss << "when: " << setw(8) << iv_when << ' ' << that.iv_when << endl;
+ oss << "len: " << setw(8) << iv_spy_length << ' ' << that.iv_spy_length << endl;
+ oss << "offset: " << setw(8) << iv_spy_offset << ' ' << that.iv_spy_offset << endl;
+ oss << "array: " << setw(8) << iv_array_addr << ' ' << that.iv_array_addr << endl;
+ }
+ // need to expand all Rpns to verify resolution of vars and lits
+ // when Rpn
+ string rpn1 = iv_when_rpn.listing("",iv_spy_names.front(),false);
+ string rpn2 = that.iv_when_rpn.listing("",iv_spy_names.front(),false);
+ if(rpn1 != rpn2)
+ {
+ result = false;
+ oss << "this when Rpn:" << endl << rpn1 << endl;
+ oss << "that when Rpn:" << endl << rpn2 << endl;
+ }
+
+ // spyv Rpn
+ if(iv_spyv_rpn.size() != that.iv_spyv_rpn.size())
+ {
+ result = false;
+ oss << "this spyv Rpn(s):" << endl;
+ for(RPN_LIST::iterator r1 = iv_spyv_rpn.begin(); r1 != iv_spyv_rpn.end(); ++r1)
+ oss << r1->listing("",iv_spy_names.front(),false) << endl;
+ oss << "that spyv Rpn(s):" << endl;
+ for(RPN_LIST::iterator r1 = that.iv_spyv_rpn.begin(); r1 != that.iv_spyv_rpn.end(); ++r1)
+ oss << r1->listing("",iv_spy_names.front(),false) << endl;
+ }
+ else
+ {
+ RPN_LIST::iterator r1 = iv_spyv_rpn.begin();
+ RPN_LIST::iterator r2 = that.iv_spyv_rpn.begin();
+ for(; r1 != iv_spyv_rpn.end(); ++r1, ++r2)
+ {
+ rpn1 = r1->listing("",iv_spy_names.front(),false);
+ rpn2 = r2->listing("",iv_spy_names.front(),false);
+ if(rpn1 != rpn2)
+ {
+ result = false;
+ oss << "this spyv Rpn:" << endl << rpn1 << endl;
+ oss << "that spyv Rpn:" << endl << rpn2 << endl;
+ }
+ }
+ }
+
+ // column names
+ if(iv_col_vars.size() != that.iv_col_vars.size())
+ {
+ result = false;
+ oss << "this col names:" << endl;
+ for(RPN_LIST::iterator i = iv_col_vars.begin(); i != iv_col_vars.end(); ++i)
+ {
+ oss << i->symbol_names() << endl;
+ }
+ oss << "that col names:" << endl;
+ for(RPN_LIST::iterator i = that.iv_col_vars.begin(); i != that.iv_col_vars.end(); ++i)
+ {
+ oss << i->symbol_names() << endl;
+ }
+ }
+ else
+ {
+ RPN_LIST::iterator i = iv_col_vars.begin();
+ RPN_LIST::iterator j = that.iv_col_vars.begin();
+ for(;i != iv_col_vars.end(); ++i, ++j)
+ {
+ //string s1 = iv_symbols->find_name(*i);
+ //string s2 = that.iv_symbols->find_name(*j);
+ if((*i) != (*j))
+ {
+ result = false;
+ oss << "this col name: " << i->symbol_names() << endl;
+ oss << "that col name: " << j->symbol_names() << endl;
+ }
+ }
+ }
+
+ // row Rpns
+ Rpn r1(iv_symbols);
+ Rpn r2(that.iv_symbols);
+ for(COL_LIST::iterator c = iv_cols_rpn.begin(); c != iv_cols_rpn.end(); ++c)
+ {
+ for(RPN_LIST::iterator r = c->begin(); r != c->end(); ++r)
+ {
+ r1.append(*r);
+ }
+ }
+ for(COL_LIST::iterator c = that.iv_cols_rpn.begin(); c != that.iv_cols_rpn.end(); ++c)
+ {
+ for(RPN_LIST::iterator r = c->begin(); r != c->end(); ++r)
+ {
+ r2.append(*r);
+ }
+ }
+ rpn1 = r1.listing("",iv_spy_names.front(),false);
+ rpn2 = r2.listing("",iv_spy_names.front(),false);
+ if(rpn1 != rpn2)
+ {
+ result = false;
+ oss << "this row/col rpn:" << endl;
+ oss << rpn1 << endl;
+ oss << "that row/col rpn:" << endl;
+ oss << rpn2 << endl;
+ }
+
+ if(!result) cout << oss.str();
+#endif
+ return result;
+}
+
+
+//=================================================================================================
+// SpyList Class definitions
+//=================================================================================================
+
+ScomList::ScomList(const string & initfile, FILELIST & defines, ostream & stats, uint32_t i_ec)
+ :
+ iv_syntax_version(0),
+ iv_symbols(new Symbols(defines)),
+ iv_stats(stats),
+ iv_ec(i_ec)
+
+{
+ yyscomlist = this;
+
+ // What type of input? text(*.initfile) or binary(*.if) ?
+ size_t pos = initfile.rfind('.');
+ string type;
+ if(pos != string::npos)
+ {
+ type = initfile.substr(pos+1);
+ }
+
+ if(type.compare(0,8,"initfile") == 0) // source is text *.initfile
+ {
+ char line[100];
+ string first_line;
+ yyin = fopen(initfile.c_str(), "r");
+ if(!yyin)
+ {
+ string ers("ERROR: Could not open initfile: ");
+ ers.append(initfile);
+ throw invalid_argument(ers);
+ }
+
+ // In Syntax version 1 the first or second line contains the CVS version
+ fgets(line,100,yyin);
+ first_line = line;
+ fgets(line,100,yyin);
+ first_line.append(line);
+ yyline = 3;
+
+ dbg << "======================= Begin Parse ========================" << endl;
+ yyparse(); // Parse the initfile
+ dbg << "======================= End Parse ==========================" << endl;
+
+ if(iv_syntax_version == 1)
+ {
+ // example pattern ..... $Id: galaxy.initfile,v 5.0 ......
+ size_t pos = first_line.find("$Id:");
+ if(pos != string::npos)
+ {
+ istringstream iss(first_line.substr(pos+4));
+ string tok;
+ iss >> tok; // ex. galaxy.initfile,v
+ iss >> tok; // ex. 5.0
+ iv_cvs_versions = tok; // just want the version number - eg '5.0'
+ }
+ }
+
+ iv_stats << '*' << setw(20) << "lines:" << setw(6) << yyline-1 << endl;
+ iv_stats << '*' << setw(20) << "Scom statements:" << setw(6) << iv_scom_list.size() << endl;
+ // TODO num var/lits num lits found
+ }
+ else if(type.compare(0,2,"if") == 0) // source is binary *.if file
+ {
+// TODO - No support for this currently
+#if 0
+ dbg << "======================= Begin Uncompiling ========================" << endl;
+
+ BINSEQ bin_seq;
+ ifstream ifs(initfile.c_str(), ios_base::in | ios_base::binary);
+ if(!ifs)
+ {
+ string msg("ERROR: SpyList::Could not open ");
+ msg.append(initfile);
+ throw invalid_argument(msg);
+ }
+ while(1)
+ {
+ int ch = ifs.get();
+ if (!(ifs.good())) break;
+ bin_seq.push_back(ch);
+ }
+ ifs.close();
+
+ // Turn this back into a list of spies
+ BINSEQ::const_iterator bli = bin_seq.begin();
+ BINSEQ::const_iterator b;
+
+ iv_syntax_version = Rpn::extract32(bli);
+ bli += 8;
+ if(iv_syntax_version == 1)
+ {
+ for(b = bli-8; (b != bli) && (*b); ++b)
+ {
+ iv_cvs_versions.push_back(*b);
+ }
+ }
+ else
+ {
+ // offset to CVS sub version section
+ b = bin_seq.begin() + Rpn::extract32(bli);
+ size_t size = Rpn::extract16(b);
+ while(size--) iv_cvs_versions.push_back(*b++);
+ }
+
+ b = bin_seq.begin() + Rpn::extract32(bli);
+ iv_symbols->restore_var_bseq(b);
+
+ b = bin_seq.begin() + Rpn::extract32(bli);
+ iv_symbols->restore_lit_bseq(b);
+
+ size_t section_count = Rpn::extract32(bli);
+ if(section_count > LAST_WHEN_TYPE)
+ {
+ throw range_error("ERROR: SpyList::SpyList - Inalid # of sections");
+ }
+
+ for(size_t i = 0; i < section_count; ++i)
+ {
+ size_t spy_type = Rpn::extract32(bli); // type
+ size_t offset = Rpn::extract32(bli); // offset
+ size_t count = Rpn::extract32(bli); // Number of spies
+
+ b = bin_seq.begin() + offset;
+ if(!(b < bin_seq.end()))
+ {
+ throw overflow_error("ERROR: SpyList::SpyList - iterator overflowed sequence");
+ }
+ if(spy_type > LAST_WHEN_TYPE || spy_type == 0)
+ {
+ throw range_error("ERROR: SpyList::SpyList - when= type out of range");
+ }
+ while(count--)
+ {
+ Scom * s = new Scom(b,iv_symbols);
+ insert(s);
+ s->set_when((SPY_WHEN)spy_type);
+ }
+ }
+#endif
+ dbg << "======================= End Uncompiling ========================" << endl;
+ }
+ else
+ {
+ ostringstream ess;
+ ess << "ERROR: SpyList::SpyList Invalid file type: " << type;
+ ess << "\n source: " << initfile;
+ throw invalid_argument(ess.str());
+ }
+}
+
+//-------------------------------------------------------------------------------------------------
+
+ScomList::~ScomList()
+{
+ delete iv_symbols;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void ScomList::clear()
+{
+ for(SCOM_LIST::iterator i = iv_scom_list.begin(); i != iv_scom_list.end(); ++i) delete i->second;
+ iv_scom_list.clear();
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void ScomList::set_syntax_version(uint32_t v)
+{
+ if(v != 1 && v != 2) yyerror("Invalid Syntax Version");
+ iv_syntax_version = v;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void ScomList::compile(BINSEQ & bin_seq)
+{
+ uint32_t count_s = 0;
+ uint32_t section_count = 0;
+ size_t offset = 0;
+
+
+ BINSEQ blist_v; // vars
+ BINSEQ blist_i; // lits
+ BINSEQ blist_l; // when=L spies
+ BINSEQ blist_s; // when=S spies
+ BINSEQ blist_c; // when=C spies
+ BINSEQ blist_d; // when=D spies
+
+ // Make the BINSEQs big enough to hopefully never have to resize
+ blist_v.reserve(0x00400);
+ blist_i.reserve(0x02000);
+ blist_l.reserve(0x30000);
+ blist_s.reserve(0x03000);
+ blist_c.reserve(0x03000);
+ blist_d.reserve(0x03000);
+
+
+ dbg << "======================== Begin compile ============================" << endl;
+ Rpn::set32(bin_seq,iv_syntax_version); // bytes[0:3]
+
+ // bytes [4:12]
+ if(iv_syntax_version == 2)
+ {
+ const char * s = "SEE SUBV";
+ for(; *s != 0; ++s) bin_seq.push_back(*s);
+ istringstream iss(iv_cvs_versions);
+ string vers;
+ while(iss >> vers)
+ {
+ stats << '*' << setw(20) << "Version:" << " " << vers << endl;
+ }
+ }
+ else if (iv_syntax_version == 1)
+ {
+ if(iv_cvs_versions.size())
+ {
+ size_t len = iv_cvs_versions.size();
+ if(len > 8) { iv_cvs_versions.erase(9); len = 8; }
+ for(string::const_iterator s = iv_cvs_versions.begin();
+ s != iv_cvs_versions.end(); ++s)
+ {
+ bin_seq.push_back(*s);
+ }
+ while(len < 8) { bin_seq.push_back(0); ++len; }
+ stats << '*' << setw(20) << "Version:" << setw(6) << iv_cvs_versions << endl;
+ }
+ else
+ {
+ throw range_error("ERROR: No CVS version(s) specified");
+ }
+ }
+ else // syntax version already validated to be 1 or 2 - so if we get here it was never set.
+ {
+ throw range_error("ERROR: No sytax version specified!");
+ }
+ stats << '*' << setw(20) << "Syntax Version:" << setw(6) << iv_syntax_version << endl;
+
+
+ // Determine the number of scoms in each section
+
+ for(SCOM_LIST::iterator i = iv_scom_list.begin(); i != iv_scom_list.end(); ++i)
+ {
+ // Filter out filtered spies dg003a
+ if(!(i->second->valid_when(dbg,iv_ec)))
+ {
+ continue;
+ }
+
+ count_s += i->second->bin_listing(blist_s);
+
+ }
+ if(count_s) ++section_count;
+
+ // 28 bytes of File Header Data
+ offset = 28;
+ stats << '*' << setw(20) << "Sections:" << setw(6) << section_count << endl;
+
+ // for verion 2 add offset to CVS versions section
+ if(iv_syntax_version == 2)
+ {
+ offset += 4;
+ Rpn::set32(bin_seq,offset);
+ offset += iv_cvs_versions.length() + 2;
+ }
+ // offset now points to start of Var Symbol Table
+
+ iv_symbols->bin_vars(blist_v); // get Var table
+ iv_symbols->bin_lits(blist_i); // Get Lit table
+
+ Rpn::set32(bin_seq,offset); // Offset to Variable Symbol Table
+ offset += blist_v.size(); // offset += var table byte size
+ Rpn::set32(bin_seq,offset); // Offset to Literal Symbol Table
+ offset += blist_i.size(); // offset += lit table byte size
+
+ if(count_s)
+ {
+ Rpn::set32(bin_seq,offset); // SCOM Section offset
+ Rpn::set32(bin_seq,count_s); // Number of SCOM's
+ }
+
+ if(iv_syntax_version == 2) // Add Sub-version section
+ {
+ Rpn::set16(bin_seq,(uint16_t)iv_cvs_versions.length()); // Length of Sub version
+ bin_seq.insert(bin_seq.end(), iv_cvs_versions.begin(), iv_cvs_versions.end());
+ }
+
+ bin_seq.insert(bin_seq.end(), blist_v.begin(), blist_v.end()); // add var table section
+ bin_seq.insert(bin_seq.end(), blist_i.begin(), blist_i.end()); // add lit table section
+
+ if(count_s)
+ {
+ bin_seq.insert(bin_seq.end(), blist_s.begin(), blist_s.end()); // add SCOM section
+ stats << '*' << setw(20) << "S scoms:" << setw(6) << count_s << endl;
+ }
+ dbg << "======================== End compile ============================" << endl;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+bool Scom::valid_when(ostream & msg, uint32_t i_ec) //dg002a dg003c
+{
+ bool result = true;
+
+ // unconditional state was determined earlier
+ if( iv_when_rpn.isTrue()) // unconditionally true - Rpn is not needed.
+ iv_when_rpn.clear();
+ else if( iv_when_rpn.isFalse()) //unconditionally false
+ result = false;
+ else if(i_ec != 0xffffffff)
+ {
+ if(iv_when_rpn.resolve_ec(i_ec) == false) result = false;
+ }
+#if 0
+ if(result == false)
+ {
+ msg << hex;
+ SPY_NAMES::iterator i = iv_spy_names.begin();
+ // if more than one spyname, the first is just the stem of the name - skip it
+ if(iv_spy_names.size() > 1) ++i;
+
+ for(; i != iv_spy_names.end(); ++i)
+ {
+ if(i_ec != 0xffffffff)
+ msg << "For EC " << i_ec << ": ";
+
+ msg << "Removing spy " << *i << endl;
+ }
+ msg << iv_when_rpn.listing("WHEN RPN","",true) << endl;
+ }
+#endif
+ return result;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void ScomList::listing(BINSEQ & bin_seq,ostream & olist)
+{
+ dbg << "======================= Begin Listing ========================" << endl;
+
+ BINSEQ::const_iterator bli = bin_seq.begin();
+ BINSEQ::const_iterator b;
+ uint32_t syntax_version = Rpn::extract32(bli);
+
+ string cvs_versions;
+
+ olist << hex << setfill('0');
+ olist << "--------------- FILE HEADER ------------------------\n\n";
+ olist << fmt8(syntax_version) << "[Syntax Version]\n"
+ << "0x";
+ bli += 8;
+ for(b = bli-8; b != bli; ++b) olist << setw(2) << (uint32_t)(*b);
+ olist << " [";
+ for(b = bli-8; b != bli; ++b) if((*b) != 0) olist << (char)(*b);
+ olist << "]\t[CVS Version]\n";
+ if(syntax_version == 2)
+ {
+ size_t offset = Rpn::extract32(bli);
+ olist << fmt8(offset) << "[Offset to Sub-Version Section]\n";
+ }
+
+ uint32_t var_table_offset = Rpn::extract32(bli);
+ uint32_t lit_table_offset = Rpn::extract32(bli);
+
+ olist << fmt8(var_table_offset) << "[Offset to Attribute Symbol Table]\n";
+ olist << fmt8(lit_table_offset) << "[Offset to Literal Symbol Table]\n";
+
+
+ b = bin_seq.begin() + var_table_offset;
+ iv_symbols->restore_var_bseq(b);
+
+ b = bin_seq.begin() + lit_table_offset;
+ iv_symbols->restore_lit_bseq(b);
+
+ b = bli; // save
+
+ size_t offset = Rpn::extract32(bli); // offset
+ size_t count = Rpn::extract32(bli); // Number of spies
+
+ olist << fmt8(offset) << "[Scom Section Offset]\n";
+ olist << fmt8(count) << "[Number of scoms]\n";
+
+ olist << endl;
+
+ if(syntax_version == 2)
+ {
+ olist << "--------------- Sub Version Section ---------------\n\n";
+ uint16_t len = Rpn::extract16(bli);
+ olist << "0x" << setw(4) << len << "\t\t"
+ << "Length of Sub Version Section\n\n";
+ for(uint16_t i = 0; i < len; ++i) olist << (char)(*bli++);
+ olist << endl;
+ }
+
+ olist << iv_symbols->listing() << endl;
+ olist << "------------------- SCOM TABLES ------------------------\n\n"
+ << endl;
+
+ bli = b; // restore
+
+ olist << "------------ Scoms -----------\n\n";
+
+ b = bin_seq.begin() + offset;
+ if(!(b < bin_seq.end()))
+ {
+ throw overflow_error("ERROR: ScomList::listing - iterator overflowed sequence");
+ }
+ while(count--)
+ {
+ Scom s(b,iv_symbols);
+ olist << s.listing() << endl;
+ }
+
+ dbg << "======================= End Listing ========================" << endl;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void ScomList::attr_listing(BINSEQ & bin_seq,ostream & olist)
+{
+ olist << iv_symbols->attr_listing();
+}
+
+//-------------------------------------------------------------------------------------------------
+
+string ScomList::fmt8(uint32_t val)
+{
+ ostringstream oss;
+ oss << setfill('0');
+ oss << "0x" << hex << setw(8) << val << "\t " << '[' << dec << val << ']' << '\t';
+ if(val < 1000) oss << '\t';
+ return oss.str();
+}
+
+
+//-------------------------------------------------------------------------------------------------
+
+void ScomList::insert(Scom * i_scom)
+{
+ uint64_t l_addr = i_scom->get_address();
+ SCOM_LIST::iterator i = iv_scom_list.find(l_addr);
+ if(i == iv_scom_list.end())
+ {
+ iv_scom_list[l_addr] = i_scom;
+ }
+ else
+ {
+ ostringstream oss;
+ oss << "Duplicate scom statement found on line " << i_scom->get_line() << endl;
+ oss << "First instance found on line " << i->second->get_line() << "Address: " << i_scom->get_address() << endl;
+ yyerror(oss.str().c_str());
+ }
+}
+
+//-------------------------------------------------------------------------------------------------
+
+bool ScomList::compare(ScomList & that)
+{
+ bool result = true;
+ dbg << "======================= Begin Compare ========================" << endl;
+ if(iv_scom_list.size() != that.iv_scom_list.size())
+ {
+ cout << "E> Lists are not the same size" << endl;
+ result = false;
+ }
+
+ // check each spy section
+ for(SCOM_LIST::iterator i = iv_scom_list.begin(); i != iv_scom_list.end(); ++i)
+ {
+ // The name checks spyname, arrayaddr (if array), bitrange(s) (if any)
+ uint64_t l_addr = i->second->get_address();
+ SCOM_LIST::iterator j = that.iv_scom_list.find(l_addr);
+ if(j == that.iv_scom_list.end())
+ {
+ cout << "E> " << l_addr << " not found in both lists!" << endl;
+ result = false;
+ continue;
+ }
+ if(i->second->compare(*(j->second)) == false)
+ {
+ cout << "E> Spy: " << l_addr << " does not match!" << endl;
+ result = false;
+ }
+ }
+
+ // check for spies in that that are not in this
+ for(SCOM_LIST::iterator i = that.iv_scom_list.begin(); i != that.iv_scom_list.end(); ++i)
+ {
+ uint64_t l_addr = i->second->get_address();
+ SCOM_LIST::iterator j = iv_scom_list.find(l_addr);
+ if(j == iv_scom_list.end())
+ {
+ cout << "E> " << l_addr << " not found in both lists!" << endl;
+ result = false;
+ }
+ }
+ dbg << "======================= End Compare ========================" << endl;
+ return result;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+//-------------------------------------------------------------------------------------------------
+
+void Scom::set_scom_address(const string & i_scom_addr)
+{
+
+ if(iv_scom_addr.size())
+ {
+ yyerror("SCOM Address already set!");
+ }
+ else
+ {
+ iv_scom_addr.push_back(i_scom_addr);
+ // cout << "I>Scom::set_scom_address: " << i_scom_addr << " is the output string!" << endl;
+ }
+}
+
+//-------------------------------------------------------------------------------------------------
+
+
+void Scom::dup_scom_address(const string & i_scom_addr)
+{
+
+
+ if(iv_scom_addr.size())
+ {
+ iv_scom_addr.push_back(iv_scom_addr.front() + i_scom_addr);
+ }
+ else
+ yyerror("No base scom address to dulicate for append!");
+
+ // cout << "I>Scom::dup_scom_address: "<< i_scom_addr << " is the output string!" << endl;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void Scom::set_scom_suffix(const string & i_scom_addr)
+{
+
+ if(iv_scom_addr.size() == 1) iv_scom_addr[0] = iv_scom_addr[0] + i_scom_addr;
+ else if(iv_scom_addr.size() > 1)
+ {
+ SCOM_ADDR::iterator i = iv_scom_addr.begin();
+ ++i;
+ for(;i != iv_scom_addr.end(); ++i)
+ {
+ *i += i_scom_addr;
+ }
+ }
+ else
+ yyerror("No base scom address to append suffix");
+
+ // cout << "I>Scom::set_scom_suffix: "<< i_scom_addr << " is the output string!" << endl;
+}
diff --git a/src/usr/hwpf/ifcompiler/initScom.H b/src/usr/hwpf/ifcompiler/initScom.H
new file mode 100755
index 000000000..35938ba20
--- /dev/null
+++ b/src/usr/hwpf/ifcompiler/initScom.H
@@ -0,0 +1,247 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/ifcompiler/initScom.H,v $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2010,2010
+//
+//UNDEFINED
+//
+// Origin: UNDEFINED
+//
+// IBM_PROLOG_END_TAG
+#if !defined(INITSPY_H)
+#define INITSPY_H
+
+// Change Log *************************************************************************************
+//
+// Flag Track 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 More filtering enhancements
+// andrewg 05/24/11 Port over for VPL/PgP
+// andrewg 09/19/11 Updates based on review
+// mjjones 11/17/11 Output attribute listing
+// End Change Log *********************************************************************************
+
+/**
+ * @file initSpy.H
+ * @brief Declairation of the initSpy Class. Represents the information parsed from an initfile spy
+ * statement.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string>
+#include <vector>
+#include <map>
+#include <set>
+#include <initRpn.H>
+#include <initSymbols.H>
+
+
+using namespace std;
+
+namespace init
+{
+ typedef vector<string> SCOM_ADDR;
+ typedef vector<Rpn> RPN_LIST;
+ typedef vector<RPN_LIST> COL_LIST;
+ typedef vector<uint32_t> VAR_LIST;
+ typedef pair<uint32_t,uint32_t> RANGE;
+ typedef vector<RANGE> RANGE_LIST;
+
+ enum SCOM_WHEN
+ {
+ NONE = 0x00000000,
+
+ // WHEN= types
+ LONG_SCAN = 0x00000001,
+ SCOM = 0x00000002,
+ DRAMINIT = 0x00000003,
+ CFAMINIT = 0x00000004,
+ LAST_WHEN_TYPE = CFAMINIT,
+ WHEN_MASK = 0x000000FF,
+
+ // WHEN= sub types
+ SUBTYPE_MASK = 0x0000F000,
+ HOT_ADD_NODE = 0x00004000,
+ AFTER_HOT_ADD_NODE = 0x00006000,
+ HOT_ADD_GX = 0x00008000,
+ HOT_ADD_GX0 = 0x00007000,
+ HOT_ADD_GX1 = 0x00005000,
+ AFTER_HOT_ADD_GX = 0x0000A000,
+ AFTER_HOT_ADD_GX0 = 0x00003000,
+ AFTER_HOT_ADD_GX1 = 0x00002000,
+ };
+
+ const char when_char[] = { '@','L','S','D','C' };
+
+ class Scom
+ {
+ public:
+
+ enum SPY_TYPE
+ {
+ NOTYPE,
+ ISPY,
+ ESPY,
+ ARRAY
+ };
+
+
+ Scom(Symbols * i_symbols,uint32_t i_line = 0) :
+ iv_symbols(i_symbols),
+ iv_line(i_line),
+ iv_scom_length(0),
+ iv_scom_offset(0),
+ iv_when(NONE) {}
+
+ // Build from binary sequence
+ Scom(BINSEQ::const_iterator & bli, Symbols * i_symbols);
+
+ bool compare(Scom & that);
+ uint32_t get_when(void) { return(iv_when); }
+ void set_when(SCOM_WHEN i_when) { iv_when |= (uint32_t)i_when; }
+ void set_when(const string * when_str);
+ bool do_when(SCOM_WHEN i_when) { return ((uint32_t)i_when == (WHEN_MASK & iv_when)); }
+ void set_sub_when(SCOM_WHEN i_when) { iv_when |= i_when; }
+ void set_when_rpn(const Rpn * i_rpn) { iv_when_rpn = *i_rpn; delete i_rpn; }
+ uint32_t get_line() { return iv_line; }
+ void add_scom_rpn(const Rpn * i_rpn) { iv_scom_rpn.push_back(*i_rpn); delete i_rpn; }
+
+
+
+ /**
+ * Is when statement valid for this spy
+ * @param stats: ostream to print debug information
+ * @param ec restriction - true if valid for this ec, 0xffffffff means ANY ec
+ * @return false if Rpn for when statement resolves to false, otherwise true
+ */
+ bool valid_when(ostream & stats, uint32_t i_ec = 0xffffffff);
+
+ void add_col(const string & i_colname);
+
+ /**
+ * Add a row rpn to the current column
+ * @param pointer to Rpn object
+ * @pre add_col()
+ */
+ void add_row_rpn(Rpn * i_rpn);
+
+ void add_bit_range(uint32_t start, uint32_t end);
+ void add_target_range(uint32_t r1, uint32_t r2);
+ void make_target(const char * i_symbol);
+
+
+ uint64_t get_address(void) {return(strtoul(iv_scom_addr[0].c_str(),NULL,16));}
+ // string name();
+ string listing();
+
+ /**
+ * Append binary listing of this Spy
+ * @param when [init::LONG_SCAN | init::SCOM]
+ * @param BINSEQ binary listing to append
+ * @returns uint32_t number of spies added
+ */
+ uint32_t bin_listing(BINSEQ & blist);
+
+ void set_scom_address(const string & i_scom_addr);
+ void dup_scom_address(const string & i_scom_addr);
+ void set_scom_suffix(const string & i_scom_addr);
+
+ private: // functions
+
+ string list_one(RANGE range);
+ void bin_list_one(BINSEQ & blist,uint64_t i_addr, RANGE range);
+
+ /**
+ * Optimize the row RPNs
+ * @note Remove any rows that resolve to unconditionally false.
+ */
+ void row_optimize();
+
+ private: // data
+
+ typedef map<string,SCOM_WHEN> WHEN_SUBTYPE_MAP;
+
+ SCOM_ADDR iv_scom_addr;
+ uint64_t iv_scom_addr_hex;
+ uint32_t iv_scom_length;
+ uint32_t iv_scom_offset;
+ RPN_LIST iv_scom_rpn; ///< spyv - for each row
+ RPN_LIST iv_col_vars; ///< RPNs of column name for each column
+ COL_LIST iv_cols_rpn; ///< A list of row rpn segments one rpn list for each column
+ RPN_LIST iv_row_rpn; ///< row rpns for current column being parsed.
+ RANGE_LIST iv_range_list; ///< bit range list
+ RANGE_LIST iv_target_ranges; ///< target range for current target begin parsed.
+ Symbols * iv_symbols;
+ uint32_t iv_line; ///< line # in the initfile
+ uint32_t iv_when;
+ Rpn iv_when_rpn;
+
+
+ static WHEN_SUBTYPE_MAP cv_when_subtypes;
+
+ };
+
+
+ //=================================================================================================
+ // SpyList Class declarations
+ //=================================================================================================
+ // Container to track scoms
+ typedef map<uint64_t, init::Scom *> SCOM_LIST;
+
+ class ScomList
+ {
+ public:
+ ScomList(const string & initfile, FILELIST & defines, ostream & stats, uint32_t i_ec = 0xFFFFFFFF);
+ ~ScomList();
+ //size_t size() { return iv_spy_list.size(); }
+ //SPY_LIST::iterator begin() { return iv_spy_list.begin(); }
+ //SPY_LIST::iterator end() { return iv_spy_list.end(); }
+ void clear();
+ void insert(Scom * i_scom);
+
+ void compile(BINSEQ & bin_seq);
+
+ void listing(BINSEQ & bin_seq, ostream & out);
+ void attr_listing(BINSEQ & bin_seq, ostream & out);
+
+ /**
+ * Compare two spylists for equivalance
+ * @returns true if equal
+ * @note Both spylists should have been built from a binary sequence
+ * not directly from an initfile
+ */
+ bool compare(ScomList & that);
+
+
+
+ void set_cvs_versions(const string * s) { iv_cvs_versions = *s; }
+ void set_syntax_version(uint32_t v);
+ size_t get_syntax_version() { return iv_syntax_version; }
+ void clear_defines() { iv_symbols->clear_defines(); }
+ void add_define(const string * name, const Rpn * rpn)
+ { iv_symbols->add_define(name,rpn); }
+
+ Symbols * get_symbols() { return iv_symbols; }
+
+ private: // functions
+
+ string fmt8(uint32_t val);
+
+ private:
+
+ SCOM_LIST iv_scom_list;
+ string iv_cvs_versions;
+ uint32_t iv_syntax_version;
+ Symbols * iv_symbols;
+ ostream & iv_stats;
+ uint32_t iv_ec;
+ };
+};
+#endif
diff --git a/src/usr/hwpf/ifcompiler/initSymbols.C b/src/usr/hwpf/ifcompiler/initSymbols.C
new file mode 100755
index 000000000..6e8b8bc38
--- /dev/null
+++ b/src/usr/hwpf/ifcompiler/initSymbols.C
@@ -0,0 +1,1056 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/ifcompiler/initSymbols.C,v $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2010,2010
+//
+//UNDEFINED
+//
+// Origin: UNDEFINED
+//
+// IBM_PROLOG_END_TAG
+// Change Log *************************************************************************************
+//
+// Flag Track Userid Date Description
+// ---- -------- -------- -------- -------------------------------------------------------------
+// D754106 dgilbert 06/14/10 Create
+// dgilbert 10/22/10 Add spies_are_in()
+// 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
+// mjjones 11/17/11 Output attribute listing
+// End Change Log *********************************************************************************
+
+/**
+ * @file initSymbols.C
+ * @brief Definition of the initSymbols class. Handles all symbols for initfiles
+ */
+
+#include <initSymbols.H>
+#include <initRpn.H>
+#include <sstream>
+#include <iomanip>
+#include <iostream>
+#include <fstream>
+#include <stdexcept>
+#include <stdlib.h>
+
+using namespace init;
+
+ostringstream errss;
+
+#define SYM_EXPR 0x10000000
+
+// ------------------------------------------------------------------------------------------------
+
+Symbols::Symbols(FILELIST & i_filenames)
+ : iv_used_var_count(1), iv_used_lit_count(1), iv_rpn_id(1)
+{
+ string fileline;
+
+ for(FILELIST::iterator fn = i_filenames.begin(); fn != i_filenames.end(); ++fn)
+ {
+ printf("Parsing file %s\n",fn->c_str());
+ uint32_t lineno = 0;
+ ifstream infs(fn->c_str());
+ if(!infs)
+ {
+ errss.str("");
+ errss << "ERROR - Could not open " << *fn;
+ throw invalid_argument(errss.str());
+ }
+ while(getline(infs,fileline))
+ {
+ ++lineno;
+ if(fileline.size() == 0) continue;
+ if(fileline[0] == '/') continue;
+ istringstream iss(fileline);
+ string def;
+ iss >> def;
+ //printf("def: %s\n",def.c_str());
+ if(def == "enum")
+ {
+ // Make sure it's the AttributeId enum
+ iss >> def;
+ if(def == "AttributeId")
+ {
+ // We've now found the beginning of the attribute enum definition
+ // Read and skip the '{' on the next line
+ getline(infs,fileline);
+ getline(infs,fileline);
+
+ // We're just parsing the enum in order so values start
+ // at 0 and increment by 1 after that.
+ uint32_t value = 0;
+
+ while(fileline[0] != '}')
+ {
+ istringstream attr_stream(fileline);
+ string attr;
+ attr_stream >> attr;
+
+ // Strip off the "," at the end.
+ size_t pos = attr.find(',');
+ if(pos != string::npos)
+ {
+ attr = attr.substr(0,attr.length()-1);
+ }
+
+ //printf("Attribute String:%s\n",attr.c_str());
+ // We now have the first attribute loaded into attr
+ // Get a value for the string
+
+ iv_symbols[attr] = MAP_DATA(value,NOT_USED);
+ value++;
+ getline(infs,fileline);
+ }
+ }
+ else
+ {
+ // Make sure it's an attribute enum
+
+ string attribute_enum_name;
+ string find_enum = "_Enum";
+
+ // Check for _Enum in the name
+ size_t pos = def.find(find_enum);
+ if(pos != string::npos)
+ {
+ // We've now found the beginning of the attribute enum definition
+ // Read and skip the '{' on the next line
+ getline(infs,fileline);
+ getline(infs,fileline);
+
+ // We're just parsing the enum in order so values start
+ // at 0 and increment by 1 after that unless they are
+ // explicitly assigned.
+ uint64_t value = 0;
+
+ while(fileline[0] != '}')
+ {
+ istringstream attr_enum_stream(fileline);
+ string attr_enum;
+ string tmp;
+
+ // Get the attribute enum name
+ attr_enum_stream >> attr_enum;
+
+ // Strip off the "," at the end.
+ pos = attr_enum.find(',');
+ if(pos != string::npos)
+ {
+ attr_enum = attr_enum.substr(0,attr_enum.length()-1);
+ }
+ else
+ {
+ // Is a value for the enum specified?
+ attr_enum_stream >> tmp;
+
+ if (!attr_enum_stream.eof())
+ {
+ //Make sure it's an '='
+ if ("=" != tmp)
+ {
+ printf ("ERROR: Unknown attribute enum! %s\n",attr_enum.c_str());
+ exit(1);
+ }
+ else
+ {
+ attr_enum_stream >> tmp;
+ value = strtoll(tmp.c_str(), NULL, 0);
+ }
+ }
+ }
+
+ //printf("Attribute Enum String:%s Value %u\n",attr_enum.c_str(), value);
+
+ // Get a value for the string
+ iv_attr_enum[attr_enum] = value;
+ value++;
+ getline(infs,fileline);
+ }
+ }
+ }
+ }
+ else if(def == "typedef")
+ {
+ string type;
+ string attribute_name;
+ string find_type = "_Type";
+ string find_array = "[";
+ uint32_t array = 0;
+ iss >> type;
+ iss >> attribute_name;
+ if(attribute_name == "*")
+ {
+ // It's a pointer type so read in the next string
+ iss >> attribute_name;
+ type = type + "*";
+ }
+ //printf("typedef: type:%s attribute_name:%s\n",type.c_str(),attribute_name.c_str());
+
+ // Determine how many (if any) dimensions this array has
+ size_t pos = attribute_name.find(find_array);
+ while(pos != string::npos)
+ {
+ array++;
+ pos = attribute_name.find(find_array,pos+1);
+ }
+
+ // Now strip off the _type in the name
+ pos = attribute_name.find(find_type);
+ if(pos != string::npos)
+ {
+ attribute_name = attribute_name.substr(0,pos);
+ }
+ else
+ {
+ printf ("ERROR: Unknown attribute type! %s\n",attribute_name.c_str());
+ exit(1);
+ }
+
+ iv_attr_type[attribute_name] = get_attr_type(type,array);
+ //printf("Attribute %s Type with array dimension %u for %s is %u\n",attribute_name.c_str(),array,
+ // type.c_str(),get_attr_type(type,array));
+ }
+ }
+ infs.close();
+ }
+ iv_rpn_map[Rpn::SYMBOL | INIT_EXPR_VAR] = RPN_DATA("EXPR",SYM_EXPR);
+ iv_rpn_map[Rpn::SYMBOL | INIT_ANY_LIT] = RPN_DATA("ANY",CINI_LIT_MASK);
+}
+
+uint32_t Symbols::get_attr_type(const string &i_type, const uint32_t i_array)
+{
+ uint32_t l_type = 0;
+
+ if (i_type == "uint8_t")
+ {
+ l_type = SYM_ATTR_UINT8_TYPE;
+ }
+ else if(i_type == "uint32_t")
+ {
+ l_type = SYM_ATTR_UINT32_TYPE;
+ }
+ else if(i_type == "uint64_t")
+ {
+ l_type = SYM_ATTR_UINT64_TYPE;
+ }
+ else
+ {
+ printf("Unknown data type: %s\n",i_type.c_str());
+ exit(-1);
+ }
+
+ if(i_array > MAX_ATTRIBUTE_ARRAY_DIMENSION)
+ {
+ printf("Array dimension size for %s %u exceeded maximum dimension of %u\n",
+ i_type.c_str(),i_array,MAX_ATTRIBUTE_ARRAY_DIMENSION);
+ exit(-1);
+ }
+ // See enum definition on why this works
+ l_type += (i_array*ATTR_DIMENSION_SIZE_MULT)+i_array;
+
+ return(l_type);
+}
+
+// ------------------------------------------------------------------------------------------------
+
+void Symbols::add_define(const string * name, const Rpn * rpn)
+{
+ string s(*name);
+ translate_spyname(s);
+ iv_defines[s] = DEF_DATA(*rpn,NOT_USED);
+}
+
+// -------------------------------------------------------------------------------------------------
+
+Rpn Symbols::get_define_rpn(uint32_t rpn_id)
+{
+ Rpn r(this);
+ for(DEF_MAP::iterator i = iv_defines.begin(); i != iv_defines.end(); ++i)
+ {
+ if(i->second.second == rpn_id)
+ {
+ r = i->second.first;
+ break;
+ }
+ }
+ return r;
+}
+
+// ------------------------------------------------------------------------------------------------
+
+uint32_t Symbols::use_symbol(string & i_symbol)
+{
+ uint32_t rpn_id = Rpn::SYMBOL | NOT_FOUND;
+ if(i_symbol == "ANY") rpn_id = INIT_ANY_LIT | Rpn::SYMBOL;
+ else if(i_symbol == "EXPR") rpn_id = INIT_EXPR_VAR | Rpn::SYMBOL;
+ else if(i_symbol.compare(0,3,"DEF") == 0)
+ {
+ DEF_MAP::iterator i = iv_defines.find(i_symbol);
+ if(i != iv_defines.end())
+ {
+ if(i->second.second == NOT_USED)
+ {
+ rpn_id = Rpn::DEFINE | iv_rpn_id++;
+ i->second.second = rpn_id;
+ }
+ else
+ {
+ rpn_id = i->second.second;
+ }
+ }
+ else
+ {
+ rpn_id = add_undefined(i_symbol);
+ }
+ }
+ else
+ {
+ SYMBOL_MAP::iterator i = iv_symbols.find(i_symbol);
+ if(i != iv_symbols.end())
+ {
+ if(i->second.second == NOT_USED)
+ {
+ rpn_id = Rpn::SYMBOL | iv_rpn_id++;
+ i->second.second = rpn_id;
+ iv_rpn_map[rpn_id] = RPN_DATA(i_symbol,i->second.first);
+
+ //printf ("Symbols::use_symbol: Just added %s symbol, rpn_id:0x%8X to iv_rpn_map\n",i_symbol.c_str(),rpn_id);
+
+ if(i->second.first & CINI_LIT_MASK) ++iv_used_lit_count;
+ else ++iv_used_var_count;
+ }
+ else
+ {
+ rpn_id = i->second.second;
+ }
+ }
+ else
+ {
+ rpn_id = add_undefined(i_symbol);
+ }
+ }
+
+ return rpn_id;
+}
+
+// ------------------------------------------------------------------------------------------------
+
+uint32_t Symbols::add_undefined(const string & i_symbol)
+{
+ uint32_t rpn_id = 0;
+
+ SYMBOL_MAP::iterator i = iv_not_found.find(i_symbol);
+ if(i != iv_not_found.end())
+ {
+ rpn_id = i->second.second;
+ }
+ else
+ {
+ rpn_id = Rpn::SYMBOL | iv_rpn_id++;
+ iv_not_found[i_symbol] = MAP_DATA(NOT_FOUND,rpn_id);
+ iv_rpn_map[rpn_id] = RPN_DATA(i_symbol,CINI_ID_NOT_FOUND);
+ }
+ return rpn_id;
+}
+
+// ------------------------------------------------------------------------------------------------
+
+uint16_t Symbols::get_tag(uint32_t i_rpn_id)
+{
+ uint16_t tag = NOT_FOUND;
+ uint32_t cini_id = CINI_ID_NOT_FOUND;
+
+ // Set up tag table if not already setup
+ if(iv_used_var.size() == 0)
+ {
+ iv_used_var.reserve(iv_used_var_count); // makes if faster
+ iv_used_lit.reserve(iv_used_lit_count);
+
+ iv_used_var.push_back(iv_rpn_map[Rpn::SYMBOL|INIT_EXPR_VAR].second); // EXPR var always first
+ iv_used_lit.push_back(iv_rpn_map[Rpn::SYMBOL|INIT_ANY_LIT].second); // ANY lit always first
+
+ for(SYMBOL_MAP::iterator i = iv_symbols.begin(); i != iv_symbols.end(); ++i)
+ {
+ if(i->second.second != NOT_USED)
+ {
+ if((i->second.first & CINI_LIT_MASK) == CINI_LIT_MASK)
+ {
+ iv_used_lit.push_back(i->second.first);
+ }
+ else //VAR
+ {
+ iv_used_var.push_back(i->second.first);
+ }
+ }
+ }
+ }
+
+ do
+ {
+
+ RPN_MAP::iterator rm = iv_rpn_map.find(i_rpn_id);
+ if(rm != iv_rpn_map.end())
+ {
+ cini_id = (rm->second).second;
+ }
+ else
+ {
+ //SYMBOL_MAP::iterator sm = iv_not_found.begin();
+ //for(; sm != iv_not_found.end(); ++sm)
+ //{
+ // if((sm->second).second == i_rpn_id)
+ // {
+ // break;
+ // }
+ //}
+
+ //if(sm == iv_not_found.end())
+ //{
+ ostringstream err;
+ err << hex;
+ err << "ERROR! Symbols::get_tag() bad arg rpn_id = " << i_rpn_id << endl;
+ throw invalid_argument(err.str());
+ //}
+ break;
+ }
+
+ uint32_t offset = 0;
+ for(SYMBOL_USED::iterator i = iv_used_var.begin(); i != iv_used_var.end(); ++i,++offset)
+ {
+ if(cini_id == *i)
+ {
+ tag = (uint16_t) (offset | IF_ATTR_TYPE);
+ break;
+ }
+ }
+
+ } while(0);
+
+ return tag;
+}
+
+
+
+
+// ------------------------------------------------------------------------------------------------
+
+string Symbols::find_name(uint32_t i_rpn_id)
+{
+ string name;
+ RPN_MAP::iterator rm = iv_rpn_map.find(i_rpn_id);
+ if(rm != iv_rpn_map.end())
+ {
+ name = (rm->second).first;
+ }
+ else name = "NOT FOUND";
+ return name;
+}
+
+// ------------------------------------------------------------------------------------------------
+
+uint32_t Symbols::find_numeric_lit(uint64_t i_data, int32_t byte_size)
+{
+ uint32_t offset = 0;
+ LIT_LIST::iterator i = iv_lits.begin();
+ for(; i != iv_lits.end(); ++i,++offset)
+ {
+ if(i_data == i->first && (uint32_t)byte_size == i->second)
+ break;
+ }
+ if(i == iv_lits.end())
+ {
+ iv_lits.push_back(LIT_DATA(i_data,byte_size));
+ }
+ //printf("Symbols::find_numeric_lit: i_data:0x%llX byte_size:%d Tag:0x%X\n",
+ // i_data,byte_size, offset | Rpn::NUMBER);
+ return offset | Rpn::NUMBER;
+}
+
+uint32_t Symbols::find_numeric_array_lit(uint64_t i_data, int32_t byte_size)
+{
+ uint32_t offset = 0;
+ LIT_LIST::iterator i = iv_lits.begin();
+ for(; i != iv_lits.end(); ++i,++offset)
+ {
+ if(i_data == i->first && (uint32_t)byte_size == i->second)
+ break;
+ }
+ if(i == iv_lits.end())
+ {
+ iv_lits.push_back(LIT_DATA(i_data,byte_size));
+ }
+ //printf("Symbols::find_numeric_lit: i_data:0x%llX byte_size:%d Tag:0x%X\n",
+ // i_data,byte_size, offset | Rpn::NUMBER);
+ return offset | Rpn::ARRAY_INDEX;
+}
+
+// ------------------------------------------------------------------------------------------------
+
+uint16_t Symbols::get_numeric_tag(uint32_t i_rpn_id)
+{
+ uint32_t tag = NOT_FOUND;
+ uint32_t offset = i_rpn_id - Rpn::NUMBER;
+ string any("ANY");
+ if(iv_used_lit.size() == 0) get_tag(use_symbol(any));
+ if(offset < iv_lits.size())
+ {
+ // numeric lits are numbered after enum lits, but with different TYPE
+ tag = (iv_used_lit.size() + offset) | IF_NUM_TYPE;
+ }
+ else
+ {
+ ostringstream err;
+ err << hex;
+ err << "ERROR! - Symbols::get_numeric_tag() invalid arg rpn_id = " << i_rpn_id << endl;
+ throw invalid_argument(err.str());
+ }
+ return (uint16_t)tag;
+}
+
+// ------------------------------------------------------------------------------------------------
+
+uint16_t Symbols::get_numeric_array_tag(uint32_t i_rpn_id)
+{
+ uint32_t tag = NOT_FOUND;
+ uint32_t offset = i_rpn_id - Rpn::ARRAY_INDEX;
+ string any("ANY");
+ if(iv_used_lit.size() == 0) get_tag(use_symbol(any));
+ if(offset < iv_lits.size())
+ {
+ // numeric lits are numbered after enum lits, but with different TYPE
+ tag = (iv_used_lit.size() + offset) | IF_NUM_TYPE;
+ }
+ else
+ {
+ ostringstream err;
+ err << hex;
+ err << "ERROR! - Symbols::get_numeric_array_tag() invalid arg rpn_id = " << i_rpn_id << endl;
+ throw invalid_argument(err.str());
+ }
+ return (uint16_t)tag;
+}
+
+// ------------------------------------------------------------------------------------------------
+
+uint64_t Symbols::get_numeric_data(uint32_t i_rpn_id, uint32_t & o_size)
+{
+ uint64_t data = 0;
+ o_size = 0;
+ uint32_t offset = i_rpn_id - Rpn::NUMBER;
+ if(offset < iv_lits.size())
+ {
+ LIT_DATA d = iv_lits[offset];
+ data = d.first;
+ o_size = d.second;
+ }
+ else
+ {
+ ostringstream err;
+ err << hex;
+ err << "ERROR! - Symbols::get_numeric_data() invalid arg rpn_id = " << i_rpn_id << endl;
+ throw invalid_argument(err.str());
+ }
+ return data;
+}
+
+// ------------------------------------------------------------------------------------------------
+uint64_t Symbols::get_attr_enum_val(string & i_attr_enum)
+{
+ return iv_attr_enum[i_attr_enum];
+}
+
+// ------------------------------------------------------------------------------------------------
+
+string Symbols::find_text(uint32_t i_cini_id)
+{
+ string name = "NOT FOUND";
+ if(i_cini_id == CINI_LIT_MASK) name = "ANY";
+ else if(i_cini_id == SYM_EXPR) name = "EXPR";
+ else
+ {
+ for(SYMBOL_MAP::const_iterator i = iv_symbols.begin(); i != iv_symbols.end(); ++i)
+ {
+ //printf("SYMBOL:%s\n",i->first.c_str());
+ if((i->second).first == i_cini_id)
+ {
+ name = i->first;
+ break;
+ }
+ }
+// for(RPN_MAP::iterator i = iv_rpn_map.begin(); i != iv_rpn_map.end(); ++i)
+// {
+// if((i->second).second == i_cini_id)
+// {
+// name = (i->second).first;
+// break;
+// }
+// }
+ }
+ return name;
+}
+
+
+// ------------------------------------------------------------------------------------------------
+
+uint32_t Symbols::get_spy_id(const string & spyname)
+{
+ uint32_t id = NOT_FOUND;
+ string s = spyname;
+ translate_spyname(s);
+ SPY_MAP::iterator sm = iv_spymap.find(s);
+ if(sm != iv_spymap.end())
+ {
+ id = sm->second;
+ }
+ else
+ {
+ size_t pos = s.find('-');
+ if(pos == string::npos) s.insert(0,"SPY_");
+ else
+ {
+ s[pos] = '_';
+ s.insert(pos+1,"SPY_");
+ s.insert(0,"ENUM_");
+ }
+ iv_not_found[s] = MAP_DATA(0,0);
+ //cerr << "ERROR! Symbols::get_spy_id() Spyname not found " << '[' << s << ']' << endl;
+ }
+ return id;
+}
+
+// ------------------------------------------------------------------------------------------------
+
+uint32_t Symbols::use_enum(const string & enumname)
+{
+ uint32_t rpn_id = NOT_FOUND;
+ string s = enumname;
+ translate_spyname(s);
+ SPY_MAP::iterator sm = iv_enums.find(s);
+ if(sm != iv_enums.end())
+ {
+ rpn_id = sm->second;
+ }
+ else
+ {
+ printf("Error!\n");
+ exit(0);
+ }
+ return rpn_id;
+}
+
+// ------------------------------------------------------------------------------------------------
+
+uint32_t Symbols::get_spy_enum_id(uint32_t i_rpn_id, const string & spyname)
+{
+ //uint32_t id = NOT_FOUND;
+ string enumname = get_enum_name(i_rpn_id);
+ enumname.append("-");
+ enumname.append(spyname);
+ return get_spy_id(enumname);
+}
+
+// ------------------------------------------------------------------------------------------------
+
+string Symbols::get_enum_name(uint32_t i_rpn_id)
+{
+ string name("SPY ENUM NOT FOUND");
+ for(SPY_MAP::iterator i = iv_enums.begin(); i != iv_enums.end(); ++i)
+ {
+ if(i->second == i_rpn_id)
+ {
+ name = i->first;
+ break;
+ }
+ }
+ return name;
+}
+
+// ------------------------------------------------------------------------------------------------
+
+string Symbols::full_listing()
+{
+ uint32_t count = 0;
+ ostringstream oss;
+ oss << hex << setfill('0');
+
+ for(SYMBOL_MAP::iterator i = iv_symbols.begin(); i != iv_symbols.end(); ++i)
+ {
+ if(i->second.first < CINI_LIT_MASK) //VAR
+ {
+ ++count;
+ oss << "0x" << setw(8) << i->second.first << '\t'
+ << '[' << i->first << ']' << endl;
+ }
+ }
+
+ ostringstream title;
+ title << "\n--------------- Attribute Symbol Table ---------------\n\n"
+ << "0x" << hex << setfill('0') << setw(8) << count << '\t'
+ << "Number of variables\n" << oss.str();
+
+ oss.str("");
+ count = 0;
+
+ for(SYMBOL_MAP::iterator i = iv_symbols.begin(); i != iv_symbols.end(); ++i)
+ {
+ if((i->second.first & CINI_LIT_MASK) == CINI_LIT_MASK) //LIT
+ {
+ ++count;
+ oss << "0x" << setw(8) << i->second.first << '\t'
+ << '[' << i->first << ']' << endl;
+ }
+ }
+
+ title << "\n--------------- Literal Symbol Table -----------------\n\n"
+ << setw(8) << count << '\t' << "Number of enumerated literals\n"
+ << oss.str();
+
+ oss.str("");
+ title << "\n-------------------- Spies and arrays ----------------------\n\n"
+ << "0x" << setw(8) << iv_spymap.size() << '\t' << "Number of spies and array symbols\n";
+
+ for(SPY_MAP::iterator i = iv_spymap.begin(); i != iv_spymap.end(); ++i)
+ {
+ oss << "0x" << setw(8) << i->second << '\t' << '[' << i->first << ']' << endl;
+ }
+
+ title << oss.str();
+
+ return title.str();
+}
+
+// ------------------------------------------------------------------------------------------------
+
+string Symbols::listing()
+{
+ uint32_t count = 0;
+ ostringstream oss;
+
+ // Set up tag table if not already setup
+ string any = "ANY";
+ get_tag(use_symbol(any));
+
+ oss << hex << setfill('0');
+
+ oss << "\n--------------- Attribute Symbol Table ---------------\n\n"
+ << "0x" << setw(4) << iv_used_var.size()-1 << '\t' << "Number of variables\n";
+
+ for(SYMBOL_USED::iterator i = iv_used_var.begin() + 1; i != iv_used_var.end(); ++i)
+ {
+ ++count;
+ oss << "Type:" << setw(2) << iv_attr_type[find_text(*i)] << " Value:0x" << setw(8) << (*i) << '\t' << "ID 0X" << setw(4) << (count | IF_ATTR_TYPE)
+ << '\t' << '[' << find_text(*i) << ']' << endl;
+
+ //printf("ATTRIBUTE: %s Value:0x%02X\n",(find_text(*i)).c_str(),iv_attr_type[find_text(*i)]);
+ }
+
+ count = 0;
+
+ oss << "\n--------------- Literal Symbol Table -----------------\n\n";
+
+ oss << "\n0x" << setw(4) << iv_lits.size() << '\t' << "Number of numeric literals\n";
+
+ count = 0;
+ for(LIT_LIST::iterator i = iv_lits.begin(); i != iv_lits.end(); ++i,++count)
+ {
+ oss << "0x" << setw(2) << i->second << endl
+ << "0x" << setw(2 * i->second) << i->first;
+ if(i->second < 6) oss << "\t\t";
+ else oss<< '\t';
+ oss << "ID 0x" << setw(4) << get_numeric_tag(count | Rpn::NUMBER) << endl;
+ }
+
+ oss << not_found_listing();
+
+ return oss.str();
+}
+
+// ------------------------------------------------------------------------------------------------
+
+string Symbols::attr_listing()
+{
+ ostringstream oss;
+
+ // Set up tag table if not already setup
+ string any = "ANY";
+ get_tag(use_symbol(any));
+
+ for(SYMBOL_USED::iterator i = iv_used_var.begin() + 1; i != iv_used_var.end(); ++i)
+ {
+ oss << find_text(*i) << endl;
+ }
+
+ return oss.str();
+}
+
+// ------------------------------------------------------------------------------------------------
+
+string Symbols::not_found_listing()
+{
+ ostringstream oss;
+ if(iv_not_found.size())
+ {
+ oss << "\n------------- Symbols requested that were NOT FOUND ---------------\n\n";
+ for(SYMBOL_MAP::iterator i = iv_not_found.begin(); i != iv_not_found.end(); ++i)
+ {
+ //if(i->first == "SPY_NOTFOUND" || (i->first).compare(0,13,"ENUM_NOTFOUND") == 0) continue;
+ oss << '[' << i->first << ']' << endl;
+ }
+ }
+ return oss.str();
+}
+
+// ------------------------------------------------------------------------------------------------
+
+uint32_t Symbols::bin_vars(BINSEQ & blist)
+{
+ // Set up tag table if not already setup
+ string any = "ANY";
+ get_tag(use_symbol(any));
+
+ uint32_t count = iv_used_var.size() - 1; // first VAR is 'EXPR' and is not stored
+
+ Rpn::set16(blist,(uint16_t)count);
+
+ for(SYMBOL_USED::iterator i = iv_used_var.begin() + 1; i != iv_used_var.end(); ++i)
+ {
+ // Write out the attribute type (i.e. uint8_t, uint16_t, ...) and it's index number
+ Rpn::set8(blist,iv_attr_type[find_text(*i)]);
+ Rpn::set32(blist,(*i));
+ //printf("Symbols::bin_vars: Just wrote out type:%u value:%u\n",iv_attr_type[find_text(*i)],*i);
+ }
+ return count;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+uint32_t Symbols::bin_lits(BINSEQ & blist)
+{
+ // Set up tag table if not already setup
+ string any = "ANY";
+ get_tag(use_symbol(any));
+
+ uint32_t count = iv_lits.size();
+ uint32_t total = count;
+
+ Rpn::set16(blist,(uint16_t)count);
+
+ for(LIT_LIST::iterator i = iv_lits.begin(); i != iv_lits.end(); ++i)
+ {
+ uint32_t size = i->second;
+ uint64_t data = i->first;
+ blist.push_back( (uint8_t)size );
+ uint32_t shift_count = size * 8;
+ while(shift_count)
+ {
+ shift_count -= 8;
+ blist.push_back( (uint8_t)(data >> shift_count) );
+ }
+ }
+ total += count;
+
+ return total;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+uint32_t Symbols::restore_var_bseq(BINSEQ::const_iterator & bli)
+{
+ uint32_t count = Rpn::extract16(bli);
+
+ iv_used_var.clear();
+ iv_used_var.push_back(iv_rpn_map[Rpn::SYMBOL|INIT_EXPR_VAR].second); // EXPR var always first
+
+ for(uint32_t i = 0; i < count; ++i)
+ {
+ uint8_t type = Rpn::extract8(bli);
+ uint32_t attribute = Rpn::extract32(bli);
+ iv_attr_type[find_text(attribute)] = type;
+ iv_used_var.push_back(attribute);
+ }
+ return count;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+uint32_t Symbols::restore_lit_bseq(BINSEQ::const_iterator & bli)
+{
+ iv_used_lit.clear();
+ iv_used_lit.push_back(iv_rpn_map[Rpn::SYMBOL|INIT_ANY_LIT].second); // ANY lit always first
+
+ iv_lits.clear();
+ uint32_t num_count = Rpn::extract16(bli);
+
+ for(uint32_t i = 0; i < num_count; ++i)
+ {
+ uint8_t size = *bli++;
+ uint64_t data = 0;
+ switch (size)
+ {
+ case 1: data = *bli++; break;
+ case 2: data = Rpn::extract16(bli); break;
+ case 4: data = Rpn::extract32(bli); break;
+ case 8: data = Rpn::extract64(bli); break;
+ default:
+ {
+ ostringstream errs;
+ errs << "ERROR! Symbols::restore_var_bseq(). Invalid literal data size ["
+ << size << ']' << endl;
+ throw invalid_argument(errs.str());
+ }
+ break;
+ }
+
+ iv_lits.push_back( LIT_DATA(data, size) );
+ }
+
+ return num_count;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+string Symbols::get_spyname(uint32_t spy_id)
+{
+ string name;
+
+ for(SPY_MAP::const_iterator i = iv_spymap.begin(); i != iv_spymap.end(); ++i)
+ {
+ if (i->second == spy_id)
+ {
+ name = i->first;
+ break;
+ }
+ }
+ if(name.length() == 0)
+ {
+ ostringstream oss;
+ oss << hex << setfill('0');
+ oss << "[0x" << setw(8) << spy_id << ']';
+ name = oss.str();
+ }
+ return name;
+}
+//-------------------------------------------------------------------------------------------------
+
+string Symbols::get_enumname(uint32_t spy_id)
+{
+ string name = get_spyname(spy_id);
+ size_t pos = name.find('-');
+ if(pos != string::npos)
+ {
+ name = name.substr(0,pos);
+ }
+ return name;
+}
+
+//-------------------------------------------------------------------------------------------------
+
+uint32_t Symbols::get_rpn_id(uint32_t bin_tag)
+{
+ uint32_t rpn_id = NOT_FOUND;
+ uint32_t type = bin_tag & IF_TYPE_MASK;
+ uint32_t offset = bin_tag & ~IF_TYPE_MASK;
+ uint32_t cini_id = 0;
+ switch(type)
+ {
+ case IF_ATTR_TYPE: {
+ cini_id = iv_used_var[offset];
+ string name = find_text(cini_id);
+ rpn_id = use_symbol(name);
+ }
+ break;
+
+ case IF_NUM_TYPE: {
+ offset -= iv_used_lit.size();
+ if(offset >= iv_lits.size())
+ {
+ ostringstream erros;
+ erros << hex;
+ erros << "ERROR! Symbols::get_rpn_id() Invalid NUM_TYPE 0x"
+ << bin_tag;
+ throw range_error(erros.str());
+ }
+ LIT_DATA d = iv_lits[offset];
+ rpn_id = find_numeric_lit(d.first,d.second);
+ }
+ break;
+
+ default:
+ {
+ ostringstream erros;
+ erros << hex
+ << "ERROR! Symbols::get_rpn_id() Invalid bin_tag = 0x"
+ << bin_tag << endl;
+ throw range_error(erros.str());
+ }
+ break;
+ }
+ return rpn_id;
+}
+//-------------------------------------------------------------------------------------------------
+
+string Symbols::spies_are_in(Symbols & i_full_list, const set<string> & i_ignore_spies)
+{
+ ostringstream result;
+ result << hex;
+
+ for(SPY_MAP::iterator i = iv_spymap.begin(); i != iv_spymap.end(); ++i)
+ {
+ // enums in the reduced file will soon no longer contain the spyname as part of the enum name <enum name>-<spy name>
+ // At that time we will just need to check the enum part of the name <enum name> in both the ignore file and the full list
+ // When initfile processing AND spyhunter both use only enum names for enum spies then we can simplify all this
+ string spyname = i->first;
+ size_t pos = spyname.find('-'); // check for enum - if so just use the spy part of the name
+ if(pos != string::npos)
+ {
+ spyname = spyname.substr(pos+1);
+ }
+
+ if(i_ignore_spies.find(spyname) != i_ignore_spies.end()) //don't check this spy or any of it's enums
+ {
+ cout << "Will not check spy: " << i->first << endl;
+ continue;
+ }
+
+ uint32_t hash = 0;
+ if(pos != string::npos) // old enum style name - check by hash - only check enumname
+ {
+ // just compare enum names based on hash
+ string enumname1 = (i->first).substr(0,pos);
+ string enumname2 = i_full_list.get_enumname(i->second);
+ if(enumname1 != enumname2)
+ {
+ result << "ERROR! Enum not found for spy " << i->first << '\n'
+ << " Enum: " << enumname1 << "!=" << enumname2 << endl;
+ }
+ }
+ else // check spyname by name or new-style enum by name
+ {
+ hash = i_full_list.get_spy_id(i->first);
+ if(hash != NOT_FOUND)
+ {
+ if(hash != i->second)
+ {
+ result << "ERROR! HASH not the same for spy "
+ << i->first << ' ' << hash << ' ' << i->second << endl;
+ }
+ // else cout << "Found " << i->first << ' ' << i->second << endl;
+ }
+ }
+ }
+ result << i_full_list.not_found_listing();
+
+
+ return result.str();
+}
+
+
+
+
+
diff --git a/src/usr/hwpf/ifcompiler/initSymbols.H b/src/usr/hwpf/ifcompiler/initSymbols.H
new file mode 100755
index 000000000..efef0dcbe
--- /dev/null
+++ b/src/usr/hwpf/ifcompiler/initSymbols.H
@@ -0,0 +1,269 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/ifcompiler/initSymbols.H,v $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2010,2010
+//
+//UNDEFINED
+//
+// Origin: UNDEFINED
+//
+// IBM_PROLOG_END_TAG
+#if !defined(INITSYMBOLS_H)
+#define INITSYMBOLS_H
+
+// Change Log *************************************************************************************
+//
+// Flag Track Userid Date Description
+// ---- -------- -------- -------- -------------------------------------------------------------
+// D754106 dgilbert 06/14/10 Create
+// 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
+// mjjones 11/17/11 Output attribute listing
+// End Change Log *********************************************************************************
+
+/**
+ * @file initSymbols.H
+ * @brief Definition of the initSymbols class. Handles all symbols for initfiles
+ */
+
+// Definitions:
+// cini_id is the 32 bit symbol tag value of a CINI initfile literal or variable as defined in ciniIfSymbols.H
+// rpn_id is an internal representation used by the Rpn class for all numbers, symbols, Spy enums, etc. that is not an operator
+// bin_id is the 16 bit tag used to represet number, symbols, enums, etc. in the compiled initfile.
+
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+#include <map>
+#include <set>
+#include <initRpn.H>
+#include <fapiHwpInitFileInclude.H> // Requires file from hwpf
+
+using namespace std;
+
+
+namespace init
+{
+ typedef set<string> FILELIST;
+
+ class Symbols
+ {
+ public:
+
+ enum
+ {
+ CINI_LIT_MASK = 0xA0000000,
+ INIT_ANY_LIT = 0x07FFFFFE,
+ INIT_EXPR_VAR = 0x07FFFFFF,
+ };
+
+
+
+ enum
+ {
+ NOT_FOUND = 0x00000000,
+ NOT_USED = 0x00000000,
+ CINI_ID_NOT_FOUND = 0x80000000,
+ };
+
+ /**
+ * Build symbol map for list of files
+ * @param List of files to open to build Symbols
+ */
+ Symbols(FILELIST & i_filenames);
+
+ /**
+ * Add a Symbol to the "used" symbol table if not already there
+ * @param string Symbols name
+ * @returns Symbols Rpn id
+ * @post marks the id as 'USED'
+ *
+ */
+ uint32_t use_symbol(string & i_symbol);
+
+ /**
+ * Lookup the tag id from the rpn_id provided by use_symbol()
+ * @returns tag id
+ * @param rpn_id
+ * @pre all the symbols have been marked used (no new symbols)
+ * @post tag table built if not already built.
+ * @note tag bits 0bttxxxxxx xxxxxxxx
+ * tt == 0b01 -> enumerated literal
+ * tt == 0b10 -> Variable name
+ * tt == 0b11 -> Numeric constant
+ * xxxxxx xxxxxxxx assigned tag offset
+ */
+ uint16_t get_tag(uint32_t i_rpn_id);
+
+ /**
+ * Find the symbol name associated with an rpn_id
+ * @param uint32_t rpn_id
+ * @returns string Symbol name | "" if not found
+ */
+ string find_name(uint32_t i_rpn_id);
+
+ /**
+ * Find the tag for the numeric lit
+ * @param data
+ * @param number of significant bytes in the data [1-8]
+ * @returns Rpn id
+ */
+ uint32_t find_numeric_lit(uint64_t i_data, int32_t byte_size);
+
+ /**
+ * Find the tag for the numeric array lit
+ * @param data
+ * @param number of significant bytes in the data [1-8]
+ * @returns Rpn id
+ */
+ uint32_t find_numeric_array_lit(uint64_t i_data, int32_t byte_size);
+
+ /**
+ * Convert a numeric literal Rpn tag to an initfile tag
+ * @param Rpn id returned by find_numeric_lit
+ * @return tag
+ * @pre Must not be called until find_numeric_lit() has been called for all numbers
+ * in the initfile.
+ */
+ uint16_t get_numeric_tag(uint32_t i_rpn_id);
+
+ /**
+ * Convert a numeric array literal Rpn tag to an initfile tag
+ * @param Rpn id returned by find_numeric_lit
+ * @return tag
+ * @pre Must not be called until find_numeric_array_lit() has been called for all numbers
+ * in the initfile.
+ */
+ uint16_t get_numeric_array_tag(uint32_t i_rpn_id);
+
+ /**
+ * Get the literal data value from the Rpn id returned by find_numeric_lit()
+ * @param uint32_t Rpn id
+ * @param uint32_t for returned byte size
+ * @returns uint64_t data
+ */
+ uint64_t get_numeric_data(uint32_t i_rpn_id, uint32_t & o_size);
+
+ /**
+ * Get the attribute enum value for the attr enum
+ * @param string attribute enum name
+ * @returns uint64_t value
+ */
+ uint64_t get_attr_enum_val(string & i_attr_enum);
+
+
+ /**
+ * Store enum name & return rpn_id
+ */
+ uint32_t use_enum(const string & enumname);
+ uint32_t get_spy_enum_id(uint32_t i_rpn_id, const string & spyname);
+ string get_enum_name(uint32_t i_rpn_id);
+
+ string get_enumname(uint32_t spy_id);
+ string get_spyname(uint32_t spy_id);
+
+ /**
+ * Return spy id
+ */
+ uint32_t get_spy_id(const string & spyname);
+
+ void add_define(const string * name, const Rpn * rpn);
+ Rpn get_define_rpn(uint32_t rpn_id);
+ void clear_defines() { iv_defines.clear(); }
+
+
+ string listing(); ///< listing of used vars & lits
+ string attr_listing(); ///< listing of used HWPF attributes
+ uint32_t bin_vars(BINSEQ & blist); ///< binary byte output of used vars. ret # vars
+ uint32_t bin_lits(BINSEQ & blist); ///< binary byte sequence of used lits ret # lits
+
+ string full_listing(); ///< listing of all vars & lits (debug)
+ string not_found_listing(); ///< listing of all vars searched for, but not found
+
+ /**
+ * Get the rpn_id from an initfile binary tag
+ */
+ uint32_t get_rpn_id(uint32_t bin_tag);
+
+
+ /**
+ * Restore used symbol lists from binary sequence
+ * @returns number of symbols
+ */
+ uint32_t restore_var_bseq(BINSEQ::const_iterator & bli);
+ uint32_t restore_lit_bseq(BINSEQ::const_iterator & bli);
+
+ /**
+ * Test that all spies in this object are a subset of the object provided
+ * @param Symbols object to compare against
+ * @return string will all error messages. Empty string indicates success.
+ */
+ string spies_are_in(Symbols & i_full_list, const set<string> & i_ignore_spies);
+
+ static void translate_spyname(string & s)
+ {
+ for(string::iterator i = s.begin(); i != s.end(); ++i)
+ if((*i) == '.' || (*i) == '#' ||
+ (*i) == '=' || (*i) == '&' ||
+ (*i) == '<' || (*i) == '>' ||
+ (*i) == '!' || (*i) == '*' ||
+ (*i) == '/' || (*i) == '%' ||
+ (*i) == '$') *i = '_';
+ else *i = toupper(*i);
+ }
+
+ private: // functions
+
+ string find_text(uint32_t i_cini_id);
+ uint32_t add_undefined(const string & s);
+ uint32_t get_attr_type(const string &i_type, const uint32_t i_array);
+
+ private: //data
+
+ // map | symbol name | (cini_id, usage flags) |
+ typedef pair<uint32_t,uint32_t> MAP_DATA;
+ typedef map<string,MAP_DATA > SYMBOL_MAP;
+ typedef map<string,uint32_t> SPY_MAP;
+ typedef map<string,uint32_t> SYMBOL_ATTR_TYPE;
+ typedef map<string,uint64_t> SYMBOL_ATTR_ENUM;
+
+ typedef pair<Rpn,uint32_t> DEF_DATA;
+ typedef map<string,DEF_DATA> DEF_MAP;
+
+ typedef pair<string,uint32_t> RPN_DATA;
+ typedef map<uint32_t,RPN_DATA> RPN_MAP;
+
+ typedef vector<uint32_t> SYMBOL_USED;
+
+ typedef pair<uint64_t,uint32_t> LIT_DATA;
+ typedef vector<LIT_DATA> LIT_LIST;
+
+ SYMBOL_MAP iv_symbols; ///< From ciniIfSymbols.H all vars and enumerated lits
+ SYMBOL_ATTR_TYPE iv_attr_type;
+ SYMBOL_ATTR_ENUM iv_attr_enum;
+ SYMBOL_MAP iv_not_found; ///< List of symbols not found
+ RPN_MAP iv_rpn_map; ///< Map rpn_id to symbol name/cini_id of used Symbols
+ SYMBOL_USED iv_used_var; ///< List of cini_ids of used vars ordered by name
+ SYMBOL_USED iv_used_lit; ///< List of cini_ids of used enum lits ordered by name
+
+ LIT_LIST iv_lits; ///< Numeric literals
+
+ SPY_MAP iv_spymap; ///< Spies & arrays & enum spies
+ SPY_MAP iv_enums; ///< Spy enums
+
+ DEF_MAP iv_defines; ///< defines
+
+ uint32_t iv_used_var_count;
+ uint32_t iv_used_lit_count;
+ uint32_t iv_rpn_id; ///< Current rpn offset assignment
+ };
+};
+
+
+#endif
OpenPOWER on IntegriCloud