| 486 | } |
| 487 | |
| 488 | char *executeret(const char *p) // all evaluation happens here, recursively |
| 489 | { |
| 490 | if(!p || !p[0]) return NULL; |
| 491 | if(executionstack.length() > CSLIMIT_RECURSION) { cslimiterr("recursion depth"); return NULL; } |
| 492 | executionstack.add(p); |
| 493 | char *w[MAXWORDS], emptychar = '\0'; |
| 494 | char *retval = NULL; |
| 495 | #define setretval(v) { char *rv = v; if(rv) retval = rv; } |
| 496 | for(bool cont = true; cont;) // for each ; seperated statement |
| 497 | { |
| 498 | if(loop_level && loop_skip) break; |
| 499 | int numargs = MAXWORDS, infix = 0; |
| 500 | loopi(MAXWORDS) // collect all argument values |
| 501 | { |
| 502 | w[i] = &emptychar; |
| 503 | if(i>numargs) continue; |
| 504 | char *s = parseword(p, i, &infix, executionstack.length()); // parse and evaluate exps |
| 505 | if(s) w[i] = s; |
| 506 | else numargs = i; |
| 507 | } |
| 508 | |
| 509 | p += strcspn(p, ";\n\r\0"); |
| 510 | cont = *p++!=0; // more statements if this isn't the end of the string |
| 511 | const char *c = w[0]; |
| 512 | if(!*c) continue; // empty statement |
| 513 | |
| 514 | DELETEA(retval); |
| 515 | |
| 516 | if(infix == '=') |
| 517 | { |
| 518 | DELETEA(w[1]); |
| 519 | swap(w[0], w[1]); |
| 520 | c = "alias"; |
| 521 | } |
| 522 | |
| 523 | ident *id = idents->access(c); |
| 524 | if(!id) |
| 525 | { |
| 526 | if(!isdigit(*c) && ((*c!='+' && *c!='-' && *c!='.') || !isdigit(c[1]))) |
| 527 | { |
| 528 | conoutf("unknown command: %s", c); |
| 529 | scripterr(); |
| 530 | FLAGMAPCONFIGERR(LWW_SCRIPTERR * 4); |
| 531 | } |
| 532 | setretval(newstring(c)); |
| 533 | } |
| 534 | else if(identaccessdenied(id)) |
| 535 | { |
| 536 | conoutf("not allowed in this execution context: %s", id->name); |
| 537 | scripterr(); |
| 538 | FLAGMAPCONFIGERR(LWW_SCRIPTERR * 4); |
| 539 | } |
| 540 | else |
| 541 | { |
| 542 | switch(id->type) |
| 543 | { |
| 544 | case ID_COMMAND: // game defined commands |
| 545 | { |
no test coverage detected