| 7247 | |
| 7248 | |
| 7249 | Var *Script::AddVar(LPCTSTR aVarName, size_t aVarNameLength, VarList *aList, int aInsertPos, int aScope) |
| 7250 | // Returns the address of the new variable or NULL on failure. |
| 7251 | // Caller must ensure that g->CurrentFunc!=NULL whenever aIsLocal!=0. |
| 7252 | // Caller must ensure that aVarName isn't NULL and that this isn't a duplicate variable name. |
| 7253 | // In addition, it has provided aInsertPos, which is the insertion point so that the list stays sorted. |
| 7254 | // Finally, aIsLocal has been provided to indicate which list, global or local, should receive this |
| 7255 | // new variable, as well as the type of local variable. (See the declaration of VAR_LOCAL etc.) |
| 7256 | { |
| 7257 | if (!*aVarName) // Should never happen, so just silently indicate failure. |
| 7258 | return NULL; |
| 7259 | if (!aVarNameLength) // Caller didn't specify, so use the entire string. |
| 7260 | aVarNameLength = _tcslen(aVarName); |
| 7261 | |
| 7262 | if (aVarNameLength > MAX_VAR_NAME_LENGTH) |
| 7263 | { |
| 7264 | ScriptError(_T("Variable name too long."), aVarName); |
| 7265 | return NULL; |
| 7266 | } |
| 7267 | |
| 7268 | // Make a temporary copy that includes only the first aVarNameLength characters from aVarName: |
| 7269 | TCHAR var_name[MAX_VAR_NAME_LENGTH + 1]; |
| 7270 | tcslcpy(var_name, aVarName, aVarNameLength + 1); // See explanation above. +1 to convert length to size. |
| 7271 | |
| 7272 | if (!Var::ValidateName(var_name)) |
| 7273 | // Above already displayed error for us. This can happen at loadtime or runtime (e.g. StringSplit). |
| 7274 | return NULL; |
| 7275 | |
| 7276 | bool aIsLocal = (aScope & VAR_LOCAL); |
| 7277 | |
| 7278 | if ((aScope & (VAR_LOCAL | VAR_DECLARED)) == VAR_LOCAL // This is an implicit local. |
| 7279 | && g_Warn_LocalSameAsGlobal && !mIsReadyToExecute // Not enabled at runtime because of overlap with #Warn UseUnset, and dynamic assignments in assume-local mode are less likely to be intended global. |
| 7280 | && FindGlobalVar(var_name, aVarNameLength)) |
| 7281 | WarnLocalSameAsGlobal(var_name); |
| 7282 | |
| 7283 | // Allocate some dynamic memory to pass to the constructor: |
| 7284 | LPTSTR new_name = SimpleHeap::Malloc(var_name, aVarNameLength); |
| 7285 | if (!new_name) |
| 7286 | // It already displayed the error for us. |
| 7287 | return NULL; |
| 7288 | |
| 7289 | // Below specifically tests for VAR_LOCAL and excludes other non-zero values/flags: |
| 7290 | // VAR_LOCAL_FUNCPARAM should not be made static. |
| 7291 | // VAR_LOCAL_STATIC is already static. |
| 7292 | // VAR_DECLARED indicates mDefaultVarType is irrelevant. |
| 7293 | if (aScope == VAR_LOCAL && (g->CurrentFunc->mDefaultVarType & VAR_LOCAL_STATIC)) |
| 7294 | // v1.0.48: Lexikos: Current function is assume-static, so set static attribute. |
| 7295 | aScope |= VAR_LOCAL_STATIC; |
| 7296 | |
| 7297 | Var *the_new_var = new Var(new_name, aScope); |
| 7298 | if (!the_new_var || !aList->Insert(the_new_var, aInsertPos)) |
| 7299 | { |
| 7300 | MemoryError(); |
| 7301 | return NULL; |
| 7302 | } |
| 7303 | |
| 7304 | if (aScope & VAR_LOCAL_FUNCPARAM) |
| 7305 | the_new_var->MarkAssignedSomewhere(); |
| 7306 |
no test coverage detected