Be more tolerant of invalid arguments
FossilOrigin-Name: d2f07d884a4f4319ff687e085c3233e210ee05b46a2675ecd757a261e6f19e6e
This commit is contained in:
parent
f1968ce5af
commit
38747afbb5
12 changed files with 112 additions and 88 deletions
|
@ -1,4 +1,5 @@
|
||||||
#import "Command.h"
|
#import "Command.h"
|
||||||
|
#import "OFString+Cube.h"
|
||||||
|
|
||||||
#include <cube.h>
|
#include <cube.h>
|
||||||
|
|
||||||
|
@ -38,34 +39,34 @@ padArguments(OFArray<OFString *> *arguments, size_t count)
|
||||||
if (isDown) {
|
if (isDown) {
|
||||||
arguments = padArguments(arguments, 2);
|
arguments = padArguments(arguments, 2);
|
||||||
((void(__cdecl *)(int))_function)(
|
((void(__cdecl *)(int))_function)(
|
||||||
[arguments[1] intValueWithBase:0]);
|
[arguments[1] cube_intValueWithBase:0]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ARG_2INT:
|
case ARG_2INT:
|
||||||
if (isDown) {
|
if (isDown) {
|
||||||
arguments = padArguments(arguments, 3);
|
arguments = padArguments(arguments, 3);
|
||||||
((void(__cdecl *)(int, int))_function)(
|
((void(__cdecl *)(int, int))_function)(
|
||||||
[arguments[1] intValueWithBase:0],
|
[arguments[1] cube_intValueWithBase:0],
|
||||||
[arguments[2] intValueWithBase:0]);
|
[arguments[2] cube_intValueWithBase:0]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ARG_3INT:
|
case ARG_3INT:
|
||||||
if (isDown) {
|
if (isDown) {
|
||||||
arguments = padArguments(arguments, 4);
|
arguments = padArguments(arguments, 4);
|
||||||
((void(__cdecl *)(int, int, int))_function)(
|
((void(__cdecl *)(int, int, int))_function)(
|
||||||
[arguments[1] intValueWithBase:0],
|
[arguments[1] cube_intValueWithBase:0],
|
||||||
[arguments[2] intValueWithBase:0],
|
[arguments[2] cube_intValueWithBase:0],
|
||||||
[arguments[3] intValueWithBase:0]);
|
[arguments[3] cube_intValueWithBase:0]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ARG_4INT:
|
case ARG_4INT:
|
||||||
if (isDown) {
|
if (isDown) {
|
||||||
arguments = padArguments(arguments, 5);
|
arguments = padArguments(arguments, 5);
|
||||||
((void(__cdecl *)(int, int, int, int))_function)(
|
((void(__cdecl *)(int, int, int, int))_function)(
|
||||||
[arguments[1] intValueWithBase:0],
|
[arguments[1] cube_intValueWithBase:0],
|
||||||
[arguments[2] intValueWithBase:0],
|
[arguments[2] cube_intValueWithBase:0],
|
||||||
[arguments[3] intValueWithBase:0],
|
[arguments[3] cube_intValueWithBase:0],
|
||||||
[arguments[4] intValueWithBase:0]);
|
[arguments[4] cube_intValueWithBase:0]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ARG_NONE:
|
case ARG_NONE:
|
||||||
|
|
|
@ -23,12 +23,17 @@
|
||||||
x = _text.intValue;
|
x = _text.intValue;
|
||||||
} @catch (OFInvalidFormatException *e) {
|
} @catch (OFInvalidFormatException *e) {
|
||||||
x = 0;
|
x = 0;
|
||||||
|
} @catch (OFOutOfRangeException *e) {
|
||||||
|
x = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@try {
|
@
|
||||||
|
try {
|
||||||
y = otherItem.text.intValue;
|
y = otherItem.text.intValue;
|
||||||
} @catch (OFInvalidFormatException *e) {
|
} @catch (OFInvalidFormatException *e) {
|
||||||
y = 0;
|
y = 0;
|
||||||
|
} @catch (OFOutOfRangeException *e) {
|
||||||
|
y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x > y)
|
if (x > y)
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "cube.h"
|
#include "cube.h"
|
||||||
|
|
||||||
#import "DynamicEntity.h"
|
#import "DynamicEntity.h"
|
||||||
|
#import "OFString+Cube.h"
|
||||||
|
|
||||||
int nextmode = 0; // nextmode becomes gamemode after next map load
|
int nextmode = 0; // nextmode becomes gamemode after next map load
|
||||||
VAR(gamemode, 1, 0, 0);
|
VAR(gamemode, 1, 0, 0);
|
||||||
|
@ -238,7 +239,7 @@ static OFString *sleepcmd = nil;
|
||||||
void
|
void
|
||||||
sleepf(OFString *msec, OFString *cmd)
|
sleepf(OFString *msec, OFString *cmd)
|
||||||
{
|
{
|
||||||
sleepwait = msec.intValue + lastmillis;
|
sleepwait = msec.cube_intValue + lastmillis;
|
||||||
sleepcmd = cmd;
|
sleepcmd = cmd;
|
||||||
}
|
}
|
||||||
COMMANDN(sleep, sleepf, ARG_2STR)
|
COMMANDN(sleep, sleepf, ARG_2STR)
|
||||||
|
|
116
src/commands.mm
116
src/commands.mm
|
@ -8,6 +8,7 @@
|
||||||
#import "Alias.h"
|
#import "Alias.h"
|
||||||
#import "Command.h"
|
#import "Command.h"
|
||||||
#import "Identifier.h"
|
#import "Identifier.h"
|
||||||
|
#import "OFString+Cube.h"
|
||||||
#import "Variable.h"
|
#import "Variable.h"
|
||||||
|
|
||||||
// contains ALL vars/commands/aliases
|
// contains ALL vars/commands/aliases
|
||||||
|
@ -181,6 +182,54 @@ lookup(OFString *n) // find value of ident referenced with $ in exp
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
executeIdentifier(__kindof Identifier *identifier,
|
||||||
|
OFArray<OFString *> *arguments, bool isDown)
|
||||||
|
{
|
||||||
|
if (identifier == nil) {
|
||||||
|
@try {
|
||||||
|
return [arguments[0] intValueWithBase:0];
|
||||||
|
} @catch (OFInvalidFormatException *e) {
|
||||||
|
conoutf(@"unknown command: %@", arguments[0]);
|
||||||
|
return 0;
|
||||||
|
} @catch (OFOutOfRangeException *e) {
|
||||||
|
conoutf(@"invalid value: %@", arguments[0]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([identifier isKindOfClass:Command.class])
|
||||||
|
// game defined commands use very ad-hoc function signature,
|
||||||
|
// and just call it
|
||||||
|
return [identifier callWithArguments:arguments isDown:isDown];
|
||||||
|
|
||||||
|
if ([identifier isKindOfClass:Variable.class]) {
|
||||||
|
if (!isDown)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// game defined variables
|
||||||
|
if (arguments.count < 2 || arguments[1].length == 0)
|
||||||
|
[identifier printValue];
|
||||||
|
else
|
||||||
|
[identifier
|
||||||
|
setValue:[arguments[1] cube_intValueWithBase:0]];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([identifier isKindOfClass:Alias.class]) {
|
||||||
|
// alias, also used as functions and (global) variables
|
||||||
|
for (int i = 1; i < arguments.count; i++) {
|
||||||
|
// set any arguments as (global) arg values so
|
||||||
|
// functions can access them
|
||||||
|
OFString *t = [OFString stringWithFormat:@"arg%d", i];
|
||||||
|
alias(t, arguments[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return execute([identifier action], isDown);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// all evaluation happens here, recursively
|
// all evaluation happens here, recursively
|
||||||
int
|
int
|
||||||
execute(OFString *string, bool isDown)
|
execute(OFString *string, bool isDown)
|
||||||
|
@ -230,55 +279,8 @@ execute(OFString *string, bool isDown)
|
||||||
if (c.length == 0)
|
if (c.length == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
__kindof Identifier *identifier = identifiers[c];
|
val = executeIdentifier(identifiers[c],
|
||||||
if (identifier == nil) {
|
[OFArray arrayWithObjects:w count:numargs], isDown);
|
||||||
@try {
|
|
||||||
val = [c intValueWithBase:0];
|
|
||||||
} @catch (OFInvalidFormatException *e) {
|
|
||||||
conoutf(@"unknown command: %@", 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];
|
|
||||||
val = [identifier
|
|
||||||
callWithArguments:arguments
|
|
||||||
isDown:isDown];
|
|
||||||
} else if ([identifier
|
|
||||||
isKindOfClass:Variable.class]) {
|
|
||||||
// game defined variables
|
|
||||||
if (isDown) {
|
|
||||||
if (w[1].length == 0)
|
|
||||||
[identifier printValue];
|
|
||||||
else
|
|
||||||
[identifier
|
|
||||||
setValue:
|
|
||||||
[w[1]
|
|
||||||
intValueWithBase:
|
|
||||||
0]];
|
|
||||||
}
|
|
||||||
} else if ([identifier
|
|
||||||
isKindOfClass:Alias.class]) {
|
|
||||||
// alias, also used as functions and
|
|
||||||
// (global) variables
|
|
||||||
for (int i = 1; i < numargs; i++) {
|
|
||||||
// set any arguments as
|
|
||||||
// (global) arg values so
|
|
||||||
// functions can access them
|
|
||||||
OFString *t = [OFString
|
|
||||||
stringWithFormat:@"arg%d",
|
|
||||||
i];
|
|
||||||
alias(t, w[i]);
|
|
||||||
}
|
|
||||||
val = execute(
|
|
||||||
[identifier action], isDown);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
|
@ -378,10 +380,9 @@ writecfg()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[stream writeString:
|
[stream writeString:@"// automatically written on exit, do not modify\n"
|
||||||
@"// automatically written on exit, do not modify\n"
|
@"// delete this file to have defaults.cfg "
|
||||||
@"// delete this file to have defaults.cfg overwrite these "
|
@"overwrite these settings\n"
|
||||||
@"settings\n"
|
|
||||||
@"// modify settings in game, or put settings in "
|
@"// modify settings in game, or put settings in "
|
||||||
@"autoexec.cfg to override anything\n"
|
@"autoexec.cfg to override anything\n"
|
||||||
@"\n"];
|
@"\n"];
|
||||||
|
@ -418,8 +419,8 @@ writecfg()
|
||||||
COMMAND(writecfg, ARG_NONE)
|
COMMAND(writecfg, ARG_NONE)
|
||||||
|
|
||||||
// below the commands that implement a small imperative language. thanks to the
|
// below the commands that implement a small imperative language. thanks to the
|
||||||
// semantics of
|
// semantics of () and [] expressions, any control construct can be defined
|
||||||
// () and [] expressions, any control construct can be defined trivially.
|
// trivially.
|
||||||
|
|
||||||
void
|
void
|
||||||
intset(OFString *name, int v)
|
intset(OFString *name, int v)
|
||||||
|
@ -439,7 +440,7 @@ void
|
||||||
loopa(OFString *times, OFString *body)
|
loopa(OFString *times, OFString *body)
|
||||||
{
|
{
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
int t = times.intValue;
|
int t = times.cube_intValue;
|
||||||
|
|
||||||
loopi(t)
|
loopi(t)
|
||||||
{
|
{
|
||||||
|
@ -497,10 +498,9 @@ void
|
||||||
at(OFString *s_, OFString *pos)
|
at(OFString *s_, OFString *pos)
|
||||||
{
|
{
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
int n = pos.intValue;
|
int n = pos.cube_intValue;
|
||||||
std::unique_ptr<char> copy(strdup(s_.UTF8String));
|
std::unique_ptr<char> copy(strdup(s_.UTF8String));
|
||||||
char *s = copy.get();
|
char *s = copy.get();
|
||||||
|
|
||||||
loopi(n) s += strspn(s += strcspn(s, " \0"), " ");
|
loopi(n) s += strspn(s += strcspn(s, " \0"), " ");
|
||||||
s[strcspn(s, " \0")] = 0;
|
s[strcspn(s, " \0")] = 0;
|
||||||
concat(@(s));
|
concat(@(s));
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#import "KeyMapping.h"
|
#import "KeyMapping.h"
|
||||||
|
#import "OFString+Cube.h"
|
||||||
|
|
||||||
struct cline {
|
struct cline {
|
||||||
char *cref;
|
char *cref;
|
||||||
|
@ -106,8 +107,8 @@ keymap(OFString *code, OFString *key, OFString *action)
|
||||||
if (keyMappings == nil)
|
if (keyMappings == nil)
|
||||||
keyMappings = [[OFMutableArray alloc] init];
|
keyMappings = [[OFMutableArray alloc] init];
|
||||||
|
|
||||||
KeyMapping *mapping = [[KeyMapping alloc] initWithCode:code.intValue
|
KeyMapping *mapping =
|
||||||
name:key];
|
[[KeyMapping alloc] initWithCode:code.cube_intValue name:key];
|
||||||
mapping.action = action;
|
mapping.action = action;
|
||||||
[keyMappings addObject:mapping];
|
[keyMappings addObject:mapping];
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "cube.h"
|
#include "cube.h"
|
||||||
|
|
||||||
#import "DynamicEntity.h"
|
#import "DynamicEntity.h"
|
||||||
|
#import "OFString+Cube.h"
|
||||||
|
|
||||||
bool editmode = false;
|
bool editmode = false;
|
||||||
|
|
||||||
|
@ -605,8 +606,8 @@ newent(OFString *what, OFString *a1, OFString *a2, OFString *a3, OFString *a4)
|
||||||
EDITSEL;
|
EDITSEL;
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
newentity(sel.x, sel.y, (int)player1.o.z, what,
|
newentity(sel.x, sel.y, (int)player1.o.z, what,
|
||||||
[a1 intValueWithBase:0], [a2 intValueWithBase:0],
|
[a1 cube_intValueWithBase:0], [a2 cube_intValueWithBase:0],
|
||||||
[a3 intValueWithBase:0], [a4 intValueWithBase:0]);
|
[a3 cube_intValueWithBase:0], [a4 cube_intValueWithBase:0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ executable('client',
|
||||||
'MapModelInfo.m',
|
'MapModelInfo.m',
|
||||||
'Menu.m',
|
'Menu.m',
|
||||||
'MenuItem.m',
|
'MenuItem.m',
|
||||||
|
'OFString+Cube.mm',
|
||||||
'Projectile.m',
|
'Projectile.m',
|
||||||
'ServerInfo.mm',
|
'ServerInfo.mm',
|
||||||
'Variable.mm',
|
'Variable.mm',
|
||||||
|
|
|
@ -206,6 +206,9 @@ loadsky(OFString *basename)
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
static OFString *lastsky = @"";
|
static OFString *lastsky = @"";
|
||||||
|
|
||||||
|
basename = [basename stringByReplacingOccurrencesOfString:@"\\"
|
||||||
|
withString:@"/"];
|
||||||
|
|
||||||
if ([lastsky isEqual:basename])
|
if ([lastsky isEqual:basename])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "cube.h"
|
#include "cube.h"
|
||||||
|
|
||||||
#import "DynamicEntity.h"
|
#import "DynamicEntity.h"
|
||||||
|
#import "OFString+Cube.h"
|
||||||
|
|
||||||
#ifdef DARWIN
|
#ifdef DARWIN
|
||||||
# define GL_COMBINE_EXT GL_COMBINE_ARB
|
# define GL_COMBINE_EXT GL_COMBINE_ARB
|
||||||
|
@ -197,11 +198,15 @@ void
|
||||||
texture(OFString *aframe, OFString *name)
|
texture(OFString *aframe, OFString *name)
|
||||||
{
|
{
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
int num = curtexnum++, frame = aframe.intValue;
|
int num = curtexnum++, frame = aframe.cube_intValue;
|
||||||
|
|
||||||
if (num < 0 || num >= 256 || frame < 0 || frame >= MAXFRAMES)
|
if (num < 0 || num >= 256 || frame < 0 || frame >= MAXFRAMES)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mapping[num][frame] = 1;
|
mapping[num][frame] = 1;
|
||||||
mapname[num][frame] = name;
|
mapname[num][frame] =
|
||||||
|
[name stringByReplacingOccurrencesOfString:@"\\"
|
||||||
|
withString:@"/"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
COMMAND(texture, ARG_2STR)
|
COMMAND(texture, ARG_2STR)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#import "DynamicEntity.h"
|
#import "DynamicEntity.h"
|
||||||
#import "MD2.h"
|
#import "MD2.h"
|
||||||
#import "MapModelInfo.h"
|
#import "MapModelInfo.h"
|
||||||
|
#import "OFString+Cube.h"
|
||||||
|
|
||||||
static OFMutableDictionary<OFString *, MD2 *> *mdllookup = nil;
|
static OFMutableDictionary<OFString *, MD2 *> *mdllookup = nil;
|
||||||
static OFMutableArray<MD2 *> *mapmodels = nil;
|
static OFMutableArray<MD2 *> *mapmodels = nil;
|
||||||
|
@ -67,11 +68,12 @@ void
|
||||||
mapmodel(
|
mapmodel(
|
||||||
OFString *rad, OFString *h, OFString *zoff, OFString *snap, OFString *name)
|
OFString *rad, OFString *h, OFString *zoff, OFString *snap, OFString *name)
|
||||||
{
|
{
|
||||||
MD2 *m = loadmodel(name);
|
MD2 *m = loadmodel([name stringByReplacingOccurrencesOfString:@"\\"
|
||||||
m.mmi = [[MapModelInfo alloc] initWithRad:rad.intValue
|
withString:@"/"]);
|
||||||
h:h.intValue
|
m.mmi = [[MapModelInfo alloc] initWithRad:rad.cube_intValue
|
||||||
zoff:zoff.intValue
|
h:h.cube_intValue
|
||||||
snap:snap.intValue
|
zoff:zoff.cube_intValue
|
||||||
|
snap:snap.cube_intValue
|
||||||
name:m.loadname];
|
name:m.loadname];
|
||||||
|
|
||||||
if (mapmodels == nil)
|
if (mapmodels == nil)
|
||||||
|
|
|
@ -88,6 +88,8 @@ music(OFString *name)
|
||||||
stopsound();
|
stopsound();
|
||||||
if (soundvol && musicvol) {
|
if (soundvol && musicvol) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
name = [name stringByReplacingOccurrencesOfString:@"\\"
|
||||||
|
withString:@"/"];
|
||||||
OFString *path =
|
OFString *path =
|
||||||
[OFString stringWithFormat:@"packages/%@", name];
|
[OFString stringWithFormat:@"packages/%@", name];
|
||||||
OFIRI *IRI = [Cube.sharedInstance.gameDataIRI
|
OFIRI *IRI = [Cube.sharedInstance.gameDataIRI
|
||||||
|
@ -148,7 +150,8 @@ registersound(OFString *name)
|
||||||
if (snames == nil)
|
if (snames == nil)
|
||||||
snames = [[OFMutableArray alloc] init];
|
snames = [[OFMutableArray alloc] init];
|
||||||
|
|
||||||
[snames addObject:name];
|
[snames addObject:[name stringByReplacingOccurrencesOfString:@"\\"
|
||||||
|
withString:@"/"]];
|
||||||
samples.add(NULL);
|
samples.add(NULL);
|
||||||
|
|
||||||
return samples.length() - 1;
|
return samples.length() - 1;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "cube.h"
|
#include "cube.h"
|
||||||
|
|
||||||
#import "DynamicEntity.h"
|
#import "DynamicEntity.h"
|
||||||
|
#import "OFString+Cube.h"
|
||||||
#import "Projectile.h"
|
#import "Projectile.h"
|
||||||
|
|
||||||
static const int MONSTERDAMAGEFACTOR = 4;
|
static const int MONSTERDAMAGEFACTOR = 4;
|
||||||
|
@ -63,9 +64,9 @@ reloadtime(int gun)
|
||||||
void
|
void
|
||||||
weapon(OFString *a1, OFString *a2, OFString *a3)
|
weapon(OFString *a1, OFString *a2, OFString *a3)
|
||||||
{
|
{
|
||||||
selectgun((a1.length > 0 ? a1.intValue : -1),
|
selectgun((a1.length > 0 ? a1.cube_intValue : -1),
|
||||||
(a2.length > 0 ? a2.intValue : -1),
|
(a2.length > 0 ? a2.cube_intValue : -1),
|
||||||
(a3.length > 0 ? a3.intValue : -1));
|
(a3.length > 0 ? a3.cube_intValue : -1));
|
||||||
}
|
}
|
||||||
COMMAND(weapon, ARG_3STR)
|
COMMAND(weapon, ARG_3STR)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue