//////////////////////////////////////////////////////// // // script.cpp // // Implementaion of a basic basic :) interpreter // // // Maarten Bosma, 09.01.2004 // maarten.paul@bosma.de // //////////////////////////////////////////////////////////////////// #include "package.hpp" #include "script.h" #include "log.h" #include using namespace std; // just a few Helpers void Replace (string* Where, string Old, string New, int start = 0, int end = -1, int instring = 1); int FindCount (string What, string Where, int start = 0, int end = -1); int Find (string Where, string What, int start = 0, int end = -1, int instring = 1); // Loads script from file, checks if it's synaxially correct // and converts it into a easy to interprete one. int RPS_Load (SCRIPT** script, const char* path) { string source; /* We have to do it that way (doublepointer) because MinGw calls "delete" at the end of function otherwise. */ (*script) = new SCRIPT; // Load file to string ifstream file(path, ios_base::in); if (!file.is_open()) return ERR_FILE; getline(file, source, '\0'); // make sure last char is a new line source += "\n"; // Are all subs and strings closed ? // FIXME: Just a quick hack sould be both checked line by line if(FindCount(source, "\"")%2) // if count is uneven not all strings are closed return ERR_SYNATX; if(FindCount(source, "Sub ") != FindCount(source, "End Sub\n")) return ERR_SYNATX; // Delete comments while (true) { int start = Find(source, "'"); if(start == NOTFOUND) break; int end = Find(source, "\n", start); source.erase(start, end-start); // needs size not line } // Converte the file into some thing easier to interprete Replace(&source, "(", " "); Replace(&source, ")", " "); Replace(&source, ";", " "); Replace(&source, ",", " "); Replace(&source, "\"", " \" "); Replace(&source, "\t", " "); Replace(&source, " ", " "); Replace(&source, "\n ", "\n"); Replace(&source, " \n", "\n"); Replace(&source, "\n\n", "\n"); if(source[0]=='\n') source.erase(0,1); // copy string into struct (line by line) UINT i, line=0; for (i=0; i < source.size(); i++) { // Make everything non capital letters if (source[i] >= 65 && source[i] <= 90) // ASCII-Code (A-Z 65-90) { source[i] += 32; // ASCII-Code (a-z 97-122) } else if (source[i] == '\"') { while(source[++i]!='\"'); } else if (source[i] == '\n') { (*script)->code.push_back(source.substr(line, i-line)); line = i+1; } } // create a sub table (with name, beginnig and end of function) for (i=0; i < (*script)->code.size(); i++) // code.size() is the cout of lines { SUB sub; if((*script)->code[i].substr(0,4) != "sub ") return ERR_SYNATX; // script has to start with sub sub.name = (*script)->code[i].substr(4,((*script)->code[i].size()-4)); sub.start = i+1; while ((*script)->code[i] != "end sub") { i++; //if script does not end with "end sub" we got a problem if (i>(*script)->code.size()) return ERR_SYNATX; } sub.end = i; (*script)->subs.push_back(sub); } return ERR_OK; } // Executes a subroutine of the script int RPS_Execute (SCRIPT* script, const char* function) { char *argv[100]; char *buffer; int a, b, c, nr = NOTFOUND, argc = 0; // find the right fuction for(a=0; (UINT)asubs.size(); a++) if(script->subs[a].name == function) nr = a; // if there isn't a fuction with this name we can't do anything if(nr == NOTFOUND) return ERR_OK; // call the function for (a=script->subs[nr].start; asubs[nr].end; a++) { // create a temporarry buffer buffer = new char[script->code[a].size()]; strcpy(buffer, script->code[a].c_str()); // make the fist argument the function's name argv[0] = &buffer[0]; int buffer_size = (int)strlen(buffer); for (b=0; bend)) break; start = pos+1; counter++; } return counter; } // Find (with only or not in Strings option) int Find (string where, string what, int start, int end, int instring) { int pos = (int)where.find (what, start); //could could not be found or is outside of search area if (pos == (int)string::npos || (end!=-1 && pos>end)) return -1; // if the count of this quotes is eaven we are in string int isInString = FindCount(where, "\"", start, pos)%2; // if so we go on searching if(isInString == instring) return Find (where, what, pos+1, end, instring); return pos; } // Replace (using Find) void Replace (string* String, string Old, string New, int start, int end, int instring) { int pos = start; while(true) { pos = Find(String->c_str(), Old, pos, end, instring); if (pos == -1) break; String->replace (pos, Old.length(), New); } }