| 7048 | |
| 7049 | |
| 7050 | Var *Script::FindVar(LPCTSTR aVarName, size_t aVarNameLength, int aScope |
| 7051 | , VarList **apList, int *apInsertPos, ResultType *aDisplayError) |
| 7052 | // Caller has ensured that aVarName isn't NULL. It must also ignore the contents of apInsertPos when |
| 7053 | // a match (non-NULL value) is returned. |
| 7054 | // Returns the Var whose name matches aVarName. If it doesn't exist, NULL is returned. |
| 7055 | // If caller provided a non-NULL apInsertPos, it will be given a the array index that a newly |
| 7056 | // inserted item should have to keep the list in sorted order (which also allows the ListVars command |
| 7057 | // to display the variables in alphabetical order). |
| 7058 | { |
| 7059 | if (!*aVarName) |
| 7060 | return NULL; |
| 7061 | if (!aVarNameLength) // Caller didn't specify, so use the entire string. |
| 7062 | aVarNameLength = _tcslen(aVarName); |
| 7063 | |
| 7064 | // For the below, no error is reported because callers don't want that. Instead, simply return |
| 7065 | // NULL to indicate that names that are illegal or too long are not found. When the caller later |
| 7066 | // tries to add the variable, it will get an error then: |
| 7067 | if (aVarNameLength > MAX_VAR_NAME_LENGTH) |
| 7068 | return NULL; |
| 7069 | |
| 7070 | // The following copy is made because it allows the various searches below to use _tcsicmp() instead of |
| 7071 | // strlicmp(), which close to doubles their performance. The copy includes only the first aVarNameLength |
| 7072 | // characters from aVarName: |
| 7073 | TCHAR var_name[MAX_VAR_NAME_LENGTH + 1]; |
| 7074 | tcslcpy(var_name, aVarName, aVarNameLength + 1); // +1 to convert length to size. |
| 7075 | |
| 7076 | global_struct &g = *::g; // Reduces code size and may improve performance. |
| 7077 | bool search_local = (aScope & VAR_LOCAL) && g.CurrentFunc; |
| 7078 | // Above has ensured that g.CurrentFunc!=NULL whenever search_local==true. |
| 7079 | |
| 7080 | if (search_local) |
| 7081 | { |
| 7082 | auto &func = *g.CurrentFunc; |
| 7083 | int nonstatic_pos, static_pos; |
| 7084 | if (Var *found = func.mVars.Find(var_name, &nonstatic_pos)) return found; |
| 7085 | if (Var *found = func.mStaticVars.Find(var_name, &static_pos)) return found; |
| 7086 | bool add_static = (aScope & VAR_LOCAL_STATIC) |
| 7087 | || !(aScope & VAR_DECLARED) && (func.mDefaultVarType & VAR_LOCAL_STATIC); |
| 7088 | if (apList) *apList = add_static ? &func.mStaticVars : &func.mVars; |
| 7089 | if (apInsertPos) *apInsertPos = add_static ? static_pos : nonstatic_pos; |
| 7090 | } |
| 7091 | else |
| 7092 | { |
| 7093 | auto varlist = GlobalVars(); |
| 7094 | int insert_pos; |
| 7095 | if (Var *found = varlist->Find(var_name, &insert_pos)) return found; |
| 7096 | if (apList) *apList = varlist; |
| 7097 | if (apInsertPos) *apInsertPos = insert_pos; |
| 7098 | |
| 7099 | if (!(aScope & FINDVAR_NO_BIF)) |
| 7100 | // Built-in functions can be shadowed, so are checked only in this section. |
| 7101 | if (auto *bif = GetBuiltInFunc(var_name)) |
| 7102 | { |
| 7103 | auto *func = new BuiltInFunc(*bif); |
| 7104 | if (!func) |
| 7105 | { |
| 7106 | if (aDisplayError) |
| 7107 | *aDisplayError = ScriptError(ERR_OUTOFMEM); |
no test coverage detected