add early string replacement and alias lookup to cubescript
replace tokens starting with @ during scanning/sizing-up of []-blocks @word look up word as in $word @(...) evaluate braces @[...] evaluate braces and look up result @"..." parse quotes in nested []-blocks, use multiple @ to determine time of replacement (for example, @@@word is replaced when found inside three nested braces) in regular $-lookup, $[...] now evaluates the braces before lookup
This commit is contained in:
@@ -16,10 +16,10 @@ const joinservermenu [
|
||||
tempalias __ingamemenu_1 [
|
||||
push t (player1 team)
|
||||
menuitemtextinput "Nickname: " "result $curname" [ name $arg1 ]
|
||||
menuitem "Change weapon\i\3" [ showmenu Weapons ] [ __ingamemenu_showmodel 0 ]
|
||||
menuitem "Change player skin\i\3" (concat showmenu (at [CLA RVSF] (&b $t 1))) [ __ingamemenu_showmodel 1 ]
|
||||
menuitem "Change to the enemy team" changeteam [ __ingamemenu_showmodel 0 ]
|
||||
menuitem (concat Change to (at "spectate active" (> $t 1)) mode) spectate
|
||||
menuitem "Change weapon\i\3" [ showmenu Weapons ] [ __ingamemenu_showmodel 0 ]
|
||||
menuitem "Change player skin\i\3" [showmenu @(at [CLA RVSF] (&b $t 1))] [ __ingamemenu_showmodel 1 ]
|
||||
menuitem "Change to the enemy team" changeteam [ __ingamemenu_showmodel 0 ]
|
||||
menuitem [Change to @(at "spectate active" (> $t 1)) mode] spectate
|
||||
pop t
|
||||
]
|
||||
|
||||
@@ -35,7 +35,7 @@ tempalias __ingamemenu_2 [
|
||||
|
||||
const __ingamemenu_showmodel [
|
||||
if (&& (< (player1 team) 4) $arg1) [
|
||||
menumdl (curmenu) (concatword "playermodels/" (at [CLA RVSF CLA RVSF] (player1 team)) "/0" (+ 1 (player1 skin))) idle 15 3
|
||||
menumdl (curmenu) [playermodels/@(at [CLA RVSF CLA RVSF] (player1 team))/0@(+ 1 (player1 skin))] idle 15 3
|
||||
] [
|
||||
menumdl (curmenu)
|
||||
]
|
||||
@@ -180,7 +180,6 @@ menuitem "\f2\t\t [ Admin connect ]\t\t" [ connectadmin $acc1 $acc2 $acc3 ]
|
||||
|
||||
//// Main > Multiplayer > server > serverbrowser help ////
|
||||
|
||||
const __getfavattr [ push n (concatword sbfavourite_ $arg1 _ $arg2) ; n = $$n ; result (pop n) ]
|
||||
newmenu [serverbrowser help]
|
||||
menuinitselection 1
|
||||
menuinit [
|
||||
@@ -208,7 +207,7 @@ menuinit [
|
||||
menuitem "Keys to add/remove servers from categories:" -1
|
||||
looplisti (listfavcats) fav [
|
||||
if (< $i 10) [
|
||||
menuitem (concatword (+ $i 1) ": Toggle category " (__getfavattr $fav desc) " <\fs" (__getfavattr $fav tag) "\fr>") -1
|
||||
menuitem [@(+ $i 1): Toggle category @[sbfavourite_@[fav]_desc] @"<\fs"@[sbfavourite_@[fav]_tag]@"\fr>"] -1
|
||||
]
|
||||
]
|
||||
]
|
||||
@@ -237,9 +236,9 @@ menuinit [
|
||||
resetcurmenu
|
||||
looplisti (listfavcats) fav [
|
||||
if (< $i 10) [
|
||||
menuitem (concatword (+ 1 (mod $i 10)) ": " (__getfavattr $fav desc) " <\fs" (__getfavattr $fav tag) "\fr>") (concatword "__curfav = " $i " ; showmenu [edit favourites category]")
|
||||
menuitem [@(+ 1 (mod $i 10)): @[sbfavourite_@[fav]_desc] @"<\fs"@[sbfavourite_@[fav]_tag]@"\fr>"] [__curfav = @i; showmenu [edit favourites category]]
|
||||
] [
|
||||
menuitem (concatword (__getfavattr $fav desc) " <\fs" (__getfavattr $fav tag) "\fr>") (concatword "__curfav = " $i " ; showmenu [edit favourites category]")
|
||||
menuitem [@[sbfavourite_@[fav]_desc] @"<\fs"@[sbfavourite_@[fav]_tag]@"\fr>"] [__curfav = @i; showmenu [edit favourites category]]
|
||||
]
|
||||
]
|
||||
]
|
||||
@@ -251,23 +250,23 @@ menuinit [
|
||||
resetcurmenu
|
||||
push fav (at (listfavcats) $__curfav)
|
||||
push n (+ 1 $__curfav)
|
||||
menuitem (concatword "Category #" $n ", name: \f2" $fav) -1
|
||||
menuitem [Category #@n@", name: \f2"@fav] -1
|
||||
menuitem "" -1
|
||||
menuitemtextinput "Tag: " (concatword "escapenoquotes $" sbfavourite_ $fav _tag) (concatword sbfavourite_ $fav _tag " = (at (addpunct $arg1) 0)") [] 15
|
||||
menuitemtextinput "Description: " (concatword "escapenoquotes $" sbfavourite_ $fav _desc) (concatword sbfavourite_ $fav _desc " = (at (addpunct $arg1) 0)") [] 45
|
||||
menuitemtextinput "Tag: " [escapenoquotes $sbfavourite_@[fav]_tag] [sbfavourite_@[fav]_tag = (at (addpunct $arg1) 0)] [] 15
|
||||
menuitemtextinput "Description: " [escapenoquotes $sbfavourite_@[fav]_desc] [sbfavourite_@[fav]_desc = (at (addpunct $arg1) 0)] [] 45
|
||||
menuitem "" -1
|
||||
menuitemslider "Background red: \t" 0 100 (__getfavattr $fav red) 10 (concatword sbfavourite_ $fav _red " = $arg1") 1
|
||||
menuitemslider "Background green:\t" 0 100 (__getfavattr $fav green) 10 (concatword sbfavourite_ $fav _green " = $arg1") 1
|
||||
menuitemslider "Background blue: \t" 0 100 (__getfavattr $fav blue) 10 (concatword sbfavourite_ $fav _blue " = $arg1") 1
|
||||
menuitemslider "Background alpha:\t" 0 100 (__getfavattr $fav alpha) 10 (concatword sbfavourite_ $fav _alpha " = $arg1") 1
|
||||
menuitemslider "Background red: \t" 0 100 $[sbfavourite_@[fav]_red] 10 [sbfavourite_@[fav]_red = $arg1] 1
|
||||
menuitemslider "Background green:\t" 0 100 $[sbfavourite_@[fav]_green] 10 [sbfavourite_@[fav]_green = $arg1] 1
|
||||
menuitemslider "Background blue: \t" 0 100 $[sbfavourite_@[fav]_blue] 10 [sbfavourite_@[fav]_blue = $arg1] 1
|
||||
menuitemslider "Background alpha:\t" 0 100 $[sbfavourite_@[fav]_alpha] 10 [sbfavourite_@[fav]_alpha = $arg1] 1
|
||||
menuitem "" -1
|
||||
menuitemtextinput "Keyword list:" (concatword "result $" sbfavourite_ $fav _keys) (concatword sbfavourite_ $fav _keys " = $arg1") [] 255
|
||||
menuitemtextinput "Keyword list:" [result $sbfavourite_@[fav]_keys] [sbfavourite_@[fav]_keys = $arg1] [] 255
|
||||
menuitem "" -1
|
||||
menuitemtextinput "Weight:" (concatword "result $" sbfavourite_ $fav _weight) (concatword sbfavourite_ $fav _weight " = $arg1") [] 10
|
||||
menuitemtextinput "Weight:" [result $sbfavourite_@[fav]_weight] [sbfavourite_@[fav]_weight = $arg1] [] 10
|
||||
menuitem "" -1
|
||||
menuitemradio "" 0 1 (__getfavattr $fav ignore) ["Enable this category " "Ignore this category"] (concatword sbfavourite_ $fav _ignore " = $arg1")
|
||||
menuitemradio "" 0 1 $[sbfavourite_@[fav]_ignore] ["Enable this category " "Ignore this category"] [sbfavourite_@[fav]_ignore = $arg1]
|
||||
menuitem "" -1
|
||||
menuitem "Show servers of this category\i\3" (concat showonlyfavourites $n ";showmenu server") [ showonlyfavourites 0 ]
|
||||
menuitem "Show servers of this category\i\3" [showonlyfavourites @n ; showmenu server] [ showonlyfavourites 0 ]
|
||||
pop fav n
|
||||
]
|
||||
|
||||
|
||||
+89
-45
@@ -15,6 +15,7 @@ int loop_level = 0; // avoid bad calls of br
|
||||
hashtable<const char *, ident> *idents = NULL; // contains ALL vars/commands/aliases
|
||||
|
||||
bool persistidents = false;
|
||||
bool currentcontextisolated = false;
|
||||
|
||||
COMMANDF(persistidents, "s", (char *on)
|
||||
{
|
||||
@@ -388,13 +389,35 @@ bool addcommand(const char *name, void (*fun)(), const char *sig)
|
||||
return false;
|
||||
}
|
||||
|
||||
inline char *parsequotes(const char *&p)
|
||||
{
|
||||
const char *word = p + 1;
|
||||
do
|
||||
{
|
||||
p++;
|
||||
p += strcspn(p, "\"\n\r");
|
||||
}
|
||||
while(*p == '\"' && p[-1] == '\\'); // skip escaped quotes
|
||||
char *s = newstring(word, p - word);
|
||||
#ifndef STANDALONE
|
||||
filterrichtext(s, s, p - word);
|
||||
#endif
|
||||
if(*p=='\"') p++;
|
||||
return s;
|
||||
}
|
||||
|
||||
char *lookup(char *n, int levels);
|
||||
|
||||
char *parseexp(const char *&p, int right) // parse any nested set of () or []
|
||||
{
|
||||
vector<char> res;
|
||||
int left = *p++;
|
||||
const char *word = p;
|
||||
bool quot = false;
|
||||
char *s;
|
||||
bool quot = false, issq = left == '[';
|
||||
for(int brak = 1; brak; )
|
||||
{
|
||||
p += strcspn(p, "([\"])@");
|
||||
int c = *p++;
|
||||
if(c==left && !quot) brak++;
|
||||
else if(c=='"') quot = !quot;
|
||||
@@ -403,12 +426,45 @@ char *parseexp(const char *&p, int right) // parse any nested set of
|
||||
{
|
||||
p--;
|
||||
conoutf("missing \"%c\"", right);
|
||||
scripterr();
|
||||
flagmapconfigerror(LWW_SCRIPTERR * 4);
|
||||
return NULL;
|
||||
goto screrr;
|
||||
}
|
||||
else if(issq && c == '@' && !quot)
|
||||
{
|
||||
const char *sq = p;
|
||||
while(*p == '@') p++;
|
||||
int level = p - sq + 1;
|
||||
if(level == brak)
|
||||
{
|
||||
res.put(word, sq - word - 1);
|
||||
char *n, a = *p;
|
||||
switch(a)
|
||||
{
|
||||
case '(': n = parseexp(p, ')'); break;
|
||||
case '"': n = parsequotes(p); break;
|
||||
case '[':
|
||||
n = parseexp(p, ']');
|
||||
if(n) n = lookup(n, 1);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
const char *w = p;
|
||||
p += strcspn(p, "])@; \t\n\r");
|
||||
n = lookup(newstring(w, p - w), 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(n) res.put(n, strlen(n)), delete[] n;
|
||||
word = p;
|
||||
}
|
||||
else if(level > brak) { conoutf("too many @"); goto screrr; }
|
||||
}
|
||||
}
|
||||
char *s = newstring(word, p-word-1);
|
||||
if(res.length())
|
||||
{
|
||||
res.put(word, p - word - 1);
|
||||
return newstring(res.getbuf(), res.length());
|
||||
}
|
||||
s = newstring(word, p-word-1);
|
||||
if(left=='(')
|
||||
{
|
||||
char *ret = executeret(s); // evaluate () exps directly, and substitute result
|
||||
@@ -416,11 +472,16 @@ char *parseexp(const char *&p, int right) // parse any nested set of
|
||||
s = ret ? ret : newstring("");
|
||||
}
|
||||
return s;
|
||||
|
||||
screrr:
|
||||
scripterr();
|
||||
flagmapconfigerror(LWW_SCRIPTERR * 4);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *lookup(char *n, int levels) // find value of ident referenced with $ in exp
|
||||
{
|
||||
if(levels > 1) n = exchangestr(n, lookup(newstring(n), levels - 1)); // nested ("$$var")
|
||||
if(levels > 1) n = exchangestr(n, lookup(newstring(n), min(levels - 1, 2))); // nested ("$$var"), limit to three levels
|
||||
ident *id = idents->access(n);
|
||||
if(id) switch(id->type)
|
||||
{
|
||||
@@ -435,42 +496,24 @@ char *lookup(char *n, int levels) // find value of ide
|
||||
return n;
|
||||
}
|
||||
|
||||
char *parseword(const char *&p, int arg, int &infix) // parse single argument, including expressions
|
||||
char *parseword(const char *&p, int arg, int *infix) // parse single argument, including expressions
|
||||
{
|
||||
p += strspn(p, " \t");
|
||||
if(p[0]=='/' && p[1]=='/') p += strcspn(p, "\n\r\0");
|
||||
if(*p=='\"')
|
||||
{
|
||||
const char *word = p + 1;
|
||||
do
|
||||
{
|
||||
p++;
|
||||
p += strcspn(p, "\"\n\r");
|
||||
}
|
||||
while(*p == '\"' && p[-1] == '\\'); // skip escaped quotes
|
||||
char *s = newstring(word, p - word);
|
||||
if(*p=='\"') p++;
|
||||
#ifndef STANDALONE
|
||||
filterrichtext(s, s, strlen(s));
|
||||
#endif
|
||||
return s;
|
||||
}
|
||||
if(*p=='(') return parseexp(p, ')');
|
||||
if(*p=='[') return parseexp(p, ']');
|
||||
int lvls = strspn(p, "$");
|
||||
if(p[lvls]=='(')
|
||||
{ // $()
|
||||
if(*p=='"') return parsequotes(p);
|
||||
if(*p=='(' && !currentcontextisolated) return parseexp(p, ')');
|
||||
if(*p=='[' && !currentcontextisolated) return parseexp(p, ']');
|
||||
int lvls = currentcontextisolated ? 0 : strspn(p, "$");
|
||||
if(lvls && (p[lvls]=='(' || p[lvls]=='['))
|
||||
{ // $() $[]
|
||||
p += lvls;
|
||||
char *b = parseexp(p, ')');
|
||||
char *b = parseexp(p, *p == '(' ? ')' : ']');
|
||||
if(b) return lookup(b, lvls);
|
||||
}
|
||||
const char *word = p;
|
||||
p += strcspn(p, "; \t\n\r\0");
|
||||
if(p-word==0) return NULL;
|
||||
if(arg==1 && p-word==1) switch(*word)
|
||||
{
|
||||
case '=': infix = *word; break;
|
||||
}
|
||||
if(arg == 1 && *word == '=' && p - word == 1) *infix = *word;
|
||||
return lvls ? lookup(newstring(word + lvls, p - word - lvls), lvls) : newstring(word, p-word);
|
||||
}
|
||||
|
||||
@@ -547,7 +590,7 @@ char *executeret(const char *p) // all evaluation hap
|
||||
{
|
||||
w[i] = &emptychar;
|
||||
if(i>numargs) continue;
|
||||
char *s = parseword(p, i, infix); // parse and evaluate exps
|
||||
char *s = parseword(p, i, &infix); // parse and evaluate exps
|
||||
if(s) w[i] = s;
|
||||
else numargs = i;
|
||||
}
|
||||
@@ -559,16 +602,11 @@ char *executeret(const char *p) // all evaluation hap
|
||||
|
||||
DELETEA(retval);
|
||||
|
||||
if(infix)
|
||||
if(infix == '=')
|
||||
{
|
||||
switch(infix)
|
||||
{
|
||||
case '=':
|
||||
DELETEA(w[1]);
|
||||
swap(w[0], w[1]);
|
||||
c = "alias";
|
||||
break;
|
||||
}
|
||||
DELETEA(w[1]);
|
||||
swap(w[0], w[1]);
|
||||
c = "alias";
|
||||
}
|
||||
|
||||
ident *id = idents->access(c);
|
||||
@@ -1156,9 +1194,12 @@ void explodelist(const char *s, vector<char *> &elems)
|
||||
{
|
||||
const char *elem = s;
|
||||
elementskip;
|
||||
#ifdef STANDALONE
|
||||
char *newelem = *elem == '"' ? newstring(elem + 1, s - elem - (s[-1]=='"' ? 2 : 1)) : newstring(elem, s-elem);
|
||||
#ifndef STANDALONE
|
||||
if(*elem == '\"') filterrichtext(newelem, newelem, strlen(newelem));
|
||||
#else
|
||||
size_t len;
|
||||
char *newelem = *elem == '"' ? newstring(elem + 1, (len = s - elem - (s[-1]=='"' ? 2 : 1))) : newstring(elem, s-elem);
|
||||
if(*elem == '\"') filterrichtext(newelem, newelem, len);
|
||||
#endif
|
||||
elems.add(newelem);
|
||||
whitespaceskip;
|
||||
@@ -1655,8 +1696,10 @@ int execcontext;
|
||||
|
||||
void pushscontext(int newcontext)
|
||||
{
|
||||
ASSERT(newcontext >= 0 && newcontext < IEXC_NUM);
|
||||
contextstack.add(execcontext);
|
||||
execcontext = newcontext;
|
||||
currentcontextisolated = contextsealed && contextisolated[execcontext];
|
||||
}
|
||||
|
||||
int popscontext()
|
||||
@@ -1664,6 +1707,7 @@ int popscontext()
|
||||
ASSERT(contextstack.length() > 0);
|
||||
int old = execcontext;
|
||||
execcontext = contextstack.pop();
|
||||
currentcontextisolated = contextsealed && contextisolated[execcontext];
|
||||
|
||||
if(execcontext < old && old >= IEXC_MAPCFG) // clean up aliases created in the old (map cfg) context
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user