Index: src/Command.mm ================================================================== --- src/Command.mm +++ src/Command.mm @@ -76,16 +76,16 @@ isDown, @(arguments[1])); break; case ARG_1EXP: if (isDown) return ((int(__cdecl *)(int))_function)( - execute(arguments[1])); + execute(@(arguments[1]))); break; case ARG_2EXP: if (isDown) return ((int(__cdecl *)(int, int))_function)( - execute(arguments[1]), execute(arguments[2])); + execute(@(arguments[1])), execute(@(arguments[2]))); break; case ARG_1EST: if (isDown) return ((int(__cdecl *)(OFString *))_function)( @(arguments[1])); Index: src/clientgame.mm ================================================================== --- src/clientgame.mm +++ src/clientgame.mm @@ -1,11 +1,9 @@ // clientgame.cpp: core game related stuff #include "cube.h" -#include - int nextmode = 0; // nextmode becomes gamemode after next map load VAR(gamemode, 1, 0, 0); void mode(int n) @@ -245,15 +243,11 @@ { if (lastmillis) { curtime = millis - lastmillis; if (sleepwait && lastmillis > sleepwait) { sleepwait = 0; - @autoreleasepool { - std::unique_ptr cmd( - strdup(sleepcmd.UTF8String)); - execute(cmd.get()); - } + execute(sleepcmd); } physicsframe(); checkquad(curtime); if (m_arena) arenarespawn(); @@ -263,11 +257,11 @@ if (getclientnum() >= 0) shoot(player1, worldpos); // only shoot when // connected to server gets2c(); // do this first, so we have most accurate // information when our player moves - }; + } otherplayers(); if (!demoplayback) { monsterthink(); if (player1->state == CS_DEAD) { if (lastmillis - player1->lastaction < 2000) { @@ -281,14 +275,14 @@ moveplayer(player1, 20, true); checkitems(); }; c2sinfo(player1); // do this last, to reduce the // effective frame lag - }; - }; + } + } lastmillis = millis; -}; +} void entinmap(dynent * d) // brute force but effective way to find a free spawn spot in the map { Index: src/commands.mm ================================================================== --- src/commands.mm +++ src/commands.mm @@ -133,13 +133,14 @@ } } char *s = newstring(word, p - word - 1); if (left == '(') { string t; - itoa(t, - execute( - s)); // evaluate () exps directly, and substitute result + // evaluate () exps directly, and substitute result + @autoreleasepool { + itoa(t, execute(@(s))); + } s = exchangestr(s, t); } return s; } @@ -186,55 +187,61 @@ conoutf(@"unknown alias lookup: %s", n + 1); return n; } int -execute(char *p, bool isdown) // all evaluation happens here, recursively -{ - const int MAXWORDS = 25; // limit, remove - char *w[MAXWORDS]; - int val = 0; - for (bool cont = true; cont;) // for each ; seperated statement - { - int numargs = MAXWORDS; - loopi(MAXWORDS) // collect all argument values - { - w[i] = ""; - if (i > numargs) - continue; - char *s = parseword(p); // parse and evaluate exps - if (!s) { - numargs = i; - s = ""; - } - if (*s == '$') - s = lookup(s); // substitute variables - w[i] = s; - } - - p += strcspn(p, ";\n\0"); - cont = *p++ != - 0; // more statements if this isn't the end of the string - char *c = w[0]; - if (*c == '/') - c++; // strip irc-style command prefix - if (!*c) - continue; // empty statement - - @autoreleasepool { - __kindof Identifier *identifier = identifiers[@(c)]; - +execute( + OFString *string, bool isdown) // all evaluation happens here, recursively +{ + @autoreleasepool { + std::unique_ptr copy(strdup(string.UTF8String)); + char *p = copy.get(); + const int MAXWORDS = 25; // limit, remove + char *w[MAXWORDS]; + int val = 0; + for (bool cont = true; cont;) { + // for each ; seperated statement + int numargs = MAXWORDS; + loopi(MAXWORDS) + { + // collect all argument values + w[i] = ""; + if (i > numargs) + continue; + // parse and evaluate exps + char *s = parseword(p); + if (!s) { + numargs = i; + s = ""; + } + if (*s == '$') + s = lookup(s); // substitute variables + w[i] = s; + } + + p += strcspn(p, ";\n\0"); + // more statements if this isn't the end of the string + cont = *p++ != 0; + char *c = w[0]; + // strip irc-style command prefix + if (*c == '/') + c++; + // empty statement + if (!*c) + continue; + + __kindof Identifier *identifier = identifiers[@(c)]; if (identifier == nil) { val = ATOI(c); if (!val && *c != '0') conoutf(@"unknown command: %s", c); } else { if ([identifier isKindOfClass:[Command class]]) { - // game defined commands - // use very ad-hoc function signature, - // and just call it + // game defined commands use very + // ad-hoc function signature, and just + // call it val = [identifier callWithArguments:w numArguments:numargs isDown:isdown]; } else if ([identifier @@ -265,22 +272,20 @@ alias(t, @(w[i])); } } // create new string here because alias // could rebind itself - char *action = newstring( - [identifier action].UTF8String); - val = execute(action, isdown); - gp()->deallocstr(action); + val = execute( + [[identifier action] copy], isdown); break; } } + loopj(numargs) gp()->deallocstr(w[j]); } - loopj(numargs) gp()->deallocstr(w[j]); - } - return val; + return val; + } } // tab-completion of all identifiers int completesize = 0, completeidx = 0; @@ -343,11 +348,11 @@ } // Ensure \0 termination. [data addItem:""]; - execute((char *)data.mutableItems); + execute(@((char *)data.mutableItems)); return true; } } void @@ -425,60 +430,45 @@ } void ifthen(OFString *cond, OFString *thenp, OFString *elsep) { - @autoreleasepool { - std::unique_ptr cmd(strdup( - (cond.UTF8String[0] != '0' ? thenp : elsep).UTF8String)); - - execute(cmd.get()); - } -} - -void -loopa(OFString *times, OFString *body_) -{ - @autoreleasepool { - int t = (int)times.longLongValue; - std::unique_ptr body(strdup(body_.UTF8String)); - - loopi(t) - { - intset(@"i", i); - execute(body.get()); - } - } -} - -void -whilea(OFString *cond_, OFString *body_) -{ - @autoreleasepool { - std::unique_ptr cond(strdup(cond_.UTF8String)); - std::unique_ptr body(strdup(body_.UTF8String)); - - while (execute(cond.get())) - execute(body.get()); - } -} - -void -onrelease(bool on, OFString *body) -{ - if (!on) { - std::unique_ptr copy(strdup(body.UTF8String)); - execute(copy.get()); - } -} - -void -concat(OFString *s) -{ - @autoreleasepool { - alias(@"s", s); - } + execute((![cond hasPrefix:@"0"] ? thenp : elsep)); +} + +void +loopa(OFString *times, OFString *body) +{ + @autoreleasepool { + int t = (int)times.longLongValue; + + loopi(t) + { + intset(@"i", i); + execute(body); + } + } +} + +void +whilea(OFString *cond, OFString *body) +{ + while (execute(cond)) + execute(body); +} + +void +onrelease(bool on, OFString *body) +{ + if (!on) + execute(body); +} + +void +concat(OFString *s) +{ + alias(@"s", s); } void concatword(OFString *s) { Index: src/console.mm ================================================================== --- src/console.mm +++ src/console.mm @@ -1,11 +1,10 @@ // console.cpp: the console buffer, its display, and command line control #include "cube.h" #include -#include #import "KeyMapping.h" struct cline { char *cref; @@ -171,13 +170,11 @@ { static bool rec = false; if (!rec && n >= 0 && n < vhistory.count) { rec = true; - OFString *cmd = vhistory[vhistory.count - n - 1]; - std::unique_ptr copy(strdup(cmd.UTF8String)); - execute(copy.get()); + execute(vhistory[vhistory.count - n - 1]); rec = false; } } COMMAND(history, ARG_1INT) @@ -247,16 +244,13 @@ [commandbuf copy]]; } } histpos = vhistory.count; - if ([commandbuf hasPrefix:@"/"]) { - std::unique_ptr copy( - strdup( - commandbuf.UTF8String)); - execute(copy.get(), true); - } else + if ([commandbuf hasPrefix:@"/"]) + execute(commandbuf, true); + else toserver(commandbuf); } saycommand(NULL); } else if (code == SDLK_ESCAPE) { saycommand(NULL); @@ -267,13 +261,11 @@ for (KeyMapping *mapping in keyMappings) { if (mapping.code == code) { // keystrokes go to game, lookup in keymap and // execute - string temp; - strcpy_s(temp, mapping.action.UTF8String); - execute(temp, isdown); + execute(mapping.action, isdown); return; } } } } Index: src/menus.mm ================================================================== --- src/menus.mm +++ src/menus.mm @@ -1,11 +1,9 @@ // menus.cpp: ingame menu system (also used for scores and serverlist) #include "cube.h" -#include - #import "Menu.h" #import "MenuItem.h" static OFMutableArray *menuStack; static OFMutableArray *menus; @@ -166,12 +164,11 @@ menuStack = [[OFMutableArray alloc] init]; [menuStack addObject:@(vmenu)]; menuset(-1); - std::unique_ptr copy(strdup(action.UTF8String)); - execute(copy.get(), true); + execute(action, true); } } return true; } Index: src/protos.h ================================================================== --- src/protos.h +++ src/protos.h @@ -5,11 +5,11 @@ void (*fun)(), bool persist); extern void setvar(OFString *name, int i); extern int getvar(OFString *name); extern bool identexists(OFString *name); extern bool addcommand(OFString *name, void (*fun)(), int narg); -extern int execute(char *p, bool down = true); +extern int execute(OFString *p, bool down = true); extern void exec(OFString *cfgfile); extern bool execfile(OFString *cfgfile); extern void resetcomplete(); extern void complete(OFString *s); extern void alias(OFString *name, OFString *action); Index: src/serverbrowser.mm ================================================================== --- src/serverbrowser.mm +++ src/serverbrowser.mm @@ -315,12 +315,14 @@ if (!*reply || strstr((char *)reply, "") || strstr((char *)reply, "")) conoutf(@"master server not replying"); else { servers.setsize(0); - execute((char *)reply); - }; + @autoreleasepool { + execute(@((char *)reply)); + } + } servermenu(); } COMMAND(addserver, ARG_1STR) COMMAND(servermenu, ARG_NONE) Index: src/world.mm ================================================================== --- src/world.mm +++ src/world.mm @@ -1,11 +1,9 @@ // world.cpp: core map management stuff #include "cube.h" -#include - extern OFString *entnames[]; // lookup from map entities above to strings sqr *world = NULL; int sfactor, ssize, cubicsize, mipsize; @@ -68,14 +66,12 @@ @autoreleasepool { OFString *aliasname = [OFString stringWithFormat:@"level_trigger_%d", tag]; - if (identexists(aliasname)) { - std::unique_ptr cmd(strdup(aliasname.UTF8String)); - execute(cmd.get()); - } + if (identexists(aliasname)) + execute(aliasname); } if (type == 2) endsp(false); } @@ -500,11 +496,11 @@ calclight(); startmap(@"base/unnamed"); if (oldworld) { free(oldworld); toggleedit(); - execute("fullbright 1"); + execute(@"fullbright 1"); } } void mapenlarge()