| 5376 | |
| 5377 | |
| 5378 | ResultType Script::ParseOperands(LPTSTR aArgText, LPTSTR aArgMap, DerefList &aDeref, int *aPos, TCHAR aEndChar) |
| 5379 | { |
| 5380 | LPTSTR op_begin, op_end; |
| 5381 | size_t operand_length; |
| 5382 | TCHAR close_char, *cp; |
| 5383 | int j; |
| 5384 | bool is_function; |
| 5385 | bool is_double_deref; |
| 5386 | SymbolType wordop; |
| 5387 | |
| 5388 | // Escape sequences outside of literal strings have no meaning, so could be considered illegal |
| 5389 | // to improve error detection and reserve ` for future use. However, in that case ` must still |
| 5390 | // be allowed inside quoted strings and for `) in continuation sections, so this is inadequate: |
| 5391 | //if (this_aArgMap) // This arg has an arg map indicating which chars are escaped/literal vs. normal. |
| 5392 | // for (j = 0; this_new_arg.text[j]; ++j) |
| 5393 | // if (this_aArgMap[j]) |
| 5394 | // return ScriptError(ERR_EXP_ILLEGAL_CHAR, this_new_arg.text + j); |
| 5395 | |
| 5396 | op_begin = aArgText; |
| 5397 | if (aPos) |
| 5398 | op_begin += *aPos; |
| 5399 | for (; *op_begin; op_begin = op_end) |
| 5400 | { |
| 5401 | while (*op_begin && _tcschr(EXPR_OPERAND_TERMINATORS, *op_begin)) // Skip over whitespace, operators, and parentheses. |
| 5402 | { |
| 5403 | if (*op_begin == aEndChar) |
| 5404 | { |
| 5405 | if (aPos) |
| 5406 | *aPos = int(op_begin - aArgText); |
| 5407 | return OK; |
| 5408 | } |
| 5409 | if (*op_begin == g_DerefChar) |
| 5410 | // This is the start of a double-deref with no initial literal part. Double-derefs are |
| 5411 | // handled outside the loop for simplicity. Breaking out of the loop means that this |
| 5412 | // will be seen as an operand of zero length. |
| 5413 | break; |
| 5414 | if (*op_begin == '.') |
| 5415 | { |
| 5416 | // This case also handles the dot in `.=` (the `=` is skipped by the next iteration). |
| 5417 | // Skip the numeric literal or identifier to the right of this, if there is one. |
| 5418 | // This won't skip the signed exponent of a scientific-notation literal, but that should |
| 5419 | // be OK as it will be recognized as purely numeric in the next iteration of this loop. |
| 5420 | op_end = find_identifier_end(op_begin + 1); |
| 5421 | if (*op_end != g_DerefChar || aEndChar == g_DerefChar) |
| 5422 | { |
| 5423 | op_begin = op_end; |
| 5424 | continue; |
| 5425 | } |
| 5426 | // Otherwise, it's a dynamic property or method call. |
| 5427 | ++op_begin; // Skip the dot. |
| 5428 | break; |
| 5429 | } |
| 5430 | switch (*op_begin) |
| 5431 | { |
| 5432 | default: |
| 5433 | op_begin++; |
| 5434 | continue; |
| 5435 |
nothing calls this directly
no test coverage detected