aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/LuaSL
diff options
context:
space:
mode:
authorDavid Walter Seikel2014-08-09 20:09:28 +1000
committerDavid Walter Seikel2014-08-09 20:09:28 +1000
commitb4dae31e4a688dea7779b83451b8179437b9c0c3 (patch)
tree4f3ca77c787a8d6ab6f29ee47d5100b4d8ef1855 /src/LuaSL
parentMention compiler speed even if the last one failed. (diff)
downloadSledjHamr-b4dae31e4a688dea7779b83451b8179437b9c0c3.zip
SledjHamr-b4dae31e4a688dea7779b83451b8179437b9c0c3.tar.gz
SledjHamr-b4dae31e4a688dea7779b83451b8179437b9c0c3.tar.bz2
SledjHamr-b4dae31e4a688dea7779b83451b8179437b9c0c3.tar.xz
Major cleanup of compileLSL() and friends, including threading it.
Diffstat (limited to 'src/LuaSL')
-rw-r--r--src/LuaSL/LuaSL.h1
-rw-r--r--src/LuaSL/LuaSL_LSL_tree.h9
-rw-r--r--src/LuaSL/LuaSL_compile.c140
-rw-r--r--src/LuaSL/LuaSL_main.c24
4 files changed, 88 insertions, 86 deletions
diff --git a/src/LuaSL/LuaSL.h b/src/LuaSL/LuaSL.h
index 54e7fa7..f696f03 100644
--- a/src/LuaSL/LuaSL.h
+++ b/src/LuaSL/LuaSL.h
@@ -12,6 +12,7 @@ typedef struct _gameGlobals gameGlobals; // Define this here, so LuaSL_threads.h
12#include "LumbrJack.h" 12#include "LumbrJack.h"
13#include "Runnr.h" 13#include "Runnr.h"
14 14
15#define COMPILE_THREADED 0
15 16
16struct _gameGlobals 17struct _gameGlobals
17{ 18{
diff --git a/src/LuaSL/LuaSL_LSL_tree.h b/src/LuaSL/LuaSL_LSL_tree.h
index fca31db..b95b82e 100644
--- a/src/LuaSL/LuaSL_LSL_tree.h
+++ b/src/LuaSL/LuaSL_LSL_tree.h
@@ -370,13 +370,10 @@ Need to do something about that.
370 370
371typedef struct 371typedef struct
372{ 372{
373 gameGlobals *game; 373 LuaCompiler compiler;
374 Ecore_Con_Client *client;
375 void *scanner; // This should be of type yyscan_t, which is typedef to void * anyway, but that does not get defined until LuaSL_lexer.h, which depends on this struct being defined first. 374 void *scanner; // This should be of type yyscan_t, which is typedef to void * anyway, but that does not get defined until LuaSL_lexer.h, which depends on this struct being defined first.
376 int argc; 375 int argc;
377 char **argv; 376 char **argv;
378 char SID[37];
379 char fileName[PATH_MAX];
380 FILE *file; 377 FILE *file;
381 LSL_Leaf *ast; 378 LSL_Leaf *ast;
382 LSL_Script script; 379 LSL_Script script;
@@ -391,6 +388,8 @@ typedef struct
391 int column, line; 388 int column, line;
392 int undeclared; 389 int undeclared;
393 boolean inState; 390 boolean inState;
391 boolean doConstants;
392 boolean result;
394} LuaSL_compiler; 393} LuaSL_compiler;
395 394
396 395
@@ -401,7 +400,7 @@ typedef struct
401 400
402 401
403boolean compilerSetup(gameGlobals *ourGlobals); 402boolean compilerSetup(gameGlobals *ourGlobals);
404boolean compileLSL(LuaCompiler *lCompiler, gameGlobals *ourGlobals, Ecore_Con_Client *client, char *SID, char *script, boolean doConstants); 403boolean compileLSL(LuaSL_compiler *lCompiler);
405void burnLeaf(void *data); 404void burnLeaf(void *data);
406 405
407LSL_Leaf *addBlock(LuaSL_compiler *compiler, LSL_Leaf *left, LSL_Leaf *lval, LSL_Leaf *right); 406LSL_Leaf *addBlock(LuaSL_compiler *compiler, LSL_Leaf *left, LSL_Leaf *lval, LSL_Leaf *right);
diff --git a/src/LuaSL/LuaSL_compile.c b/src/LuaSL/LuaSL_compile.c
index 5d244fa..87ba95d 100644
--- a/src/LuaSL/LuaSL_compile.c
+++ b/src/LuaSL/LuaSL_compile.c
@@ -362,7 +362,7 @@ LSL_Leaf *checkVariable(LuaSL_compiler *compiler, LSL_Leaf *identifier, LSL_Leaf
362 else 362 else
363 { 363 {
364 compiler->script.bugCount++; 364 compiler->script.bugCount++;
365 sendBack(compiler->client, compiler->SID, "compilerError(%d,%d,NOT found %s)", identifier->line, identifier->column, identifier->value.stringValue); 365 sendBack(compiler->compiler.client, compiler->compiler.SID, "compilerError(%d,%d,NOT found %s)", identifier->line, identifier->column, identifier->value.stringValue);
366 } 366 }
367 } 367 }
368 368
@@ -404,7 +404,7 @@ LSL_Leaf *addOperation(LuaSL_compiler *compiler, LSL_Leaf *left, LSL_Leaf *lval,
404 if (OT_undeclared == lType) 404 if (OT_undeclared == lType)
405 { 405 {
406 compiler->script.warningCount++; 406 compiler->script.warningCount++;
407// sendBack(compiler->client, compiler->SID, "compilerWarning(%d,%d,Undeclared identifier issue, deferring this until the second pass)", lval->line, lval->column); 407// sendBack(compiler->compiler.client, compiler->compiler.SID, "compilerWarning(%d,%d,Undeclared identifier issue, deferring this until the second pass)", lval->line, lval->column);
408 lval->basicType = OT_undeclared; 408 lval->basicType = OT_undeclared;
409 return lval; 409 return lval;
410 } 410 }
@@ -432,7 +432,7 @@ LSL_Leaf *addOperation(LuaSL_compiler *compiler, LSL_Leaf *left, LSL_Leaf *lval,
432 if (OT_undeclared == rType) 432 if (OT_undeclared == rType)
433 { 433 {
434 compiler->script.warningCount++; 434 compiler->script.warningCount++;
435// sendBack(compiler->client, compiler->SID, "compilerWarning(%d,%d,Undeclared identifier issue, deferring this until the second pass)", lval->line, lval->column); 435// sendBack(compiler->compiler.client, compiler->compiler.SID, "compilerWarning(%d,%d,Undeclared identifier issue, deferring this until the second pass)", lval->line, lval->column);
436 lval->basicType = OT_undeclared; 436 lval->basicType = OT_undeclared;
437 return lval; 437 return lval;
438 } 438 }
@@ -633,7 +633,7 @@ else
633 } 633 }
634 634
635 compiler->script.bugCount++; 635 compiler->script.bugCount++;
636 sendBack(compiler->client, compiler->SID, "compilerError(%d,%d,Invalid operation [%s(%s) %s %s(%s)])", lval->line, lval->column, leftType, leftToken, lval->toKen->toKen, rightType, rightToken); 636 sendBack(compiler->compiler.client, compiler->compiler.SID, "compilerError(%d,%d,Invalid operation [%s(%s) %s %s(%s)])", lval->line, lval->column, leftType, leftToken, lval->toKen->toKen, rightType, rightToken);
637 } 637 }
638 } 638 }
639 639
@@ -2191,7 +2191,7 @@ boolean compilerSetup(gameGlobals *ourGlobals)
2191 if (tokens) 2191 if (tokens)
2192 { 2192 {
2193 char buf[PATH_MAX]; 2193 char buf[PATH_MAX];
2194 LuaCompiler *compiler = calloc(1, sizeof(LuaCompiler)); 2194 LuaSL_compiler *compiler = calloc(1, sizeof(LuaSL_compiler));
2195 2195
2196 // Sort the token table. 2196 // Sort the token table.
2197 for (i = 0; LSL_Tokens[i].toKen != NULL; i++) 2197 for (i = 0; LSL_Tokens[i].toKen != NULL; i++)
@@ -2205,12 +2205,13 @@ boolean compilerSetup(gameGlobals *ourGlobals)
2205 snprintf(buf, sizeof(buf), "luajit -e 'require(\"LSL\").gimmeLSL()' > %s/constants.lsl", prefix_lib_get()); 2205 snprintf(buf, sizeof(buf), "luajit -e 'require(\"LSL\").gimmeLSL()' > %s/constants.lsl", prefix_lib_get());
2206 system(buf); 2206 system(buf);
2207 snprintf(buf, sizeof(buf), "%s/constants.lsl", prefix_lib_get()); 2207 snprintf(buf, sizeof(buf), "%s/constants.lsl", prefix_lib_get());
2208 compiler->file = strdup(buf); 2208 compiler->compiler.file = strdup(buf);
2209 compiler->SID = strdup("FAKE_SID"); 2209 compiler->compiler.SID = strdup("FAKE_SID");
2210 compiler->data = ourGlobals; 2210 compiler->compiler.data = ourGlobals;
2211 compiler->cb = _compileCb; 2211 compiler->compiler.cb = _compileCb;
2212 if (!compileLSL(compiler, ourGlobals, NULL, "FAKE_SID", buf, TRUE)) 2212 compiler->doConstants = TRUE;
2213 _compileCb(compiler); 2213 if (!compileLSL(compiler))
2214 _compileCb(&compiler->compiler);
2214 2215
2215 return TRUE; 2216 return TRUE;
2216 } 2217 }
@@ -2220,74 +2221,66 @@ boolean compilerSetup(gameGlobals *ourGlobals)
2220 return FALSE; 2221 return FALSE;
2221} 2222}
2222 2223
2223boolean compileLSL(LuaCompiler *lCompiler, gameGlobals *ourGlobals, Ecore_Con_Client *client, char *SID, char *script, boolean doConstants) 2224boolean compileLSL(LuaSL_compiler *compiler)
2224{ 2225{
2225 boolean result = FALSE;
2226 LuaSL_compiler compiler;
2227 void *pParser = ParseAlloc(malloc); 2226 void *pParser = ParseAlloc(malloc);
2228 int yv; 2227 int yv;
2229 2228
2230// Parse the LSL script, validating it and reporting errors. 2229// Parse the LSL script, validating it and reporting errors.
2231// Just pass all LSL constants and ll*() )function names through to Lua, assume they are globals there. 2230// Just pass all LSL constants and ll*() )function names through to Lua, assume they are globals there.
2232 2231
2233 memset(&compiler, 0, sizeof(LuaSL_compiler)); 2232 compiler->result = FALSE;
2234 compiler.game = ourGlobals; 2233 compiler->script.functions = eina_hash_stringshared_new(burnLeaf);
2235 compiler.client = client; 2234 compiler->script.states = eina_hash_stringshared_new(burnLeaf);
2236 compiler.script.functions = eina_hash_stringshared_new(burnLeaf); 2235 compiler->script.variables = eina_hash_stringshared_new(burnLeaf);
2237 compiler.script.states = eina_hash_stringshared_new(burnLeaf); 2236 eina_clist_init(&(compiler->danglingCalls));
2238 compiler.script.variables = eina_hash_stringshared_new(burnLeaf);
2239 eina_clist_init(&(compiler.danglingCalls));
2240#if LUASL_DIFF_CHECK 2237#if LUASL_DIFF_CHECK
2241 compiler.ignorable = eina_strbuf_new(); 2238 compiler->ignorable = eina_strbuf_new();
2242#endif 2239#endif
2243 2240
2244 strncpy(compiler.SID, SID, 36); 2241 compiler->file = fopen(compiler->compiler.file, "r");
2245 compiler.SID[36] = '\0'; 2242 if (NULL == compiler->file)
2246 strncpy(compiler.fileName, script, PATH_MAX - 1);
2247 compiler.fileName[PATH_MAX - 1] = '\0';
2248 compiler.file = fopen(compiler.fileName, "r");
2249 if (NULL == compiler.file)
2250 { 2243 {
2251 PE("Error opening file %s.", compiler.fileName); 2244 PE("Error opening file %s.", compiler->compiler.file);
2252 return FALSE; 2245 return FALSE;
2253 } 2246 }
2254 compiler.ast = NULL; 2247 compiler->ast = NULL;
2255 compiler.lval = newLeaf(LSL_UNKNOWN, NULL, NULL); 2248 compiler->lval = newLeaf(LSL_UNKNOWN, NULL, NULL);
2256 // Text editors usually start counting at 1, even programmers editors. mcedit is an exception, but you can deal with that yourself. 2249 // Text editors usually start counting at 1, even programmers editors. mcedit is an exception, but you can deal with that yourself.
2257 compiler.column = 1; 2250 compiler->column = 1;
2258 compiler.line = 1; 2251 compiler->line = 1;
2259 2252
2260 if (yylex_init_extra(&compiler, &(compiler.scanner))) 2253 if (yylex_init_extra(compiler, &(compiler->scanner)))
2261 return result; 2254 return compiler->result;
2262 if (LUASL_DEBUG) 2255 if (LUASL_DEBUG)
2263 { 2256 {
2264 yyset_debug(1, compiler.scanner); 2257 yyset_debug(1, compiler->scanner);
2265 ParseTrace(stdout, "LSL_lemon "); 2258 ParseTrace(stdout, "LSL_lemon ");
2266 } 2259 }
2267 yyset_in(compiler.file, compiler.scanner); 2260 yyset_in(compiler->file, compiler->scanner);
2268 // on EOF yylex will return 0 2261 // on EOF yylex will return 0
2269 while((yv = yylex(compiler.lval, compiler.scanner)) != 0) 2262 while((yv = yylex(compiler->lval, compiler->scanner)) != 0)
2270 { 2263 {
2271 Parse(pParser, yv, compiler.lval, &compiler); 2264 Parse(pParser, yv, compiler->lval, compiler);
2272 if (LSL_SCRIPT == yv) 2265 if (LSL_SCRIPT == yv)
2273 break; 2266 break;
2274 compiler.lval = newLeaf(LSL_UNKNOWN, NULL, NULL); 2267 compiler->lval = newLeaf(LSL_UNKNOWN, NULL, NULL);
2275 } 2268 }
2276 2269
2277 yylex_destroy(compiler.scanner); 2270 yylex_destroy(compiler->scanner);
2278 Parse (pParser, 0, compiler.lval, &compiler); 2271 Parse(pParser, 0, compiler->lval, compiler);
2279 ParseFree(pParser, free); 2272 ParseFree(pParser, free);
2280 2273
2281 if (compiler.undeclared) 2274 if (compiler->undeclared)
2282 { 2275 {
2283// PW("A second pass is needed to check if functions where used before they where declared. To avoid this second pass, don't do that."); 2276// PW("A second pass is needed to check if functions where used before they where declared. To avoid this second pass, don't do that.");
2284 if (eina_clist_count(&(compiler.danglingCalls))) 2277 if (eina_clist_count(&(compiler->danglingCalls)))
2285 { 2278 {
2286 LSL_FunctionCall *call = NULL; 2279 LSL_FunctionCall *call = NULL;
2287 2280
2288 EINA_CLIST_FOR_EACH_ENTRY(call, &(compiler.danglingCalls), LSL_FunctionCall, dangler) 2281 EINA_CLIST_FOR_EACH_ENTRY(call, &(compiler->danglingCalls), LSL_FunctionCall, dangler)
2289 { 2282 {
2290 LSL_Leaf *func = findFunction(&(compiler), call->call->value.stringValue); 2283 LSL_Leaf *func = findFunction(compiler, call->call->value.stringValue);
2291 2284
2292 if (func) 2285 if (func)
2293 { 2286 {
@@ -2298,23 +2291,23 @@ boolean compileLSL(LuaCompiler *lCompiler, gameGlobals *ourGlobals, Ecore_Con_Cl
2298 call->call->basicType = func->basicType; 2291 call->call->basicType = func->basicType;
2299 } 2292 }
2300 else 2293 else
2301 sendBack(compiler.client, compiler.SID, "compilerError(%d,%d,Undeclared function %s called)", call->call->line, call->call->column, call->call->value.stringValue); 2294 sendBack(compiler->compiler.client, compiler->compiler.SID, "compilerError(%d,%d,Undeclared function %s called)", call->call->line, call->call->column, call->call->value.stringValue);
2302 } 2295 }
2303 } 2296 }
2304 secondPass(&compiler, compiler.ast); 2297 secondPass(compiler, compiler->ast);
2305// PD("Second pass completed."); 2298// PD("Second pass completed.");
2306 } 2299 }
2307 2300
2308 if (doConstants) 2301 if (compiler->doConstants)
2309 { 2302 {
2310 memcpy(&constants, &(compiler.script), sizeof(LSL_Script)); 2303 memcpy(&constants, &(compiler->script), sizeof(LSL_Script));
2311 result = TRUE; 2304 compiler->result = TRUE;
2312 } 2305 }
2313 else 2306 else
2314 { 2307 {
2315 result = FALSE; 2308 compiler->result = FALSE;
2316 2309
2317 if (compiler.ast) 2310 if (compiler->ast)
2318 { 2311 {
2319 FILE *out; 2312 FILE *out;
2320 char buffer[PATH_MAX]; 2313 char buffer[PATH_MAX];
@@ -2324,28 +2317,28 @@ boolean compileLSL(LuaCompiler *lCompiler, gameGlobals *ourGlobals, Ecore_Con_Cl
2324 2317
2325 if (LUASL_DIFF_CHECK) 2318 if (LUASL_DIFF_CHECK)
2326 { 2319 {
2327 strcpy(outName, compiler.fileName); 2320 strcpy(outName, compiler->compiler.file);
2328 strcat(outName, "2"); 2321 strcat(outName, "2");
2329 out = fopen(outName, "w"); 2322 out = fopen(outName, "w");
2330 if (out) 2323 if (out)
2331 { 2324 {
2332 char diffName[PATH_MAX]; 2325 char diffName[PATH_MAX];
2333 2326
2334 strcpy(diffName, compiler.fileName); 2327 strcpy(diffName, compiler->compiler.file);
2335 strcat(diffName, ".diff"); 2328 strcat(diffName, ".diff");
2336 outputLeaf(out, OM_LSL, compiler.ast); 2329 outputLeaf(out, OM_LSL, compiler->ast);
2337 fclose(out); 2330 fclose(out);
2338 sprintf(buffer, "diff -u \"%s\" \"%s\" > \"%s\"", compiler.fileName, outName, diffName); 2331 sprintf(buffer, "diff -u \"%s\" \"%s\" > \"%s\"", compiler->compiler.file, outName, diffName);
2339 count = system(buffer); 2332 count = system(buffer);
2340 if (0 != count) 2333 if (0 != count)
2341 PE("LSL output file is different - %s!", outName); 2334 PE("LSL output file is different - %s!", outName);
2342 else 2335 else
2343 result = TRUE; 2336 compiler->result = TRUE;
2344 } 2337 }
2345 else 2338 else
2346 PC("Unable to open file %s for writing!", outName); 2339 PC("Unable to open file %s for writing!", outName);
2347 } 2340 }
2348 strcpy(luaName, compiler.fileName); 2341 strcpy(luaName, compiler->compiler.file);
2349 strcat(luaName, ".lua"); 2342 strcat(luaName, ".lua");
2350 out = fopen(luaName, "w"); 2343 out = fopen(luaName, "w");
2351 // Generate the Lua source code. 2344 // Generate the Lua source code.
@@ -2356,35 +2349,38 @@ boolean compileLSL(LuaCompiler *lCompiler, gameGlobals *ourGlobals, Ecore_Con_Cl
2356 fprintf(out, "--// Generated code goes here.\n\n"); 2349 fprintf(out, "--// Generated code goes here.\n\n");
2357 fprintf(out, "local _bit = require(\"bit\")\n"); 2350 fprintf(out, "local _bit = require(\"bit\")\n");
2358 fprintf(out, "local _LSL = require(\"LSL\")\n\n"); 2351 fprintf(out, "local _LSL = require(\"LSL\")\n\n");
2359 fprintf(out, "local _SID = [=[%s]=]\n\n", compiler.SID); 2352 fprintf(out, "local _SID = [=[%s]=]\n\n", compiler->compiler.SID);
2360 strcpy(buffer, basename(compiler.fileName)); 2353 strcpy(buffer, basename(compiler->compiler.file));
2361 if ((ext = rindex(buffer, '.'))) 2354 if ((ext = rindex(buffer, '.')))
2362 ext[0] = '\0'; 2355 ext[0] = '\0';
2363 fprintf(out, "local _scriptName = [=[%s]=]\n\n", buffer); 2356 fprintf(out, "local _scriptName = [=[%s]=]\n\n", buffer);
2364 outputLeaf(out, OM_LUA, compiler.ast); 2357 outputLeaf(out, OM_LUA, compiler->ast);
2365 fprintf(out, "\n\n_LSL.mainLoop(_SID, _scriptName, _defaultState)\n"); // This actually starts the script running. 2358 fprintf(out, "\n\n_LSL.mainLoop(_SID, _scriptName, _defaultState)\n"); // This actually starts the script running.
2366 fprintf(out, "\n--// End of generated code.\n\n"); 2359 fprintf(out, "\n--// End of generated code.\n\n");
2367 fclose(out); 2360 fclose(out);
2368 2361
2369 // Compile the Lua source code. 2362 // Compile the Lua source code.
2370 lCompiler->luaName = strdup(luaName); 2363 compiler->compiler.luaName = strdup(luaName);
2371 lCompiler->bugCount = compiler.script.bugCount; 2364 compiler->compiler.bugCount = compiler->script.bugCount;
2372 compileScript(lCompiler); 2365#if !COMPILE_THREADED
2373 result = TRUE; 2366 compileScript(&compiler->compiler);
2367#endif
2368 compiler->result = TRUE;
2374 } 2369 }
2375 else 2370 else
2376 PC("Unable to open file %s for writing!", luaName); 2371 PC("Unable to open file %s for writing!", luaName);
2377 } 2372 }
2378 } 2373 }
2379 2374
2380 if (NULL != compiler.file) 2375 if (NULL != compiler->file)
2381 { 2376 {
2382 fclose(compiler.file); 2377 fclose(compiler->file);
2383 compiler.file = NULL; 2378 compiler->file = NULL;
2384 } 2379 }
2385 2380
2386 if (!doConstants) 2381 if (!compiler->doConstants)
2387 burnLeaf(compiler.ast); 2382 burnLeaf(compiler->ast);
2383// end compile thread here
2388 2384
2389 return result; 2385 return compiler->result;
2390} 2386}
diff --git a/src/LuaSL/LuaSL_main.c b/src/LuaSL/LuaSL_main.c
index 41576c2..0378792 100644
--- a/src/LuaSL/LuaSL_main.c
+++ b/src/LuaSL/LuaSL_main.c
@@ -226,7 +226,7 @@ static Eina_Bool _data(void *data, int type __UNUSED__, Ecore_Con_Event_Client_D
226 char *temp; 226 char *temp;
227 char *file; 227 char *file;
228 char *name; 228 char *name;
229 LuaCompiler *compiler = calloc(1, sizeof(LuaCompiler)); 229 LuaSL_compiler *compiler = calloc(1, sizeof(LuaSL_compiler));
230 230
231 strcpy(buf, &command[8]); 231 strcpy(buf, &command[8]);
232 temp = buf; 232 temp = buf;
@@ -237,17 +237,23 @@ static Eina_Bool _data(void *data, int type __UNUSED__, Ecore_Con_Event_Client_D
237 237
238 name = &file[strlen(prefix_data_get())]; 238 name = &file[strlen(prefix_data_get())];
239 PD("Compiling %s, %s.", SID, name); 239 PD("Compiling %s, %s.", SID, name);
240 compiler->file = strdup(file); 240 compiler->compiler.file = strdup(file);
241 compiler->SID = strdup(SID); 241 compiler->compiler.SID = strdup(SID);
242 compiler->client = ev->client; 242 compiler->compiler.client = ev->client;
243 compiler->data = ourGlobals; 243 compiler->compiler.data = ourGlobals;
244 compiler->cb = _compileCb; 244 compiler->compiler.cb = _compileCb;
245 if (!compileLSL(compiler, ourGlobals, ev->client, SID, file, FALSE)) 245 compiler->doConstants = FALSE;
246#if COMPILE_THREADED
247 compiler->compiler.parser = (compileCb) compileLSL;
248 compileScript(&compiler->compiler);
249#else
250 if (!compileLSL(compiler))
246 { 251 {
247 compiler->bugCount++; 252 compiler->compiler.bugCount++;
248 PE("Compile of %s failed in a mysterious way.", file); 253 PE("Compile of %s failed in a mysterious way.", file);
249 _compileCb(compiler); 254 _compileCb(&(compiler->compiler));
250 } 255 }
256#endif
251 } 257 }
252 else if (0 == strcmp(command, "run()")) 258 else if (0 == strcmp(command, "run()"))
253 { 259 {