Index: src/commands.mm ================================================================== --- src/commands.mm +++ src/commands.mm @@ -8,23 +8,10 @@ #import "Alias.h" #import "Command.h" #import "Identifier.h" #import "Variable.h" -void -itoa(char *s, int i) -{ - sprintf_s(s)("%d", i); -} - -char * -exchangestr(char *o, const char *n) -{ - free(o); - return strdup(n); -} - // contains ALL vars/commands/aliases static OFMutableDictionary *identifiers; void alias(OFString *name, OFString *action) @@ -111,12 +98,13 @@ identifiers[name] = command; return false; } +// parse any nested set of () or [] char * -parseexp(char *&p, int right) // parse any nested set of () or [] +parseexp(char *&p, int right) { int left = *p++; char *word = p; for (int brak = 1; brak;) { int c = *p++; @@ -132,22 +120,27 @@ return NULL; } } char *s = strndup(word, p - word - 1); if (left == '(') { - string t; - // evaluate () exps directly, and substitute result @autoreleasepool { - itoa(t, execute(@(s))); + OFString *t; + @try { + t = [OFString + stringWithFormat:@"%d", execute(@(s))]; + } @finally { + free(s); + } + s = strdup(t.UTF8String); } - s = exchangestr(s, t); } return s; } +// parse single argument, including expressions char * -parseword(char *&p) // parse single argument, including expressions +parseword(char *&p) { p += strspn(p, " \t\r"); if (p[0] == '/' && p[1] == '/') p += strcspn(p, "\n\0"); if (*p == '\"') { @@ -186,13 +179,13 @@ conoutf(@"unknown alias lookup: %@", [n substringFromIndex:1]); return n; } +// all evaluation happens here, recursively int -execute( - OFString *string, bool isdown) // all evaluation happens here, recursively +execute(OFString *string, bool isDown) { @autoreleasepool { std::unique_ptr copy(strdup(string.UTF8String)); char *p = copy.get(); const int MAXWORDS = 25; // limit, remove @@ -209,17 +202,21 @@ continue; // parse and evaluate exps char *s = parseword(p); if (!s) { numargs = i; - s = ""; + s = strdup(""); } - if (*s == '$') - // substitute variables - w[i] = lookup(@(s)); - else - w[i] = @(s); + @try { + if (*s == '$') + // substitute variables + w[i] = lookup(@(s)); + else + w[i] = @(s); + } @finally { + free(s); + } } p += strcspn(p, ";\n\0"); // more statements if this isn't the end of the string cont = *p++ != 0; @@ -248,16 +245,16 @@ [[OFArray alloc] initWithObjects:w count:numargs]; val = [identifier callWithArguments:arguments - isDown:isdown]; + isDown:isDown]; } else if ([identifier isKindOfClass:[Variable class]]) { // game defined variables - if (isdown) { + if (isDown) { if (w[1].length == 0) [identifier printValue]; else [identifier setValue: @@ -276,14 +273,12 @@ 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); + [identifier action], isDown); break; } } }