MCPcopy Create free account
hub / github.com/AutoHotkey/AutoHotkey / ExpandExpression

Method ExpandExpression

source/script_expression.cpp:53–1527  ·  view source on GitHub ↗

__forceinline: Decided against it for this function because although it's only called by one caller, testing shows that it wastes stack space (room for its automatic variables would be unconditionally reserved in the stack of its caller). Also, the performance benefit of inlining this is too slight. Here's a simple way to verify wasted stack space in a caller that calls an inlined function: DWORD

Source from the content-addressed store, hash-verified

51// _asm mov stack, esp
52// MsgBox(stack);
53LPTSTR Line::ExpandExpression(int aArgIndex, ResultType &aResult, ResultToken *aResultToken
54 , LPTSTR &aTarget, LPTSTR &aDerefBuf, size_t &aDerefBufSize, LPTSTR aArgDeref[], size_t aExtraSize)
55// Caller should ignore aResult unless this function returns NULL.
56// Returns a pointer to this expression's result, which can be one of the following:
57// 1) NULL, in which case aResult will be either FAIL or EARLY_EXIT to indicate the means by which the current
58// quasi-thread was terminated as a result of a function call.
59// 2) The constant empty string (""), in which case we do not alter aTarget for our caller.
60// 3) Some persistent location not in aDerefBuf, namely the mContents of a variable or a literal string/number,
61// such as a function-call that returns "abc", 123, or a variable.
62// 4) At position aTarget inside aDerefBuf (note that aDerefBuf might have been reallocated by us).
63// aTarget is left unchanged except in case #4, in which case aTarget has been adjusted to the position after our
64// result-string's terminator. In addition, in case #4, aDerefBuf, aDerefBufSize, and aArgDeref[] have been adjusted
65// for our caller if aDerefBuf was too small and needed to be enlarged.
66//
67// Thanks to Joost Mulders for providing the expression evaluation code upon which this function is based.
68{
69 LPTSTR target = aTarget; // "target" is used to track our usage (current position) within the aTarget buffer.
70
71 // The following must be defined early so that to_free_count is initialized and the array is guaranteed to be
72 // "in scope" in case of early "goto" (goto substantially boosts performance and reduces code size here).
73 ExprTokenType **to_free = (ExprTokenType **)_alloca(mArg[aArgIndex].max_alloc * sizeof(ExprTokenType *));
74 int to_free_count = 0; // The actual number of items in use in the above array.
75 LPTSTR result_to_return = _T(""); // By contrast, NULL is used to tell the caller to abort the current thread.
76 LPCTSTR error_msg = ERR_EXPR_EVAL, error_info = _T("");
77 ExprTokenType *error_value;
78 Var *output_var = (mActionType == ACT_ASSIGNEXPR) ? VAR(mArg[0]) : NULL; // Resolve early because it's similar in usage/scope to the above.
79
80 ExprTokenType **stack = (ExprTokenType **)_alloca(mArg[aArgIndex].max_stack * sizeof(ExprTokenType *));
81 int stack_count = 0;
82 ExprTokenType *&postfix = mArg[aArgIndex].postfix;
83
84 ///////////////////////////////
85 // EVALUATE POSTFIX EXPRESSION
86 ///////////////////////////////
87 int i, delta;
88 SymbolType right_is_number, left_is_number, right_is_pure_number, left_is_pure_number, result_symbol;
89 double right_double, left_double;
90 __int64 right_int64, left_int64;
91 LPTSTR right_string, left_string;
92 size_t right_length, left_length;
93 TCHAR left_buf[max(MAX_NUMBER_SIZE, _f_retval_buf_size)];
94 TCHAR right_buf[MAX_NUMBER_SIZE];
95 LPTSTR result; // "result" is used for return values and also the final result.
96 VarSizeType result_length;
97 size_t result_size, alloca_usage = 0; // v1.0.45: Track amount of alloca mem to avoid stress on stack from extreme expressions (mostly theoretical).
98 BOOL done, done_and_have_an_output_var, left_branch_is_true
99 , left_was_negative, is_pre_op; // BOOL vs. bool benchmarks slightly faster, and is slightly smaller in code size (or maybe it's cp1's int vs. char that shrunk it).
100 ExprTokenType *this_postfix, *p_postfix;
101 Var *sym_assign_var, *temp_var;
102
103 // v1.0.44.06: EXPR_SMALL_MEM_LIMIT is the means by which _alloca() is used to boost performance a
104 // little by avoiding the overhead of malloc+free for small strings. The limit should be something
105 // small enough that the chance that even 10 of them would cause stack overflow is vanishingly small.
106 #define EXPR_SMALL_MEM_LIMIT 4097 // The maximum size allowed for an item to qualify for alloca.
107 #define EXPR_ALLOCA_LIMIT 40000 // The maximum amount of alloca memory for all items. v1.0.45: An extra precaution against stack stress in extreme/theoretical cases.
108 #define EXPR_IS_DONE (!stack_count && this_postfix[1].symbol == SYM_INVALID) // True if we've used up the last of the operators & operands. Non-zero stack_count combined with SYM_INVALID would indicate an error (an exception will be thrown later, so don't take any shortcuts).
109
110 // For each item in the postfix array: if it's an operand, push it onto stack; if it's an operator or

Callers

nothing calls this directly

Calls 15

TokenToObjectFunction · 0.85
TokenToStringFunction · 0.85
VariadicCallFunction · 0.85
TokenIsPureNumericFunction · 0.85
TokenToBOOLFunction · 0.85
TokenToInt64Function · 0.85
TokenToDoubleFunction · 0.85
TokenToDoubleOrInt64Function · 0.85
pow_llFunction · 0.85
FTOAFunction · 0.85
MemoryErrorFunction · 0.85
CopyExprFromMethod · 0.80

Tested by

no test coverage detected