Index: src/Command.h ================================================================== --- src/Command.h +++ src/Command.h @@ -8,11 +8,9 @@ - (instancetype)initWithName:(OFString *)name OF_UNAVAILABLE; - (instancetype)initWithName:(OFString *)name function:(void (*)())function argumentsTypes:(int)argumentsTypes; -- (int)callWithArguments:(char *_Nonnull *_Nonnull)arguments - numArguments:(size_t)numArguments - isDown:(bool)isDown; +- (int)callWithArguments:(OFArray *)arguments isDown:(bool)isDown; @end OF_ASSUME_NONNULL_END Index: src/Command.mm ================================================================== --- src/Command.mm +++ src/Command.mm @@ -13,105 +13,98 @@ _argumentsTypes = argumentsTypes; return self; } -- (int)callWithArguments:(char **)arguments - numArguments:(size_t)numArguments - isDown:(bool)isDown +- (int)callWithArguments:(OFArray *)arguments isDown:(bool)isDown { switch (_argumentsTypes) { case ARG_1INT: if (isDown) - ((void(__cdecl *)(int))_function)(ATOI(arguments[1])); + ((void(__cdecl *)(int))_function)( + (int)[arguments[1] longLongValueWithBase:0]); break; case ARG_2INT: if (isDown) ((void(__cdecl *)(int, int))_function)( - ATOI(arguments[1]), ATOI(arguments[2])); + (int)[arguments[1] longLongValueWithBase:0], + (int)[arguments[2] longLongValueWithBase:0]); break; case ARG_3INT: if (isDown) ((void(__cdecl *)(int, int, int))_function)( - ATOI(arguments[1]), ATOI(arguments[2]), - ATOI(arguments[3])); + (int)[arguments[1] longLongValueWithBase:0], + (int)[arguments[2] longLongValueWithBase:0], + (int)[arguments[3] longLongValueWithBase:0]); break; case ARG_4INT: if (isDown) ((void(__cdecl *)(int, int, int, int))_function)( - ATOI(arguments[1]), ATOI(arguments[2]), - ATOI(arguments[3]), ATOI(arguments[4])); + (int)[arguments[1] longLongValueWithBase:0], + (int)[arguments[2] longLongValueWithBase:0], + (int)[arguments[3] longLongValueWithBase:0], + (int)[arguments[4] longLongValueWithBase:0]); break; case ARG_NONE: if (isDown) ((void(__cdecl *)())_function)(); break; case ARG_1STR: if (isDown) - ((void(__cdecl *)(OFString *))_function)( - @(arguments[1])); + ((void(__cdecl *)(OFString *))_function)(arguments[1]); break; case ARG_2STR: if (isDown) ((void(__cdecl *)(OFString *, OFString *))_function)( - @(arguments[1]), @(arguments[2])); + arguments[1], arguments[2]); break; case ARG_3STR: if (isDown) ((void(__cdecl *)( OFString *, OFString *, OFString *))_function)( - @(arguments[1]), @(arguments[2]), @(arguments[3])); + arguments[1], arguments[2], arguments[3]); break; case ARG_5STR: if (isDown) ((void(__cdecl *)(OFString *, OFString *, OFString *, - OFString *, OFString *))_function)(@(arguments[1]), - @(arguments[2]), @(arguments[3]), @(arguments[4]), - @(arguments[5])); + OFString *, OFString *))_function)(arguments[1], + arguments[2], arguments[3], arguments[4], + arguments[5]); break; case ARG_DOWN: ((void(__cdecl *)(bool))_function)(isDown); break; case ARG_DWN1: ((void(__cdecl *)(bool, OFString *))_function)( - isDown, @(arguments[1])); + 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])); + arguments[1]); break; case ARG_2EST: if (isDown) - return ( - (int(__cdecl *)(OFString *, OFString *))_function)( - @(arguments[1]), @(arguments[2])); + return ((int(__cdecl *)(OFString *, + OFString *))_function)(arguments[1], arguments[2]); break; case ARG_VARI: - if (isDown) { + if (isDown) // limit, remove - string r; - r[0] = 0; - for (int i = 1; i < numArguments; i++) { - // make string-list out of all arguments - strcat_s(r, arguments[i]); - if (i == numArguments - 1) - break; - strcat_s(r, " "); - } - ((void(__cdecl *)(OFString *))_function)(@(r)); - } + ((void(__cdecl *)(OFString *))_function)([[arguments + objectsInRange:OFMakeRange(1, arguments.count - 1)] + componentsJoinedByString:@" "]); break; } return 0; } Index: src/commands.mm ================================================================== --- src/commands.mm +++ src/commands.mm @@ -168,25 +168,25 @@ if (p - word == 0) return NULL; return newstring(word, p - word); } -char * -lookup(char *n) // find value of ident referenced with $ in exp +OFString * +lookup(OFString *n) // find value of ident referenced with $ in exp { @autoreleasepool { - __kindof Identifier *identifier = identifiers[@(n + 1)]; + __kindof Identifier *identifier = + identifiers[[n substringFromIndex:1]]; if ([identifier isKindOfClass:[Variable class]]) { - string t; - itoa(t, *[identifier storage]); - return exchangestr(n, t); + return [OFString + stringWithFormat:@"%d", *[identifier storage]]; } else if ([identifier isKindOfClass:[Alias class]]) - return exchangestr(n, [identifier action].UTF8String); + return [identifier action]; } - conoutf(@"unknown alias lookup: %s", n + 1); + conoutf(@"unknown alias lookup: %@", [n substringFromIndex:1]); return n; } int execute( @@ -194,94 +194,99 @@ { @autoreleasepool { std::unique_ptr copy(strdup(string.UTF8String)); char *p = copy.get(); const int MAXWORDS = 25; // limit, remove - char *w[MAXWORDS]; + OFString *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] = ""; + 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; + // substitute variables + w[i] = lookup(@(s)); + else + 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]; + OFString *c = w[0]; // strip irc-style command prefix - if (*c == '/') - c++; + if ([c hasPrefix:@"/"]) + c = [c substringFromIndex:1]; // empty statement - if (!*c) + if (c.length == 0) continue; - __kindof Identifier *identifier = identifiers[@(c)]; + __kindof Identifier *identifier = identifiers[c]; if (identifier == nil) { - val = ATOI(c); - if (!val && *c != '0') + @try { + val = (int)[c longLongValueWithBase:0]; + } @catch (OFInvalidFormatException *e) { conoutf(@"unknown command: %s", c); + } } else { if ([identifier isKindOfClass:[Command class]]) { // game defined commands use very // ad-hoc function signature, and just // call it + OFArray *arguments = + [[OFArray alloc] + initWithObjects:w + count:numargs + 1]; val = [identifier - callWithArguments:w - numArguments:numargs + callWithArguments:arguments isDown:isdown]; } else if ([identifier isKindOfClass:[Variable class]]) { // game defined variables if (isdown) { - if (!w[1][0]) + if (w[1].length == 0) [identifier printValue]; else [identifier - setValue:ATOI( - w[1])]; + setValue: + (int)[w[1] + longLongValueWithBase: + 0]]; } } else if ([identifier isKindOfClass:[Alias class]]) { // alias, also used as functions and // (global) variables for (int i = 1; i < numargs; i++) { - @autoreleasepool { - // set any arguments as - // (global) arg values - // so functions can - // access them - OFString *t = [OFString - stringWithFormat: - @"arg%d", i]; - alias(t, @(w[i])); - } + // set any arguments as + // (global) arg values so + // functions can access them + OFString *t = [OFString + stringWithFormat:@"arg%d", + i]; + alias(t, w[i]); } // create new string here because alias // could rebind itself val = execute( [[identifier action] copy], isdown); break; } } - loopj(numargs) gp()->deallocstr(w[j]); } return val; } }