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