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 - (instancetype)initWithName:(OFString *)name
function:(void (*)())function function:(void (*)())function
argumentsTypes:(int)argumentsTypes; argumentsTypes:(int)argumentsTypes;
- (int)callWithArguments:(char *_Nonnull *_Nonnull)arguments - (int)callWithArguments:(OFArray<OFString *> *)arguments isDown:(bool)isDown;
numArguments:(size_t)numArguments
isDown:(bool)isDown;
@end @end
OF_ASSUME_NONNULL_END OF_ASSUME_NONNULL_END

View file

@ -15,31 +15,34 @@
return self; return self;
} }
- (int)callWithArguments:(char **)arguments - (int)callWithArguments:(OFArray<OFString *> *)arguments isDown:(bool)isDown
numArguments:(size_t)numArguments
isDown:(bool)isDown
{ {
switch (_argumentsTypes) { switch (_argumentsTypes) {
case ARG_1INT: case ARG_1INT:
if (isDown) if (isDown)
((void(__cdecl *)(int))_function)(ATOI(arguments[1])); ((void(__cdecl *)(int))_function)(
(int)[arguments[1] longLongValueWithBase:0]);
break; break;
case ARG_2INT: case ARG_2INT:
if (isDown) if (isDown)
((void(__cdecl *)(int, int))_function)( ((void(__cdecl *)(int, int))_function)(
ATOI(arguments[1]), ATOI(arguments[2])); (int)[arguments[1] longLongValueWithBase:0],
(int)[arguments[2] longLongValueWithBase:0]);
break; break;
case ARG_3INT: case ARG_3INT:
if (isDown) if (isDown)
((void(__cdecl *)(int, int, int))_function)( ((void(__cdecl *)(int, int, int))_function)(
ATOI(arguments[1]), ATOI(arguments[2]), (int)[arguments[1] longLongValueWithBase:0],
ATOI(arguments[3])); (int)[arguments[2] longLongValueWithBase:0],
(int)[arguments[3] longLongValueWithBase:0]);
break; break;
case ARG_4INT: case ARG_4INT:
if (isDown) if (isDown)
((void(__cdecl *)(int, int, int, int))_function)( ((void(__cdecl *)(int, int, int, int))_function)(
ATOI(arguments[1]), ATOI(arguments[2]), (int)[arguments[1] longLongValueWithBase:0],
ATOI(arguments[3]), ATOI(arguments[4])); (int)[arguments[2] longLongValueWithBase:0],
(int)[arguments[3] longLongValueWithBase:0],
(int)[arguments[4] longLongValueWithBase:0]);
break; break;
case ARG_NONE: case ARG_NONE:
if (isDown) if (isDown)
@ -47,69 +50,59 @@
break; break;
case ARG_1STR: case ARG_1STR:
if (isDown) if (isDown)
((void(__cdecl *)(OFString *))_function)( ((void(__cdecl *)(OFString *))_function)(arguments[1]);
@(arguments[1]));
break; break;
case ARG_2STR: case ARG_2STR:
if (isDown) if (isDown)
((void(__cdecl *)(OFString *, OFString *))_function)( ((void(__cdecl *)(OFString *, OFString *))_function)(
@(arguments[1]), @(arguments[2])); arguments[1], arguments[2]);
break; break;
case ARG_3STR: case ARG_3STR:
if (isDown) if (isDown)
((void(__cdecl *)( ((void(__cdecl *)(
OFString *, OFString *, OFString *))_function)( OFString *, OFString *, OFString *))_function)(
@(arguments[1]), @(arguments[2]), @(arguments[3])); arguments[1], arguments[2], arguments[3]);
break; break;
case ARG_5STR: case ARG_5STR:
if (isDown) if (isDown)
((void(__cdecl *)(OFString *, OFString *, OFString *, ((void(__cdecl *)(OFString *, OFString *, OFString *,
OFString *, OFString *))_function)(@(arguments[1]), OFString *, OFString *))_function)(arguments[1],
@(arguments[2]), @(arguments[3]), @(arguments[4]), arguments[2], arguments[3], arguments[4],
@(arguments[5])); arguments[5]);
break; break;
case ARG_DOWN: case ARG_DOWN:
((void(__cdecl *)(bool))_function)(isDown); ((void(__cdecl *)(bool))_function)(isDown);
break; break;
case ARG_DWN1: case ARG_DWN1:
((void(__cdecl *)(bool, OFString *))_function)( ((void(__cdecl *)(bool, OFString *))_function)(
isDown, @(arguments[1])); isDown, arguments[1]);
break; break;
case ARG_1EXP: case ARG_1EXP:
if (isDown) if (isDown)
return ((int(__cdecl *)(int))_function)( return ((int(__cdecl *)(int))_function)(
execute(@(arguments[1]))); execute(arguments[1]));
break; break;
case ARG_2EXP: case ARG_2EXP:
if (isDown) if (isDown)
return ((int(__cdecl *)(int, int))_function)( return ((int(__cdecl *)(int, int))_function)(
execute(@(arguments[1])), execute(@(arguments[2]))); execute(arguments[1]), execute(arguments[2]));
break; break;
case ARG_1EST: case ARG_1EST:
if (isDown) if (isDown)
return ((int(__cdecl *)(OFString *))_function)( return ((int(__cdecl *)(OFString *))_function)(
@(arguments[1])); arguments[1]);
break; break;
case ARG_2EST: case ARG_2EST:
if (isDown) if (isDown)
return ( return ((int(__cdecl *)(OFString *,
(int(__cdecl *)(OFString *, OFString *))_function)( OFString *))_function)(arguments[1], arguments[2]);
@(arguments[1]), @(arguments[2]));
break; break;
case ARG_VARI: case ARG_VARI:
if (isDown) { if (isDown)
// limit, remove // limit, remove
string r; ((void(__cdecl *)(OFString *))_function)([[arguments
r[0] = 0; objectsInRange:OFMakeRange(1, arguments.count - 1)]
for (int i = 1; i < numArguments; i++) { componentsJoinedByString:@" "]);
// 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));
}
break; break;
} }

View file

@ -170,21 +170,21 @@ parseword(char *&p) // parse single argument, including expressions
return newstring(word, p - word); return newstring(word, p - word);
} }
char * OFString *
lookup(char *n) // find value of ident referenced with $ in exp lookup(OFString *n) // find value of ident referenced with $ in exp
{ {
@autoreleasepool { @autoreleasepool {
__kindof Identifier *identifier = identifiers[@(n + 1)]; __kindof Identifier *identifier =
identifiers[[n substringFromIndex:1]];
if ([identifier isKindOfClass:[Variable class]]) { if ([identifier isKindOfClass:[Variable class]]) {
string t; return [OFString
itoa(t, *[identifier storage]); stringWithFormat:@"%d", *[identifier storage]];
return exchangestr(n, t);
} else if ([identifier isKindOfClass:[Alias class]]) } 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; return n;
} }
@ -196,7 +196,7 @@ execute(
std::unique_ptr<char> copy(strdup(string.UTF8String)); std::unique_ptr<char> copy(strdup(string.UTF8String));
char *p = copy.get(); char *p = copy.get();
const int MAXWORDS = 25; // limit, remove const int MAXWORDS = 25; // limit, remove
char *w[MAXWORDS]; OFString *w[MAXWORDS];
int val = 0; int val = 0;
for (bool cont = true; cont;) { for (bool cont = true; cont;) {
// for each ; seperated statement // for each ; seperated statement
@ -204,7 +204,7 @@ execute(
loopi(MAXWORDS) loopi(MAXWORDS)
{ {
// collect all argument values // collect all argument values
w[i] = ""; w[i] = @"";
if (i > numargs) if (i > numargs)
continue; continue;
// parse and evaluate exps // parse and evaluate exps
@ -214,63 +214,69 @@ execute(
s = ""; s = "";
} }
if (*s == '$') if (*s == '$')
s = lookup(s); // substitute variables // substitute variables
w[i] = s; w[i] = lookup(@(s));
else
w[i] = @(s);
} }
p += strcspn(p, ";\n\0"); p += strcspn(p, ";\n\0");
// more statements if this isn't the end of the string // more statements if this isn't the end of the string
cont = *p++ != 0; cont = *p++ != 0;
char *c = w[0]; OFString *c = w[0];
// strip irc-style command prefix // strip irc-style command prefix
if (*c == '/') if ([c hasPrefix:@"/"])
c++; c = [c substringFromIndex:1];
// empty statement // empty statement
if (!*c) if (c.length == 0)
continue; continue;
__kindof Identifier *identifier = identifiers[@(c)]; __kindof Identifier *identifier = identifiers[c];
if (identifier == nil) { if (identifier == nil) {
val = ATOI(c); @try {
if (!val && *c != '0') val = (int)[c longLongValueWithBase:0];
} @catch (OFInvalidFormatException *e) {
conoutf(@"unknown command: %s", c); conoutf(@"unknown command: %s", c);
}
} else { } else {
if ([identifier if ([identifier
isKindOfClass:[Command class]]) { isKindOfClass:[Command class]]) {
// game defined commands use very // game defined commands use very
// ad-hoc function signature, and just // ad-hoc function signature, and just
// call it // call it
OFArray<OFString *> *arguments =
[[OFArray alloc]
initWithObjects:w
count:numargs + 1];
val = [identifier val = [identifier
callWithArguments:w callWithArguments:arguments
numArguments:numargs
isDown:isdown]; isDown:isdown];
} else if ([identifier } else if ([identifier
isKindOfClass:[Variable isKindOfClass:[Variable
class]]) { class]]) {
// game defined variables // game defined variables
if (isdown) { if (isdown) {
if (!w[1][0]) if (w[1].length == 0)
[identifier printValue]; [identifier printValue];
else else
[identifier [identifier
setValue:ATOI( setValue:
w[1])]; (int)[w[1]
longLongValueWithBase:
0]];
} }
} else if ([identifier } else if ([identifier
isKindOfClass:[Alias class]]) { isKindOfClass:[Alias class]]) {
// alias, also used as functions and // alias, also used as functions and
// (global) variables // (global) variables
for (int i = 1; i < numargs; i++) { for (int i = 1; i < numargs; i++) {
@autoreleasepool { // set any arguments as
// set any arguments as // (global) arg values so
// (global) arg values // functions can access them
// so functions can OFString *t = [OFString
// access them stringWithFormat:@"arg%d",
OFString *t = [OFString i];
stringWithFormat: alias(t, w[i]);
@"arg%d", i];
alias(t, @(w[i]));
}
} }
// create new string here because alias // create new string here because alias
// could rebind itself // could rebind itself
@ -279,7 +285,6 @@ execute(
break; break;
} }
} }
loopj(numargs) gp()->deallocstr(w[j]);
} }
return val; return val;