From: Francis De Brabandere <francisdb@gmail.com> VBScript allows square brackets to quote identifiers containing spaces, special characters, or reserved words. --- dlls/vbscript/lex.c | 33 ++++++++++++++++++++++++++++ dlls/vbscript/tests/lang.vbs | 41 +++++++++++++++++++++++++++++++++++ dlls/vbscript/tests/run.c | 12 ++++++++++ dlls/vbscript/vbscript_defs.h | 1 + 4 files changed, 87 insertions(+) diff --git a/dlls/vbscript/lex.c b/dlls/vbscript/lex.c index d0f47d495a7..ffe28211b8c 100644 --- a/dlls/vbscript/lex.c +++ b/dlls/vbscript/lex.c @@ -410,6 +410,37 @@ static int comment_line(parser_ctx_t *ctx) return tNL; } +static int parse_bracket_identifier(parser_ctx_t *ctx, const WCHAR **ret) +{ + const WCHAR *start = ++ctx->ptr; + WCHAR *str; + int len; + + while(ctx->ptr < ctx->end && *ctx->ptr != ']' && *ctx->ptr != '\n' && *ctx->ptr != '\r') { + if(*ctx->ptr == '[') + return lex_error(ctx, MAKE_VBSERROR(VBSE_INVALID_CHAR)); + ctx->ptr++; + } + + if(ctx->ptr >= ctx->end || *ctx->ptr != ']') + return lex_error(ctx, MAKE_VBSERROR(VBSE_UNTERMINATED_IDENTIFIER)); + + len = ctx->ptr - start; + ctx->ptr++; /* skip ']' */ + + if(len > MAX_IDENTIFIER_LENGTH) + return lex_error(ctx, MAKE_VBSERROR(VBSE_IDENTIFIER_TOO_LONG)); + + str = parser_alloc(ctx, (len+1)*sizeof(WCHAR)); + if(!str) + return 0; + + memcpy(str, start, len*sizeof(WCHAR)); + str[len] = 0; + *ret = str; + return tIdentifier; +} + static int parse_next_token(void *lval, unsigned *loc, parser_ctx_t *ctx) { WCHAR c; @@ -499,6 +530,8 @@ static int parse_next_token(void *lval, unsigned *loc, parser_ctx_t *ctx) if(ctx->last_token == tIdentifier || ctx->last_token == ')' || ctx->last_token == tME) return '('; return tEXPRLBRACKET; + case '[': + return parse_bracket_identifier(ctx, lval); case '"': return parse_string_literal(ctx, lval); case '#': diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index b013e46967f..37a92fc53f4 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -278,6 +278,47 @@ Dim aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = 42 Call ok(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = 42, "255-char identifier should work") +' Bracketed identifiers +Dim [my var] +[my var] = 42 +Call ok([my var] = 42, "[my var] = " & [my var]) + +Dim [hello world!] +[hello world!] = "works" +Call ok([hello world!] = "works", "[hello world!] = " & [hello world!]) + +Dim [] +[] = "empty" +Call ok([] = "empty", "[] = " & []) + +Dim [ ] +[ ] = "spaces" +Call ok([ ] = "spaces", "[ ] = " & [ ]) + +Dim [dim] +[dim] = 99 +Call ok([dim] = 99, "[dim] = " & [dim]) + +Class BracketTestObj + Public [my property] + Public Sub Class_Initialize + [my property] = "init" + End Sub +End Class + +Dim bracketObj +Set bracketObj = New BracketTestObj +bracketObj.[my property] = "updated" +Call ok(bracketObj.[my property] = "updated", "bracketObj.[my property] = " & bracketObj.[my property]) + +Dim [loop var] +Dim bracketTotal : bracketTotal = 0 +For [loop var] = 1 To 3 + bracketTotal = bracketTotal + [loop var] +Next +Call ok(bracketTotal = 6, "For [loop var] total = " & bracketTotal) + +' Chained call syntax Class ChainedCallTarget Public Function Ret() Set Ret = Me diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index e51bcf29751..2849e610513 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -3085,6 +3085,18 @@ static void test_parse_errors(void) L"Dim aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n", 0, 260, NULL, S_OK, 1030 + }, + { + /* Nested square brackets */ + L"Dim [[nested]]\n", + 0, -13, + NULL, S_OK, 1032 + }, + { + /* Unclosed square bracket */ + L"Dim [unclosed\n", + 0, 13, + NULL, S_OK, 1007 } }; HRESULT hres; diff --git a/dlls/vbscript/vbscript_defs.h b/dlls/vbscript/vbscript_defs.h index 9e7f9aa631b..e60eb1604ca 100644 --- a/dlls/vbscript/vbscript_defs.h +++ b/dlls/vbscript/vbscript_defs.h @@ -275,6 +275,7 @@ #define VBSE_UNQUALIFIED_REFERENCE 505 #define VBSE_SYNTAX_ERROR 1002 #define VBSE_EXPECTED_LPAREN 1005 +#define VBSE_UNTERMINATED_IDENTIFIER 1007 #define VBSE_EXPECTED_IDENTIFIER 1010 #define VBSE_EXPECTED_ASSIGN 1011 #define VBSE_EXPECTED_TO 1013 -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10579