/* NO its NOT RANDOM the way I format my CODE */ #include "masc.h" #include<sstream> #include<stdarg.h> namespace masc { using std::cout; using std::endl; char *mysprintf(char *src, const char *sptr, ...) { va_list l; char *p, *sval = src, *ptr; va_start(l,sptr); for(p = const_cast<char*>(sptr); *p; p++) { if(*p != '%') { *sval = *p; sval++; continue; } else { switch(*++p) { case 'd': { int ival = va_arg(l,int); std::ostringstream s; s << ival; std::string d = s.str(); for(size_t i = 0; i < d.length(); i++) *sval = d[i], sval++; } break; case 's': for(ptr = va_arg(l, char*); *ptr; ptr++) *sval = *ptr, sval++; break; case 'f': { double dval = va_arg(l,double); std::ostringstream s; s << dval; std::string d = s.str(); for(size_t i = 0; i < d.length(); i++) *sval = d[i], sval++; } break; default: *sval = *p; sval++; break; } } } *sval = 0; return src; } int myprintf(const char *src, ...) { va_list l; char *p,*ptr; va_start(l,src); for(p = const_cast<char*>(src); *p; p++) { if(*p != '%') { putchar(*p); continue; } else { switch(*++p) { case 'd': { int ival = va_arg(l,int); std::cout << ival; break; } case 's': for(ptr = va_arg(l, char*); *ptr; ptr++) putchar(*ptr); break; case 'f': { double dval = va_arg(l,double); std::cout << dval; } break; default: putchar(*p); break; } } } return 0; } void Symbol_Table::Set(int type, std::string val, std::string name) { vars[name].name = name; vars[name].val = val; vars[name].type = type; } symb &Symbol_Table::Get(std::string name) { return vars[name]; } void Symbol_Table::DebugPrint() const { std::map<std::string,symb>::const_iterator i; for(i = vars.begin(); i != vars.end(); i++) std::cout << "Variable name: " << i->first << " Variable value: " << i->second.val << '\n'; } symb &Symbol_Table::operator() ( size_t pos ) { std::list<symb>::iterator i = st.begin(); for(size_t z = 0; z < pos; z++) i++; return *i; } symb Symbol_Table::Pop() { if(!st.empty()) { symb p = st.back(); st.pop_back(); return p; } return symb(); } void Symbol_Table::operator+=(const symb &s) { st.push_back(s); } symb Symbol_Table::operator--() { return Pop(); } void Symbol_Table::PopAll() { while(!st.empty()) st.pop_back(); } void Symbol_Table::Push(symb &s) { st.push_back(s); } Parser::Parser(std::string s) : MFile(s) , err(0) , current_line(0) { if(opened == true) { GetLine(); Begin(); } else { current_line = 0; ErrorMsg("Couldnt open file (%s)\n", s.c_str()); return; } } void Parser::StartParse(std::string str) { opened = false; Open(str); if(opened == true) { GetLine(); Begin(); } else { current_line = 0; ErrorMsg("Couldnt open file (%s)\n", str.c_str()); return; } } void Parser::Begin() { Parse(cur_line); if(!GetLine()) Begin(); } void Parser::Parse(std::string str) { std::string::iterator p; std::string cur_tok = ""; cur.line_num = curline; cur.source_file = file_name; cur.token = ""; str += "\n"; if(str.find("insert") != -1 && str.find('\"') != -1 && str.find(";") != -1) { std::string insert_file; insert_file = str.substr(str.find('\"')+1, str.length()); if(insert_file.find('\"') != -1) insert_file = insert_file.substr(0, insert_file.find('\"')); insert_vec.push_back(insert_file); } for(p = str.begin(); p != str.end(); p++) { if(*p == '/') return; if(isalpha(*p)) { cur_tok = ""; while(*p != '\n' && (isalpha(*p) || isdigit(*p) || *p == '_' || *p == '$' || *p == '&' || *p == '#' || *p == '.' || *p == '[' || *p == ']') && p != str.end()) { cur_tok += *p; p++; } if(*p != ':') cur.type = IDENTIFIER; else cur.type = CODELABEL; cur.token = cur_tok; tok_vec.push_back(cur); cur_tok = ""; } else if(isdigit(*p)) { cur_tok = ""; while((isdigit(*p) || *p == '.') && p != str.end()) { cur_tok += *p; p++; } cur.token = cur_tok; cur.type = DIGIT; tok_vec.push_back(cur); } else if(*p == '\"') { p++; while(*p != '\"' && p != str.end()) { if(*p != '\\') { cur_tok += *p; p++; } else if(*p == '\\') { p++; if(*p == '\"') cur_tok += *p, p++; else if(*p == 'n') cur_tok += '\n', p++; } } cur.token = cur_tok; cur.type = STRING; tok_vec.push_back(cur); cur_tok = ""; } switch(*p) { case '{': case '}': case ';': case ',': case '=': case '<': case '~': case '\'': case '@': case '!': case '#': case '$': case '%': case '^': case '&': case '*': case '(': case ')': case '-': case '+': case '/': case '\\': case '.': case '>': case ':': if(*(p+1) == '<') { p++; } cur.token = *p; cur.type = *p; tok_vec.push_back(cur); cur_tok = ""; break; } } } void Parser::DebugTokens() { for(unsigned int i = 0; i < tok_vec.size(); i++) cout << "token (type:" << int(tok_vec[i].type) << ") " << tok_vec[i].token << endl; } void Parser::ErrorMsg(const char *str, ...) { va_list l; char error_msg[5000]; va_start(l,str); vsprintf(const_cast<char*>(error_msg),str,l); va_end(l); cout << "**** error#: " << (++err) << " " << error_msg << " \n\t->line(" << current_line << ").file(" << current_file << ") " << endl; } bool Parser::LexAnayalize() { int masteronLucy = 0; std::string obj_name = ""; for(unsigned int z = 0; z < tok_vec.size(); z++) { current_line = tok_vec[z].line_num; current_file = tok_vec[z].source_file; int vid = IdentToValue(tok_vec[z].token); if(vid == TOK_USES) { std::map<std::string,masc::External_Callback>::iterator itz; for(itz = GetBend()->callb.begin(); itz != GetBend()->callb.end(); itz++) { if(itz->second.imp == true && itz->second.isdef == false) { std::map<std::string,std::string>::iterator it; bool found_it = false; for(it = GetBend()->obj.begin(); it != GetBend()->obj.end(); it++) { if(GetBend()->Find(it->second + "." + itz->second.other_name) != 0 || GetBend()->Find("master." + itz->second.other_name) != 0) { found_it = true; break; } } if(found_it == false) { ErrorMsg(" (fatal) procedure (%s) not implemented yet is defined to be so ", itz->second.name.c_str()); return false; } } } } else if(tok_vec[z].type == '{' && pBounds(z-4)) { int zid = IdentToValue(tok_vec[z-1].token), zzid = IdentToValue(tok_vec[z-2].token); if(zid == -1 && zzid != TOK_PROC && zzid != TOK_EXTERN && tok_vec[z-4].type != '}' && GetBend()->obj[tok_vec[z-1].token] == "") { ErrorMsg("Invalid object/uses/procedure name on opening block you put (%s)", tok_vec[z-1].token.c_str()); z++; continue; } } else if(pBounds(z-1) && (vid == TOK_USES || vid == TOK_BEGIN || vid == TOK_END || vid == TOK_PROC || vid == TOK_MAS || vid == TOK_MAIN) && pBounds(z-1)) { int rid = IdentToValue(tok_vec[z-1].token); if(rid == -1 && tok_vec[z-1].type != ';' && tok_vec[z-1].type != '}') { ErrorMsg("Error bad value before keyword (%s) i found (%s)", tok_array[vid], tok_vec[z-1].token.c_str()); z++; continue; } else { if((vid == TOK_MAS || vid == TOK_MAIN) && pBounds(z+1) && tok_vec[z+1].type == IDENTIFIER) { obj_name = tok_vec[z+1].token; continue; } } } else if(vid == TOK_IMPLEMENT) { if(pBounds(++z) && (vid = IdentToValue(tok_vec[z].token)) == TOK_PROC && pBounds(++z) && tok_vec[z].type == IDENTIFIER && pBounds(++z) && tok_vec[z].type == ';') { if(pBounds(z-1) && GetBend()->callb[obj_name + "." + tok_vec[z-1].token].imp == false) { ErrorMsg("implemented procedure is missing from object (%s)" ,""); continue; } } else { ErrorMsg(" there is a problem with the implement keyword probaly you forgot a semi-colon,proc keyword, or name "); } z++; } } current_line = 0; int ID = 0; for(unsigned int i = 0; i < tok_vec.size(); i++) { current_line = tok_vec[i].line_num; current_file = tok_vec[i].source_file; switch(tok_vec[i].type) { case IDENTIFIER: { int id = IdentToValue(tok_vec[i].token); switch(id) { case TOK_USES: { if(pBounds(i+3) && (tok_vec[i+1].type == '{')) { i+=2; while(pBounds(i) && tok_vec[i].type != '}') { if(pBounds(i) && tok_vec[i].type != ';' && GetBend()->obj[tok_vec[i].token] != tok_vec[i].token) { ErrorMsg("Error uses block is trying to inhert from a unknown object (%s)\n", tok_vec[i].token.c_str()); i++; continue; } i++; } } } break; case TOK_INSERT: { i++; if(pBounds(i)) { std::fstream f; f.open(tok_vec[i].token.c_str(), std::ios::in); if(f.is_open()) { f.close(); continue; } else f.close(), ErrorMsg("insert not including a file instead I found %s", tok_vec[i].token.c_str()); continue; } } break; case TOK_MAS: case TOK_MAIN: { if(id == TOK_MAIN) { masteronLucy++; if(masteronLucy >= 2) { ErrorMsg("(fatal) more than one main object cannot continue try only putting one master object in your script."); return false; } } if(pBounds(++i)) { int tid = IdentToValue(tok_vec[i].token); if(tid >= TOK_INSERT && tid <= VAR_FLOAT) { ErrorMsg("mas(ter) keyword found another keyword (%s) instead of name of the object.", tok_vec[i].token.c_str()); continue; } else if(tok_vec[i].type == DIGIT || tok_vec[i].type == STRING || (tok_vec[i].type >= '!' && tok_vec[i].type <= '@') || (tok_vec[i].type >= '{' && tok_vec[i].type <= '~')) { ErrorMsg("mas(ter) keyword found a digit,string,or special character instead of identifier (%s)", tok_vec[i].token.c_str()); continue; } } ID++; } break; case TOK_VAR: { ID++; i++; if(pBounds(i) && pBounds(i+1)) { if(tok_vec[i].type != '{') { ErrorMsg("(fatal) variable code block missing opening brace instead I found (%s) ", tok_vec[i].token.c_str()); return false; } } while(pBounds(++i) && tok_vec[i].type != '}') { current_line = tok_vec[i].line_num; current_file = tok_vec[i].source_file; int zid = IdentToValue(tok_vec[i].token); if(zid >= TOK_USES && zid <= TOK_EXTERN) { ErrorMsg("(fatal) found keyword (%s) instead of variable decleration (maybe you forgot } or \")", tok_vec[i].token.c_str()); return false; } if(zid >= VAR_INTEGER && zid <= VAR_FLOAT) { if(pBounds(++i)) { if(tok_vec[i].type != IDENTIFIER) { ErrorMsg(" found a string,digit,or special character (%s) instead of a identifier for variable name!", tok_vec[i].token.c_str()); continue; } else if(pBounds(++i) && tok_vec[i].type != '=' && tok_vec[i].type != ';') { ErrorMsg(" found %s instead of equal sign or semi-colon.", tok_vec[i].token.c_str()); continue; } else if(pBounds(i) && tok_vec[i].type == '=' && pBounds(++i) && tok_vec[i].type != STRING && tok_vec[i].type != DIGIT) { ErrorMsg(" looking for string or digit for varaible decleration initilzation instead i found (%s) ", tok_vec[i].token.c_str()); continue; } else if(pBounds(i) && (zid == VAR_INTEGER || zid == VAR_FLOAT) && tok_vec[i].type == STRING) { ErrorMsg(" numeric variable decleration contains a string (%s)", tok_vec[i].token.c_str()); continue; } else if(pBounds(i) && (zid == VAR_STRING) && tok_vec[i].type == DIGIT) { ErrorMsg(" string variable decleration contains numeric values (%s)", tok_vec[i].token.c_str()); continue; } } } else if(GetBend()->symbols.vars[tok_vec[i].token].name == "" && tok_vec[i].type != ',' && tok_vec[i].type != ';') { ErrorMsg("Error invalid variable decleration! (%s)", tok_vec[i].token.c_str()); continue; } } if(tok_vec[i].type == '}') continue; else { ErrorMsg("(fatal) variable code block missing closing brace !" ); return false; } } break; case TOK_EXTERN: case TOK_BEGIN: case TOK_END: case TOK_PROC: { ID++; if(id == TOK_EXTERN && pBounds(i+2) && tok_vec[i+1].type != IDENTIFIER && tok_vec[i+2].type != ';') { ErrorMsg("external function (c++) call dosent have a name, or is missing terminating semi-colon"); i+=2; continue; } if(id == TOK_BEGIN && pBounds(i+1) && tok_vec[i+1].type != '{') { ErrorMsg("looking for { on begin statement instead i found %s", tok_vec[i+1].token.c_str()); continue; } if(id == TOK_END && pBounds(i+1) && tok_vec[i+1].type != '{') { ErrorMsg("looking for { on end statement instead i found %s", tok_vec[i+1].token.c_str()); continue; } if(id == TOK_PROC && pBounds(i+2) && (tok_vec[i+2].type != '{' && tok_vec[i+2].type != ';') ) { ErrorMsg("looking for (normal) { or (extern) ; on procedure statement instead i found (%s)", tok_vec[i+2].token.c_str()); continue; } if(id == TOK_PROC && pBounds(++i) && tok_vec[i].type != IDENTIFIER) { ErrorMsg(" procedure has string or digit or symbol (%s) as a name", tok_vec[i].token.c_str()); continue; } i ++; while(pBounds(++i) && (tok_vec[i].type != '}')) { int prev_i = i; current_line = tok_vec[i].line_num; current_file = tok_vec[i].source_file; int qid = IdentToValue(tok_vec[i].token); if(qid == -1 && id != TOK_EXTERN && tok_vec[i].type == IDENTIFIER && GetBend()->symbols.vars[tok_vec[i].token].name == "" && GetBend()->callb[tok_vec[i].token].name == "" && GetBend()->labels[tok_vec[i].token].label_name == "" && GetBend()->Find(tok_vec[i].token) == 0) { ErrorMsg("Invalid instruction (%s)", tok_vec[i].token.c_str()); continue; } if(qid >= TOK_MOV && qid <= TOK_PRINT) { if(pBounds(i-1) && tok_vec[i-1].type != ';' && tok_vec[i-1].type != '{' && tok_vec[i-1].type != ':') { ErrorMsg(" Error should have found semi-colon instead found (%s) ", tok_vec[i-1].token.c_str()); continue; } switch(qid) { case TOK_MOV: case TOK_CMP: case TOK_ADD: case TOK_SUB: case TOK_MUL: case TOK_DIV: case TOK_OR: case TOK_XOR: case TOK_AND: { if(pBounds(++i) && tok_vec[i].type != IDENTIFIER) { ErrorMsg(" looking for variable name on (%s) instruction instead i found (%s)", tok_array[qid], tok_vec[i].token.c_str()); continue; } else if(pBounds(i) && tok_vec[i].type == IDENTIFIER && GetBend()->symbols.vars[tok_vec[i].token].name == "") { ErrorMsg(" looking for variable name on (%s) instruction instead i found (%s)", tok_array[qid], tok_vec[i].token.c_str()); continue; } else if(pBounds(i+2) && tok_vec[i+2].type == IDENTIFIER && GetBend()->symbols.vars[tok_vec[i].token].name == "") { ErrorMsg(" expected variable or constant on (%s) instruction operand 2 instead i found (%s)", tok_array[qid], tok_vec[i].token.c_str()); continue; } else if(pBounds(++i) && tok_vec[i].type != ',') { ErrorMsg(" looking for comma to seperate (%s) instruction instead i found (%s)", tok_array[qid],tok_vec[i].token.c_str()); continue; } else if(pBounds(++i) && tok_vec[i].type != IDENTIFIER && tok_vec[i].type != STRING && tok_vec[i].type != DIGIT) { ErrorMsg(" looking for variable or constant on (%s) instruction instead i found (%s)", tok_array[qid], tok_vec[i].token.c_str()); continue; } } break; case TOK_INC: case TOK_DEC: case TOK_NOT: case TOK_JMP: case TOK_JNE: case TOK_JE: case TOK_JL: case TOK_JG: case TOK_JGE: case TOK_JLE: case TOK_POP: { if((!(qid >= TOK_JMP && qid <= TOK_JGE) || qid == TOK_POP) && pBounds(++i) && tok_vec[i].type != IDENTIFIER) { ErrorMsg(" looking for variable name on (%s) instead I found (%s)" , tok_array[qid], tok_vec[i].token.c_str()); continue; } else if((!(qid >= TOK_JMP && qid <= TOK_JGE) || qid == TOK_POP) && pBounds(i) && tok_vec[i].type == IDENTIFIER && GetBend()->symbols.vars[tok_vec[i].token].name == "") { ErrorMsg(" looking for variable name on (%s) instead I found (%s)", tok_array[qid], tok_vec[i].token.c_str()); continue; } else if(qid >= TOK_JMP && qid <= TOK_JGE && pBounds(++i) && tok_vec[i].type != IDENTIFIER ) { ErrorMsg(" looking for code label to (%s) to instead I found which might not be a valid label (%s)", tok_array[qid],tok_vec[i].token.c_str()); continue; } else if(qid >= TOK_JMP && qid <= TOK_JGE && pBounds(i) && tok_vec[i].type == IDENTIFIER && GetBend()->labels[tok_vec[i].token].label_name == "") { ErrorMsg(" couldnt find label (%s) on instruction (%s) ", tok_vec[i].token.c_str(),tok_array[qid]); continue; } } break; case TOK_CALL: { if(pBounds(++i) && tok_vec[i].type != IDENTIFIER || (tok_vec[i].type == IDENTIFIER && GetBend()->Find(tok_vec[i].token) == 0 && GetBend()->callb[tok_vec[i].token].name == "")) { ErrorMsg("call instruction excpets a valid procedure or external C++ function instead i found (%s)", tok_vec[i].token.c_str()); continue; } } break; case TOK_PRINT: case TOK_SCAT: { if(qid == TOK_PRINT && pBounds(++i) && tok_vec[i].type == '<') { if(pBounds(i+1) && tok_vec[i+1].type == ';') { ErrorMsg("stream terminated with semi-colon before any data was passed you put (%s)", tok_vec[i+1].token.c_str()); continue; } while(pBounds(++i) && tok_vec[i].type != ';') { if(tok_vec[i].type != STRING && tok_vec[i].type != DIGIT && tok_vec[i].type != '<' && GetBend()->symbols.vars[tok_vec[i].token].name == "") { ErrorMsg("on print instruction requires string/digit/or stream operator you put (%s)", tok_vec[i].token.c_str()); continue; } else if(pBounds(i+1) && tok_vec[i+1].type == '<' && pBounds(i+2) && tok_vec[i+2].type != STRING && tok_vec[i+2].type != DIGIT && GetBend()->symbols.vars[tok_vec[i+2].token].name == "") { ErrorMsg(" on print instruction stream operator requires r-value ( a variable on the right hand side ) of the stream operator you put (%s)" , tok_vec[i+2].token.c_str()); i+=2; continue; } } } else if(qid == TOK_PRINT && pBounds(i) && (tok_vec[i].type != STRING && tok_vec[i].type != DIGIT) && GetBend()->symbols.vars[tok_vec[i].token].name == "") { ErrorMsg("print instruction requires variable/string/digit or stream operator you put (%s)", tok_vec[i].token.c_str()); continue; } else if(qid == TOK_SCAT && pBounds(++i) && (GetBend()->symbols.vars[tok_vec[i].token].name == "")) { ErrorMsg(" on scat stream , requires variable for first operand you put (%s)", tok_vec[i].token.c_str()); continue; } else if(qid == TOK_SCAT && pBounds(++i) && tok_vec[i].type != '<') { ErrorMsg(" on scat stream, requires stream operator for second operand. you put (%s)", tok_vec[i].token.c_str()); continue; } else if(qid == TOK_SCAT && pBounds(i)) { while(pBounds(++i) && tok_vec[i].type != ';') { if(tok_vec[i].type != STRING && tok_vec[i].type != DIGIT && tok_vec[i].type != '<' && GetBend()->symbols.vars[tok_vec[i].token].name == "") { ErrorMsg("on scat stream requires string/digit/or stream operator you put (%s)", tok_vec[i].token.c_str()); continue; } } } } break; } if(pBounds(i+1) && tok_vec[i+1].type == ';') i++; } else if(id != TOK_EXTERN && qid == TOK_PROC || qid == TOK_BEGIN || qid == TOK_END) { ErrorMsg("nested procedures / blocks not allowed I found (%s) ", tok_vec[i].token.c_str()); continue; } } if(tok_vec[i].type != '}') { ErrorMsg(" code block is missing closing brace } "); continue; } } break; default: { } } } break; } } if(err == 0 && ID >= 4) // make sure its a valid program before execution.. //this can be disabled for speed but its not advised return true; return false; } void BackEnd::Convert() { for(size_t z = 0; z < p->insert_vec.size(); z++) { p->StartParse(p->insert_vec[z]); } if(!p->insert_vec.empty()) p->insert_vec.clear(); std::string current_proc = ""; for(size_t i = 0; i < p->tok_vec.size();i++) { switch(p->tok_vec[i].type) { case IDENTIFIER: { int id = IdentToValue(p->tok_vec[i].token); if(id != -1) { switch(id) { case VAR_INTEGER: i++; if(Bounds(i)) { if(Bounds(i+1)) { if(p->tok_vec[i].token.find('[') != -1 && p->tok_vec[i].token.find(']') != -1) { std::string num = p->tok_vec[i].token.substr(p->tok_vec[i].token.find('[')+1, p->tok_vec[i].token.find(']')-2); std::string name = p->tok_vec[i].token.substr(0,p->tok_vec[i].token.find('[')); for(size_t p = 0; p < size_t(atoi(num.c_str())); p++) { std::ostringstream s; s << current_obj + "." + name << "[" << int(p) << "]"; symbols.Set(VAR_INTEGER,"0",s.str()); } } else if(p->tok_vec[i+1].type == '=') { if(Bounds(i+2)) symbols.Set(VAR_INTEGER,p->tok_vec[i+2].token,current_obj + "." + p->tok_vec[i].token); } else { symbols.Set(VAR_INTEGER,"0", current_obj + "." + p->tok_vec[i].token); } } } break; case VAR_STRING: i++; if(Bounds(i)) { if(Bounds(i+1)) { if(p->tok_vec[i].token.find('[') != -1 && p->tok_vec[i].token.find(']') != -1) { std::string num = p->tok_vec[i].token.substr(p->tok_vec[i].token.find('[')+1, p->tok_vec[i].token.find(']')-2); std::string name = p->tok_vec[i].token.substr(0,p->tok_vec[i].token.find('[')); for(size_t p = 0; p < size_t(atoi(num.c_str())); p++) { std::ostringstream s; s << current_obj + "." +name << "[" << int(p) << "]"; symbols.Set(VAR_STRING,"",s.str()); } } else if(p->tok_vec[i+1].type == '=') { if(Bounds(i+2)) symbols.Set(VAR_STRING,p->tok_vec[i+2].token,current_obj + "." + p->tok_vec[i].token); } else { symbols.Set(VAR_STRING,"", current_obj + "." + p->tok_vec[i].token); } } } break; case VAR_FLOAT: i++; if(Bounds(i)) { if(Bounds(i+1)) { if(p->tok_vec[i].token.find('[') != -1 && p->tok_vec[i].token.find(']') != -1) { std::string num = p->tok_vec[i].token.substr(p->tok_vec[i].token.find('[')+1, p->tok_vec[i].token.find(']')-2); std::string name = p->tok_vec[i].token.substr(0,p->tok_vec[i].token.find('[')); for(size_t p = 0; p < size_t(atoi(num.c_str())); p++) { std::ostringstream s; s << current_obj + "." + name << "[" << int(p) << "]"; symbols.Set(VAR_FLOAT,"0.0",s.str()); } } else if(p->tok_vec[i+1].type == '=') { if(Bounds(i+2)) symbols.Set(VAR_FLOAT,p->tok_vec[i+2].token,current_obj + "." + p->tok_vec[i].token); } else { symbols.Set(VAR_FLOAT,"0.0", current_obj + "." + p->tok_vec[i].token); } } } break; case TOK_MAIN: { i++; if(Bounds(i)) { prog_name = p->tok_vec[i].token; current_obj = "master"; obj[p->tok_vec[i].token] = p->tok_vec[i].token; } } break; case TOK_USES: { i += 2; if(Bounds(i)) while(p->tok_vec[i].type != ';' && i < p->tok_vec.size()) { uses.push_back(current_obj + "." + p->tok_vec[i].token); i++; if(Bounds(i) && p->tok_vec[i].type == ',') i++; } } break; case TOK_MAS: i++; if(Bounds(i)) { current_obj = p->tok_vec[i].token; obj[current_obj] = current_obj; } break; case TOK_BEGIN: i ++; current_proc = current_obj + "." + "begin"; if(Bounds(i)) AddIncBlock(current_obj + "." + "begin", i); break; case TOK_END: i ++; current_proc = current_obj + "." + "end"; if(Bounds(i)) AddIncBlock(current_obj + "." + "end", i); break; case TOK_EXTERN: i += 2; if(Bounds(i)) { callb[current_obj + "." + p->tok_vec[i].token].isdef = true; } break; case TOK_PROC: i++; current_proc = current_obj + "." + p->tok_vec[i].token; if(Bounds(i+2)) { AddIncBlock(current_obj + "." + p->tok_vec[i].token, i+1); } break; case TOK_IMPLEMENT: { i+=2; if(Bounds(i)) { callb[current_obj + "." + p->tok_vec[i].token].imp = true; callb[current_obj + "." + p->tok_vec[i].token].name = current_obj + "." + p->tok_vec[i].token; callb[current_obj + "." + p->tok_vec[i].token].other_name = p->tok_vec[i].token; } } break; } } } break; case STRING: break; case DIGIT: break; case CODELABEL: labels[p->tok_vec[i].token].label_name = p->tok_vec[i].token; labels[p->tok_vec[i].token].proc = current_proc; break; } } } void BackEnd::AddIncBlock(std::string block_name, size_t start) { std::vector<Instruct> v; v.push_back ( Instruct(0xFF,block_name, "") ); size_t pos; for(start, pos = 0; p->tok_vec[start].type != '}' && start < p->tok_vec.size(); start++) { int id = IdentToValue(p->tok_vec[start].token); if(id >= TOK_MOV && id <= TOK_PRINT) { Instruct i; i.op_code = id; i.op1 = p->tok_vec[start+1].token; if(Bounds(start+3) && p->tok_vec[start+2].type == ',') i.op2 = p->tok_vec[start+3].token; else if(Bounds(start+3) && p->tok_vec[start+1].type == '<') { std::ostringstream string_s; start++; while(Bounds(start) && p->tok_vec[start].type != ';') { if(p->tok_vec[start].type != '<') string_s << p->tok_vec[start].token << char(0xFF); start++; } i.op1 = string_s.str(); i.op2 = ""; } else if(Bounds(start+3) && p->tok_vec[start+2].type == '<') { std::ostringstream string_s; i.op1 = p->tok_vec[start+1].token; start+=2; while(Bounds(start) && p->tok_vec[start].type != ';') { if(p->tok_vec[start].type != '<') string_s << p->tok_vec[start].token << char(0xFF); start++; } i.op2 = string_s.str(); } else i.op2 = ""; v.push_back(i); pos++; } if(p->tok_vec[start].type == 4) { labels[p->tok_vec[start].token].pos = pos++; } } ins.push_back(v); } void BackEnd::DebugInc() { size_t i; for(i = 0; i < ins.size(); i++) for(size_t z = 0; z < ins[i].size(); z++) { if(ins[i][z].op_code == 0xFF) cout << "Code Block Name: " << ins[i][z].op1 << endl; else cout << "Opcode: " << tok_array[ins[i][z].op_code] << " Operand 1: " << ins[i][z].op1 << ((ins[i][z].op2.length()==0) ? "" : " Operand 2: ") << ins[i][z].op2 << endl; } for(i = 0; i < uses.size(); i++) cout << "Uses clause: " << uses[i] << endl; std::map<std::string,Code_Label>::iterator l = labels.begin(); for(l; l != labels.end(); l++) cout << "Code Label: " << l->second.label_name << " In Procedure: " << l->second.proc << " At Code Position: " << int(l->second.pos) << endl; } void BackEnd::CallProcedure(std::string proc_name) { size_t p = Find(proc_name); if(p != 0) { code.push_back(std::make_pair(cur_pos,i+1)); cur_pos = p, i = 0; return; } else std::cout << "**** Procedure " << proc_name << " Not Found!\n"; } void BackEnd::Execute(bool anaylize) { if(anaylize && !p->LexAnayalize()) { cout << "**** Errors in script cannot continue...\n"; #ifdef _WIN32 system("PAUSE"); #endif return; } if(p->err != 0) { cout << "**** Errors in script cannot continue...\n"; #ifdef _WIN32 system("PAUSE"); #endif return; } if(!p->tok_vec.empty()) p->tok_vec.clear(); if(p->file) { p->file->close(); } size_t begin_pos = Find("master.begin"), end_pos = Find("master.end"); size_t u, b , e; cur_pos = begin_pos; i = 0; if(end_pos != 0) code.push_back( std::pair<size_t,size_t>(end_pos,0) ); if(uses.size()!=0) { for(u = 0; u < uses.size(); u++) { std::string str = uses[u].substr(uses[u].find(".")+1,uses[u].length()); e = Find(str + ".end"); if(e != 0) code.push_back(std::make_pair(e,0)); } code.push_back(std::make_pair(begin_pos,0)); for(u = 0; u < uses.size(); u++) { std::string str = uses[u].substr(uses[u].find(".")+1,uses[u].length()); b = Find(str + ".begin"); if(u != uses.size()-1) code.push_back(std::make_pair(b,0)); } cur_pos = b; } else cur_pos = begin_pos; while(1) { while(i < ins[cur_pos].size()) { PROC_RETURN rt; if((rt = ProcInc(cur_pos, i)) == PROC_CONT) ins[cur_pos][i].op1 = prev_op1, ins[cur_pos][i].op2 = prev_op2, i++; else if(rt == PROC_JMP){ ins[cur_pos][i].op1 = prev_op1, ins[cur_pos][i].op2 = prev_op2; size_t pos = Find(ins[cur_pos][i].op1); if(pos != 0) { if(ins[pos][0].op_code == 0xFF) { code.push_back(std::pair<size_t,size_t>(cur_pos,i+1)); code.push_back(std::pair<size_t,size_t>(pos,0)); break; } } else { if(callb[ins[cur_pos][i].op1].name == "" || callb[ins[cur_pos][i].op1].isdef == false) cout << "**** invalid procedure call-> " << ins[cur_pos][i].op1 << endl; else if(callb[ins[cur_pos][i].op1].f(symbols) != 0) std::cerr << "Error external callback didnt return 0\n"; i++; } } else if(rt == PROC_RET) { ins[cur_pos][i].op1 = prev_op1, ins[cur_pos][i].op2 = prev_op2; break; } } if(code.empty()) break; cur_pos = code.back().first; i = code.back().second; code.pop_back(); } } PROC_RETURN BackEnd::ProcInc(size_t block, size_t &inc) { prev_op1 = ins[block][inc].op1; prev_op2 = ins[block][inc].op2; if(ins[block][inc].op1.find('[') != -1 && ins[block][inc].op1.find(']') != -1) { std::ostringstream curs; std::string num = ins[block][inc].op1; std::vector<std::string> vec; while(num.find('[') != -1) { num = num.substr(num.find('[')+1,num.length()); num = num.substr(0,num.rfind(']')); vec.push_back(num); } std::string prev_index = ""; for(int array_pos = int(vec.size())-1; array_pos >= 0; array_pos--) { std::string the_name = ""; if(vec[array_pos].find('[') != -1) { if(IsVar(vec[array_pos])) { prev_index = symbols.vars[vec[array_pos]].val; } else { the_name = vec[array_pos].substr(0,vec[array_pos].find('[')); prev_index = symbols.vars[the_name + "[" + prev_index + "]"].val; } } else prev_index = (IsVar(vec[array_pos]) == true ? symbols.vars[vec[array_pos]].val : vec[array_pos]); } std::string name = ins[block][inc].op1.substr(0,ins[block][inc].op1.find('[')); curs << name << "[" << prev_index << "]"; ins[block][inc].op1 = curs.str(); } if(ins[block][inc].op2.find('[') != -1 && ins[block][inc].op2.find(']') != -1) { std::ostringstream curs; std::string num = ins[block][inc].op2; std::vector<std::string> vec; while(num.find('[') != -1) { num = num.substr(num.find('[')+1,num.length()); num = num.substr(0,num.rfind(']')); vec.push_back(num); } std::string prev_index = ""; for(int array_pos = int(vec.size())-1; array_pos >= 0; array_pos--) { std::string the_name; if(vec[array_pos].find('[') != -1) { if(IsVar(vec[array_pos])) { prev_index = symbols.vars[vec[array_pos]].val; } else { the_name = vec[array_pos].substr(0,vec[array_pos].find('[')); prev_index = symbols.vars[the_name + "[" + prev_index + "]"].val; } } else prev_index = (IsVar(vec[array_pos]) == true ? symbols.vars[vec[array_pos]].val : vec[array_pos]); } std::string name = ins[block][inc].op2.substr(0,ins[block][inc].op2.find('[')); curs << name << "[" << prev_index << "]"; ins[block][inc].op2 = curs.str(); } switch(ins[block][inc].op_code) { case TOK_MOV: if(IsVar(ins[block][inc].op1)) { if(IsVar(ins[block][inc].op2)) symbols.vars[ins[block][inc].op1].val = symbols.vars[ins[block][inc].op2].val; else symbols.vars[ins[block][inc].op1].val = ins[block][inc].op2; } else std::cout << "**** invalid variable name on mov...[" << ins[block][inc].op1 << "]\n"; break; case TOK_ADD: case TOK_SUB: case TOK_MUL: case TOK_DIV: case TOK_OR: case TOK_XOR: case TOK_AND: { if(IsVar(ins[block][inc].op1)) { if(IsVar(ins[block][inc].op2)) { std::ostringstream s; switch(ins[block][inc].op_code) { case TOK_ADD: s << (symbols.vars[ins[block][inc].op1].type == VAR_INTEGER ? (std::atoi(symbols.vars[ins[block][inc].op1].val.c_str())+std::atoi(symbols.vars[ins[block][inc].op2].val.c_str())) : (atof(symbols.vars[ins[block][inc].op1].val.c_str())+atof(symbols.vars[ins[block][inc].op2].val.c_str()))); break; case TOK_SUB: s << (symbols.vars[ins[block][inc].op1].type == VAR_INTEGER ? (std::atoi(symbols.vars[ins[block][inc].op1].val.c_str())-std::atoi(symbols.vars[ins[block][inc].op2].val.c_str())) : (atof(symbols.vars[ins[block][inc].op1].val.c_str())-atof(symbols.vars[ins[block][inc].op2].val.c_str()))); break; case TOK_MUL: s << (symbols.vars[ins[block][inc].op1].type == VAR_INTEGER ? (std::atoi(symbols.vars[ins[block][inc].op1].val.c_str())*std::atoi(symbols.vars[ins[block][inc].op2].val.c_str())) : (atof(symbols.vars[ins[block][inc].op1].val.c_str())*atof(symbols.vars[ins[block][inc].op2].val.c_str()))); break; case TOK_DIV: if(std::atoi(symbols.vars[ins[block][inc].op1].val.c_str()) == 0 || std::atoi(symbols.vars[ins[block][inc].op2].val.c_str()) == 0) std::cout << "***** Error cannot divide by zero...\n"; else s << (symbols.vars[ins[block][inc].op1].type == VAR_INTEGER ? (std::atoi(symbols.vars[ins[block][inc].op1].val.c_str())/std::atoi(symbols.vars[ins[block][inc].op2].val.c_str())) : (atof(symbols.vars[ins[block][inc].op1].val.c_str())/atof(symbols.vars[ins[block][inc].op2].val.c_str()))); break; case TOK_OR: s << (std::atoi(symbols.vars[ins[block][inc].op1].val.c_str())|std::atoi(symbols.vars[ins[block][inc].op2].val.c_str())); break; case TOK_XOR: s << (std::atoi(symbols.vars[ins[block][inc].op1].val.c_str())^std::atoi(symbols.vars[ins[block][inc].op2].val.c_str())); break; case TOK_AND: s << (std::atoi(symbols.vars[ins[block][inc].op1].val.c_str())&std::atoi(symbols.vars[ins[block][inc].op2].val.c_str())); break; } symbols.vars[ins[block][inc].op1].val = s.str(); } else { std::ostringstream s; switch(ins[block][inc].op_code) { case TOK_ADD: s << (symbols.vars[ins[block][inc].op1].type == VAR_INTEGER ? (std::atoi(symbols.vars[ins[block][inc].op1].val.c_str())+std::atoi(ins[block][inc].op2.c_str())) : (atof(symbols.vars[ins[block][inc].op1].val.c_str())+atof(ins[block][inc].op2.c_str()))); break; case TOK_SUB: s << (symbols.vars[ins[block][inc].op1].type == VAR_INTEGER ? (std::atoi(symbols.vars[ins[block][inc].op1].val.c_str())-std::atoi(ins[block][inc].op2.c_str())) : (atof(symbols.vars[ins[block][inc].op1].val.c_str())-atof(ins[block][inc].op2.c_str()))); break; case TOK_MUL: s << (symbols.vars[ins[block][inc].op1].type == VAR_INTEGER ? (std::atoi(symbols.vars[ins[block][inc].op1].val.c_str())*std::atoi(ins[block][inc].op2.c_str())) : (std::atof(symbols.vars[ins[block][inc].op1].val.c_str())*std::atof(ins[block][inc].op2.c_str()))); break; case TOK_DIV: if(std::atoi(symbols.vars[ins[block][inc].op1].val.c_str()) == 0 || std::atoi(ins[block][inc].op2.c_str()) == 0) cout << "***** Error cannot divide by zero...\n"; else s << (symbols.vars[ins[block][inc].op1].type == VAR_INTEGER ? (std::atoi(symbols.vars[ins[block][inc].op1].val.c_str())/std::atoi(ins[block][inc].op2.c_str())) : (std::atof(symbols.vars[ins[block][inc].op1].val.c_str())/std::atof(ins[block][inc].op2.c_str()))); break; case TOK_OR: s << (std::atoi(symbols.vars[ins[block][inc].op1].val.c_str())|std::atoi(ins[block][inc].op2.c_str())); break; case TOK_XOR: s << (std::atoi(symbols.vars[ins[block][inc].op1].val.c_str())^std::atoi(ins[block][inc].op2.c_str())); break; case TOK_AND: s << (std::atoi(symbols.vars[ins[block][inc].op1].val.c_str())&std::atoi(ins[block][inc].op2.c_str())); break; } symbols.vars[ins[block][inc].op1].val = s.str(); } } else std::cout << "**** invalid variable name ...[" << ins[block][inc].op1 << "]\n"; } break; case TOK_NOT: { if(IsVar(ins[block][inc].op1)) { std::ostringstream s; s << (!std::atoi(symbols.vars[ins[block][inc].op1].val.c_str())); symbols.vars[ins[block][inc].op1].val = s.str(); } else std::cout << "**** invalid variable name ...[" << ins[block][inc].op1 << "]\n"; } break; case TOK_INC: case TOK_DEC: { if(IsVar(ins[block][inc].op1)) { std::ostringstream s; if(ins[block][inc].op_code == TOK_INC) s << (std::atoi(symbols.vars[ins[block][inc].op1].val.c_str())+1); else s << (std::atoi(symbols.vars[ins[block][inc].op1].val.c_str())-1); symbols.vars[ins[block][inc].op1].val = s.str(); } else std::cout << "**** invalid variable name ...[" << ins[block][inc].op1 << "]\n"; } break; case TOK_PUSH: { static symb s; if(IsVar(ins[block][inc].op1)) { s.name = ins[block][inc].op1; s.val = symbols.vars[s.name].val; s.type = symbols.vars[s.name].type; symbols += s; } else { s.name = "constant"; s.type = IDENTIFIER; s.val = ins[block][inc].op1; symbols += s; } } break; case TOK_POP: { if(IsVar(ins[block][inc].op1)) { symb s = --symbols; symbols[ins[block][inc].op1].val = s.val; } else std::cout << "**** invalid variable name on pop...[" << ins[block][inc].op1 << "]\n"; } break; case TOK_PRINT: if(ins[block][inc].op1.find(char(0xFF)) == -1 && symbols.vars[ins[block][inc].op1].name != "") std::cout << symbols.vars[ins[block][inc].op1].val; else if(ins[block][inc].op1.find(char(0xFF)) == -1) { std::cout<< ins[block][inc].op1; } else { // stream data std::ostringstream string_s; std::string left, right,temp = ins[block][inc].op1; while(temp.length() > 0 && temp.find(char(0xFF)) != -1) { left = temp.substr(0,temp.find(char(0xFF))); temp = temp.substr(temp.find(char(0xFF))+1,temp.length()); if(IsVar(left)) string_s << symbols.vars[left].val; else string_s << left; } cout << string_s.str(); } break; case TOK_SCAT: { std::ostringstream string_s; if(ins[block][inc].op2.find(char(0xFF)) == -1 && symbols.vars[ins[block][inc].op1].name != "") { std::cout << "**** error no data to stream to variable...\n"; } else { // stream data std::string left, right,temp = ins[block][inc].op2; while(temp.length() > 0 && temp.find(char(0xFF)) != -1) { left = temp.substr(0,temp.find(char(0xFF))); temp = temp.substr(temp.find(char(0xFF))+1,temp.length()); if(IsVar(left)) string_s << symbols.vars[left].val; else string_s << left; } symbols.vars[ins[block][inc].op1].val = string_s.str(); } } break; case TOK_CALL: return PROC_JMP; break; case TOK_JMP: if(ins[block][0].op1 == labels[ins[block][inc].op1].proc) inc = labels[ins[block][inc].op1].pos; else std::cout << "***** on jmp instruction wrong procedure or no label found.\n"; break; case TOK_JNE: if(ins[block][0].op1 == labels[ins[block][inc].op1].proc) { if(reg[0] == false) inc = labels[ins[block][inc].op1].pos; } else std::cout << "***** on jmp instruction wrong procedure or no label found.\n"; break; case TOK_JE: if(ins[block][0].op1 == labels[ins[block][inc].op1].proc) { if(reg[0] == true) inc = labels[ins[block][inc].op1].pos; } else std::cout << "***** on jmp instruction wrong procedure or no label found.\n"; break; case TOK_JL: if(ins[block][0].op1 == labels[ins[block][inc].op1].proc) { if(reg[1] != true) inc = labels[ins[block][inc].op1].pos; } else std::cout << "***** on jmp instruction wrong procedure or no label found.\n"; break; case TOK_JG: if(ins[block][0].op1 == labels[ins[block][inc].op1].proc) { if(reg[1] == true) inc = labels[ins[block][inc].op1].pos; } else std::cout << "***** on jmp instruction wrong procedure or no label found.\n"; case TOK_JLE: if(ins[block][0].op1 == labels[ins[block][inc].op1].proc) { if(reg[3] == true) inc = labels[ins[block][inc].op1].pos; } else std::cout << "***** on jmp instruction wrong procedure or no label found.\n"; break; case TOK_JGE: if(ins[block][0].op1 == labels[ins[block][inc].op1].proc) { if(reg[2] == true) inc = labels[ins[block][inc].op1].pos; } else std::cout << "***** on jmp instruction wrong procedure or no label found.\n"; break; case TOK_CMP: { if(IsVar(ins[block][inc].op1)) { if(IsVar(ins[block][inc].op2)) { reg[0] = (symbols.vars[ins[block][inc].op1].val == symbols.vars[ins[block][inc].op2].val); reg[1] = (std::atof(symbols.vars[ins[block][inc].op1].val.c_str()) > std::atof(symbols.vars[ins[block][inc].op2].val.c_str())); reg[2] = (std::atof(symbols.vars[ins[block][inc].op1].val.c_str()) >= std::atof(symbols.vars[ins[block][inc].op2].val.c_str())); reg[3] = (std::atof(symbols.vars[ins[block][inc].op1].val.c_str()) <= std::atof(symbols.vars[ins[block][inc].op2].val.c_str())); } else { reg[0] = (symbols.vars[ins[block][inc].op1].val == ins[block][inc].op2); reg[1] = (std::atof(symbols.vars[ins[block][inc].op1].val.c_str()) > std::atof(ins[block][inc].op2.c_str())); reg[2] = (std::atof(symbols.vars[ins[block][inc].op1].val.c_str()) >= std::atof(ins[block][inc].op2.c_str())); reg[3] = (std::atof(symbols.vars[ins[block][inc].op1].val.c_str()) <= std::atof(ins[block][inc].op2.c_str())); } } } break; case TOK_RET: { return PROC_RET; } break; case TOK_EXIT: { std::exit(0); } break; } return PROC_CONT; } size_t BackEnd::Find(std::string what) { for(size_t i = 0; i < ins.size(); i++) if(strcmp(ins[i][0].op1.c_str(),what.c_str()) == 0) return i; return 0; } void BackEnd::AddExternal(std::string name, int (*f)(Symbol_Table &t)) { callb[name].f = f; callb[name].name = name; } bool BackEnd::IsVar(std::string &name) { if(symbols.vars[name].name == "") return false; return true; } std::string BackEnd::byteToString(unsigned char type) { std::string s; switch(type) { case 1: return "Identifier"; case 2: return "Digit"; case 3: return "String"; case 4: return "Code Label"; } s += type; return s; } std::string BackEnd::tokenTypeToString(TOK_TYPE t) { std::string s; switch(t) { case 0: return "Constant"; case VAR_INTEGER: return "Integer"; case VAR_STRING: return "String"; case VAR_FLOAT: return "Float"; } s += int(t); return s; } void BackEnd::DebugHTML(std::string src, bool sout) { std::fstream file; file.open(src.c_str(), std::ios::out); if(file.is_open()) { size_t i = 0, z = 0; file << "<HTML><TITLE>Masc Debug Output File for " << prog_name << "</TITLE><BODY>"; file << "<font face=\"FixedSys\" size=\"4\" color=\"black\"><TABLE border=\"4\" bgcolor=\"#FFFFFF\" BORDERCOLOR=\"#000000\" CELLPADDING=\"3\" CELLSPACING=\"0\"><br>"; file << "<TR><font color=\"#BD0000\"> Tokenized Code </font> </TR><br><TH> File/Line </TH><TH> Byte Code </TH><TH> Symbols </TH>"; for(i = 0; i < p->tok_vec.size(); i++) file << "<TR><TH><font color=\"blue\">" << p->tok_vec[i].source_file << ":" << p->tok_vec[i].line_num << "</TH><TH>" << byteToString(p->tok_vec[i].type) << "</font></TH><TH><font color=\"A0A0A0\">" << p->tok_vec[i].token << "</font></TH>"; file << "</TABLE><TABLE border =\"4\" bgcolor=\"#FFFFFF\" BORDERCOLOR=\"#000000\" CELLPADDING=\"3\" CELLSPACING=\"0\"> <br> <TR><font color=\"#BD0000\"> Intermediate Code</font></TR><br><TH> OpCode </TH><TH> Operand 1 </TH> <TH> Operand 2 </TH>"; for(i = 0; i < ins.size(); i++) for(z = 0; z < ins[i].size(); z++) file << "<TR><TH><font color=\"orange\"> " << (ins[i][z].op_code == 0xFF ? "Code Block" : (ins[i][z].op_code <= TOK_PRINT ? tok_array[int(ins[i][z].op_code)] : "Unknown")) << " (" << int(ins[i][z].op_code) << ")</font></TH> <TH><font color=\"purple\">" << ins[i][z].op1 << "</font></TH>" << "<TH><font color=\"purple\">" << ins[i][z].op2 << "</font></TH>"; file << "</TABLE><TABLE border =\"4\" bgcolor=\"#FFFFFF\" BORDERCOLOR=\"#000000\" CELLPADDING=\"3\" CELLSPACING=\"0\"> <br> <TR><font color=\"#BD0000\"> Symbol Table </font></TR><br><TH> String Name </TH><TH> Value </TH> <TH> Type </TH>"; std::map<std::string,symb>::const_iterator x; for(x = symbols.vars.begin(); x != symbols.vars.end(); x++) file << "<TR><TH><font color=\"teal\">" << x->first << "</font></TH> <TH><font color=\"green\">" << x->second.val << "</font></TH>" << "<TH><font color=\"red\">" << tokenTypeToString(TOK_TYPE(x->second.type)) << "</font></TH>"; std::map<std::string, masc::External_Callback>::iterator y; file << "</TABLE><TABLE border =\"4\" bgcolor=\"#FFFFFF\" BORDERCOLOR=\"#000000\" CELLPADDING=\"3\" CELLSPACING=\"0\"> <br> <TR><font color=\"#BD0000\"> External Callbacks </font></TR><br><TH> Procedure Name </TH> <TH> Address </TH>"; for(y = callb.begin(); y != callb.end(); y++) file << "<TR><TH><font color=\"purple\">" << y->first << "</font></TH> <TH><font color=\"green\">" << y->second.f << "</font></TH>"; file << "<font></TABLE></BODY></HTML>"; file.close(); } // dump debug output to stdout if(sout == true) { std::fstream ifile; cout << "Content-type: text/html\n\n"; ifile.open(src.c_str(),std::ios::in); while(ifile.is_open() && !ifile.eof()) { std::string s; std::getline(ifile,s); cout << s << "\n"; } ifile.close(); } } inline int IdentToValue(std::string s) { for(int i = 0; tok_array[i] != 0; i++) if(s == tok_array[i]) return i; return -1; } BackEnd *BackEnd::back; }