Clean up argument passing of commands

FossilOrigin-Name: 22520cd0d9f9e9a106f9680d90f4c5ac87da8db1c1c304342d6c637557012b22
This commit is contained in:
Jonathan Schleifer 2025-03-07 23:29:58 +00:00
parent e4c1890a25
commit 6ecfc000d1
3 changed files with 69 additions and 73 deletions

View file

@ -10,9 +10,7 @@ OF_ASSUME_NONNULL_BEGIN
- (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<OFString *> *)arguments isDown:(bool)isDown;
@end
OF_ASSUME_NONNULL_END

View file

@ -15,31 +15,34 @@
return self;
}
- (int)callWithArguments:(char **)arguments
numArguments:(size_t)numArguments
isDown:(bool)isDown
- (int)callWithArguments:(OFArray<OFString *> *)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)
@ -47,69 +50,59 @@
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;
}

View file

@ -170,21 +170,21 @@ parseword(char *&p) // parse single argument, including expressions
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;
}
@ -196,7 +196,7 @@ execute(
std::unique_ptr<char> 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
@ -204,7 +204,7 @@ execute(
loopi(MAXWORDS)
{
// collect all argument values
w[i] = "";
w[i] = @"";
if (i > numargs)
continue;
// parse and evaluate exps
@ -214,63 +214,69 @@ execute(
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<OFString *> *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
// (global) arg values so
// functions can access them
OFString *t = [OFString
stringWithFormat:
@"arg%d", i];
alias(t, @(w[i]));
}
stringWithFormat:@"arg%d",
i];
alias(t, w[i]);
}
// create new string here because alias
// could rebind itself
@ -279,7 +285,6 @@ execute(
break;
}
}
loopj(numargs) gp()->deallocstr(w[j]);
}
return val;