1 ////////////////////////////////////////////////////////
5 // Implementaion of a basic basic :) interpreter
8 // Maarten Bosma, 09.01.2004
9 // maarten.paul@bosma.de
11 ////////////////////////////////////////////////////////////////////
13 #include "package.hpp"
21 void Replace (string
* Where
, string Old
, string New
, int start
= 0, int end
= -1, int instring
= 1);
22 int FindCount (string What
, string Where
, int start
= 0, int end
= -1);
23 int Find (string Where
, string What
, int start
= 0, int end
= -1, int instring
= 1);
26 // Loads script from file, checks if it's synaxially correct
27 // and converts it into a easy to interprete one.
28 int RPS_Load (SCRIPT
** script
, const char* path
)
32 /* We have to do it that way (doublepointer) because MinGw
33 calls "delete" at the end of function otherwise. */
34 (*script
) = new SCRIPT
;
36 // Load file to string
37 ifstream
file(path
, ios_base::in
);
41 getline(file
, source
, '\0');
43 // make sure last char is a new line
46 // Are all subs and strings closed ?
47 // FIXME: Just a quick hack sould be both checked line by line
48 if(FindCount(source
, "\"")%2) // if count is uneven not all strings are closed
51 if(FindCount(source
, "Sub ") != FindCount(source
, "End Sub\n"))
57 int start
= Find(source
, "'");
60 int end
= Find(source
, "\n", start
);
61 source
.erase(start
, end
-start
); // needs size not line
64 // Converte the file into some thing easier to interprete
65 Replace(&source
, "(", " ");
66 Replace(&source
, ")", " ");
67 Replace(&source
, ";", " ");
68 Replace(&source
, ",", " ");
69 Replace(&source
, "\"", " \" ");
70 Replace(&source
, "\t", " ");
72 Replace(&source
, " ", " ");
73 Replace(&source
, "\n ", "\n");
74 Replace(&source
, " \n", "\n");
75 Replace(&source
, "\n\n", "\n");
80 // copy string into struct (line by line)
82 for (i
=0; i
< source
.size(); i
++)
84 // Make everything non capital letters
85 if (source
[i
] >= 65 && source
[i
] <= 90) // ASCII-Code (A-Z 65-90)
87 source
[i
] += 32; // ASCII-Code (a-z 97-122)
90 else if (source
[i
] == '\"')
92 while(source
[++i
]!='\"');
95 else if (source
[i
] == '\n')
97 (*script
)->code
.push_back(source
.substr(line
, i
-line
));
102 // create a sub table (with name, beginnig and end of function)
103 for (i
=0; i
< (*script
)->code
.size(); i
++) // code.size() is the cout of lines
107 if((*script
)->code
[i
].substr(0,4) != "sub ")
108 return ERR_SYNATX
; // script has to start with sub
110 sub
.name
= (*script
)->code
[i
].substr(4,((*script
)->code
[i
].size()-4));
113 while ((*script
)->code
[i
] != "end sub")
116 //if script does not end with "end sub" we got a problem
117 if (i
>(*script
)->code
.size())
122 (*script
)->subs
.push_back(sub
);
129 // Executes a subroutine of the script
130 int RPS_Execute (SCRIPT
* script
, const char* function
)
134 int a
, b
, c
, nr
= NOTFOUND
, argc
= 0;
136 // find the right fuction
137 for(a
=0; (UINT
)a
<script
->subs
.size(); a
++)
138 if(script
->subs
[a
].name
== function
)
141 // if there isn't a fuction with this name we can't do anything
146 for (a
=script
->subs
[nr
].start
; a
<script
->subs
[nr
].end
; a
++)
148 // create a temporarry buffer
149 buffer
= new char[script
->code
[a
].size()];
150 strcpy(buffer
, script
->code
[a
].c_str());
152 // make the fist argument the function's name
153 argv
[0] = &buffer
[0];
155 int buffer_size
= (int)strlen(buffer
);
156 for (b
=0; b
<buffer_size
+1; b
++)
158 // ignore chars in strings
161 argv
[argc
] = &buffer
[b
+1];
163 while(buffer
[++b
]!='\"');
168 // create a new argument
169 else if(buffer
[b
]==' ')
172 argv
[argc
] = &buffer
[b
+1];
175 // we don't want buffer overflows
182 else if(buffer
[b
]=='\0')
187 Log("* excute command: ");
188 for(c
=0; c
<argc
+1; c
++)
194 for(c
=0; c
<FUNC_COUNT
; c
++)
195 if(!strcmp(argv
[0], FuncTable
[c
].name
))
196 error
= FuncTable
[c
].function(argc
, &argv
[0]);
204 // start again with next line
212 // get a Constant or a variavle
213 int RPS_getVar (const char* name
)
219 void RPS_Clear (SCRIPT
* script
)
225 /* Helper Functions */
227 // How often do we find a string inside another one
228 int FindCount (string where
, string what
, int start
, int end
)
230 int counter
= 0, pos
;
234 pos
= (int)where
.find (what
, start
);
235 //could could not be found or is outside of search area
236 if (pos
== (int)string::npos
|| (end
!=-1 && pos
>end
))
245 // Find (with only or not in Strings option)
246 int Find (string where
, string what
, int start
, int end
, int instring
)
248 int pos
= (int)where
.find (what
, start
);
250 //could could not be found or is outside of search area
251 if (pos
== (int)string::npos
|| (end
!=-1 && pos
>end
))
254 // if the count of this quotes is eaven we are in string
255 int isInString
= FindCount(where
, "\"", start
, pos
)%2;
257 // if so we go on searching
258 if(isInString
== instring
)
259 return Find (where
, what
, pos
+1, end
, instring
);
265 // Replace (using Find)
266 void Replace (string
* String
, string Old
, string New
, int start
, int end
, int instring
)
272 pos
= Find(String
->c_str(), Old
, pos
, end
, instring
);
276 String
->replace (pos
, Old
.length(), New
);