Force Nagle algorithm off for loopback
[reactos.git] / rosapps / packmgr / lib / script.cpp
1 ////////////////////////////////////////////////////////
2 //
3 // script.cpp
4 //
5 // Implementaion of a basic basic :) interpreter
6 //
7 //
8 // Maarten Bosma, 09.01.2004
9 // maarten.paul@bosma.de
10 //
11 ////////////////////////////////////////////////////////////////////
12
13 #include "package.hpp"
14 #include "script.h"
15 #include "log.h"
16 #include <fstream>
17
18 using namespace std;
19
20 // just a few Helpers
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);
24
25
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)
29 {
30 string source;
31
32 /* We have to do it that way (doublepointer) because MinGw
33 calls "delete" at the end of function otherwise. */
34 (*script) = new SCRIPT;
35
36 // Load file to string
37 ifstream file(path, ios_base::in);
38 if (!file.is_open())
39 return ERR_FILE;
40
41 getline(file, source, '\0');
42
43 // make sure last char is a new line
44 source += "\n";
45
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
49 return ERR_SYNATX;
50
51 if(FindCount(source, "Sub ") != FindCount(source, "End Sub\n"))
52 return ERR_SYNATX;
53
54 // Delete comments
55 while (true)
56 {
57 int start = Find(source, "'");
58 if(start == NOTFOUND)
59 break;
60 int end = Find(source, "\n", start);
61 source.erase(start, end-start); // needs size not line
62 }
63
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", " ");
71
72 Replace(&source, " ", " ");
73 Replace(&source, "\n ", "\n");
74 Replace(&source, " \n", "\n");
75 Replace(&source, "\n\n", "\n");
76
77 if(source[0]=='\n')
78 source.erase(0,1);
79
80 // copy string into struct (line by line)
81 UINT i, line=0;
82 for (i=0; i < source.size(); i++)
83 {
84 // Make everything non capital letters
85 if (source[i] >= 65 && source[i] <= 90) // ASCII-Code (A-Z 65-90)
86 {
87 source[i] += 32; // ASCII-Code (a-z 97-122)
88 }
89
90 else if (source[i] == '\"')
91 {
92 while(source[++i]!='\"');
93 }
94
95 else if (source[i] == '\n')
96 {
97 (*script)->code.push_back(source.substr(line, i-line));
98 line = i+1;
99 }
100 }
101
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
104 {
105 SUB sub;
106
107 if((*script)->code[i].substr(0,4) != "sub ")
108 return ERR_SYNATX; // script has to start with sub
109
110 sub.name = (*script)->code[i].substr(4,((*script)->code[i].size()-4));
111 sub.start = i+1;
112
113 while ((*script)->code[i] != "end sub")
114 {
115 i++;
116 //if script does not end with "end sub" we got a problem
117 if (i>(*script)->code.size())
118 return ERR_SYNATX;
119 }
120
121 sub.end = i;
122 (*script)->subs.push_back(sub);
123 }
124
125 return ERR_OK;
126 }
127
128
129 // Executes a subroutine of the script
130 int RPS_Execute (SCRIPT* script, const char* function)
131 {
132 char *argv[100];
133 char *buffer;
134 int a, b, c, nr = NOTFOUND, argc = 0;
135
136 // find the right fuction
137 for(a=0; (UINT)a<script->subs.size(); a++)
138 if(script->subs[a].name == function)
139 nr = a;
140
141 // if there isn't a fuction with this name we can't do anything
142 if(nr == NOTFOUND)
143 return ERR_OK;
144
145 // call the function
146 for (a=script->subs[nr].start; a<script->subs[nr].end; a++)
147 {
148 // create a temporarry buffer
149 buffer = new char[script->code[a].size()];
150 strcpy(buffer, script->code[a].c_str());
151
152 // make the fist argument the function's name
153 argv[0] = &buffer[0];
154
155 int buffer_size = (int)strlen(buffer);
156 for (b=0; b<buffer_size+1; b++)
157 {
158 // ignore chars in strings
159 if(buffer[b]=='\"')
160 {
161 argv[argc] = &buffer[b+1];
162
163 while(buffer[++b]!='\"');
164
165 buffer[b] = '\0';
166 }
167
168 // create a new argument
169 else if(buffer[b]==' ')
170 {
171 argc++;
172 argv[argc] = &buffer[b+1];
173 buffer[b] = '\0';
174
175 // we don't want buffer overflows
176 if(argc == 99)
177 return ERR_GENERIC;
178
179 }
180
181 // call the function
182 else if(buffer[b]=='\0')
183 {
184 int error = 0;
185
186 // log the name
187 Log("* excute command: ");
188 for(c=0; c<argc+1; c++)
189 {
190 LogAdd(argv[c]);
191 LogAdd(" ");
192 }
193
194 for(c=0; c<FUNC_COUNT; c++)
195 if(!strcmp(argv[0], FuncTable[c].name))
196 error = FuncTable[c].function(argc, &argv[0]);
197
198 if(error)
199 return error;
200 }
201
202 }
203
204 // start again with next line
205 delete[] buffer;
206 argc = 0;
207 }
208
209 return ERR_OK;
210 }
211
212 // get a Constant or a variavle
213 int RPS_getVar (const char* name)
214 {
215 return ERR_OK;
216 }
217
218 // Clears up Memory
219 void RPS_Clear (SCRIPT* script)
220 {
221 if(script)
222 delete script;
223 }
224
225 /* Helper Functions */
226
227 // How often do we find a string inside another one
228 int FindCount (string where, string what, int start, int end)
229 {
230 int counter = 0, pos;
231
232 while(true)
233 {
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))
237 break;
238 start = pos+1;
239 counter++;
240 }
241
242 return counter;
243 }
244
245 // Find (with only or not in Strings option)
246 int Find (string where, string what, int start, int end, int instring)
247 {
248 int pos = (int)where.find (what, start);
249
250 //could could not be found or is outside of search area
251 if (pos == (int)string::npos || (end!=-1 && pos>end))
252 return -1;
253
254 // if the count of this quotes is eaven we are in string
255 int isInString = FindCount(where, "\"", start, pos)%2;
256
257 // if so we go on searching
258 if(isInString == instring)
259 return Find (where, what, pos+1, end, instring);
260
261 return pos;
262
263 }
264
265 // Replace (using Find)
266 void Replace (string* String, string Old, string New, int start, int end, int instring)
267 {
268 int pos = start;
269
270 while(true)
271 {
272 pos = Find(String->c_str(), Old, pos, end, instring);
273 if (pos == -1)
274 break;
275
276 String->replace (pos, Old.length(), New);
277 }
278 }