/* ============ Cvar_Get If the variable already exists, the value will not be set unless CVAR_ROM The flags will be or'ed in if the variable exists. ============ */ cvar_t *Cvar_Get(const char *var_name, const char *var_value, int flags) { cvar_t *var; long hash; if (!var_name || !var_value) { Com_Error(ERR_FATAL, "Cvar_Get: NULL parameter"); } if (!Cvar_ValidateString(var_name)) { Com_Printf("invalid cvar name string: %s\n", var_name); var_name = "BADNAME"; } #if 0 // FIXME: values with backslash happen if (!Cvar_ValidateString(var_value)) { Com_Printf("invalid cvar value string: %s\n", var_value); var_value = "BADVALUE"; } #endif var = Cvar_FindVar(var_name); if (var) { // if the C code is now specifying a variable that the user already // set a value for, take the new value as the reset value if ((var->flags & CVAR_USER_CREATED) && !(flags & CVAR_USER_CREATED) && var_value[0]) { var->flags &= ~CVAR_USER_CREATED; Z_Free(var->resetString); var->resetString = CopyString(var_value); // ZOID--needs to be set so that cvars the game sets as // SERVERINFO get sent to clients cvar_modifiedFlags |= flags; } var->flags |= flags; // only allow one non-empty reset string without a warning if (!var->resetString[0]) { // we don't have a reset string yet Z_Free(var->resetString); var->resetString = CopyString(var_value); } else if (var_value[0] && strcmp(var->resetString, var_value)) { Com_DPrintf("Warning: cvar \"%s\" given initial values: \"%s\" and \"%s\"\n", var_name, var->resetString, var_value); } // if we have a latched string, take that value now if (var->latchedString) { char *s; s = var->latchedString; var->latchedString = NULL; // otherwise cvar_set2 would free it Cvar_Set2(var_name, s, qtrue); Z_Free(s); } // if CVAR_USERINFO was toggled on for an existing cvar, check wether the value needs to be cleaned from foreigh characters // (for instance, seta name "name-with-foreign-chars" in the config file, and toggle to CVAR_USERINFO happens later in CL_Init) if (flags & CVAR_USERINFO) { char *cleaned = Cvar_ClearForeignCharacters(var->string); // NOTE: it is probably harmless to call Cvar_Set2 in all cases, but I don't want to risk it if (strcmp(var->string, cleaned)) { Cvar_Set2(var->name, var->string, qfalse); // call Cvar_Set2 with the value to be cleaned up for verbosity } } // use a CVAR_SET for rom sets, get won't override #if 0 // CVAR_ROM always overrides if (flags & CVAR_ROM) { Cvar_Set2(var_name, var_value, qtrue); } #endif return var; } // allocate a new cvar if (cvar_numIndexes >= MAX_CVARS) { Com_Error(ERR_FATAL, "Cvar_Get: MAX_CVARS (%d) hit -- too many cvars!", MAX_CVARS); } var = &cvar_indexes[cvar_numIndexes]; cvar_numIndexes++; var->name = CopyString(var_name); var->string = CopyString(var_value); var->modified = qtrue; var->modificationCount = 1; var->value = atof(var->string); var->integer = atoi(var->string); var->resetString = CopyString(var_value); // link the variable in var->next = cvar_vars; cvar_vars = var; var->flags = flags; hash = generateHashValue(var_name); var->hashNext = hashTable[hash]; hashTable[hash] = var; return var; }
cvar_t *Cvar_Set2(const char *var_name, const char *value, qboolean force) { cvar_t *var; Com_DPrintf("Cvar_Set2: %s %s\n", var_name, value); if (!Cvar_ValidateString(var_name)) { Com_Printf("invalid cvar name string: %s\n", var_name); var_name = "BADNAME"; } var = Cvar_FindVar(var_name); if (!var) { if (!value) { return NULL; } // create it if (!force) { return Cvar_Get(var_name, value, CVAR_USER_CREATED); } else { return Cvar_Get(var_name, value, 0); } } if (!value) { value = var->resetString; } if (var->flags & CVAR_USERINFO) { char *cleaned = Cvar_ClearForeignCharacters(value); if (strcmp(value, cleaned)) { #ifdef DEDICATED Com_Printf(FOREIGN_MSG); #else Com_Printf("%s", CL_TranslateStringBuf(FOREIGN_MSG)); #endif Com_Printf("Using %s instead of %s\n", cleaned, value); return Cvar_Set2(var_name, cleaned, force); } } if (!strcmp(value, var->string)) { if ((var->flags & CVAR_LATCH) && var->latchedString) { if (!strcmp(value, var->latchedString)) { return var; } } else { return var; } } // note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo) cvar_modifiedFlags |= var->flags; if (!force) { // don't set unsafe variables when com_crashed is set if ((var->flags & CVAR_UNSAFE) && com_crashed != NULL && com_crashed->integer) { Com_Printf("%s is unsafe. Check com_crashed.\n", var_name); return var; } if (var->flags & CVAR_ROM) { Com_Printf("%s is read only.\n", var_name); return var; } if (var->flags & CVAR_INIT) { Com_Printf("%s is write protected.\n", var_name); return var; } if ((var->flags & CVAR_CHEAT) && !cvar_cheats->integer) { Com_Printf("%s is cheat protected.\n", var_name); return var; } if (var->flags & CVAR_LATCH) { if (var->latchedString) { if (strcmp(value, var->latchedString) == 0) { return var; } Z_Free(var->latchedString); } else { if (strcmp(value, var->string) == 0) { return var; } } Com_Printf("%s will be changed upon restarting.\n", var_name); var->latchedString = CopyString(value); var->modified = qtrue; var->modificationCount++; return var; } } else { if (var->latchedString) { Z_Free(var->latchedString); var->latchedString = NULL; } } if (!strcmp(value, var->string)) { return var; // not changed } var->modified = qtrue; var->modificationCount++; Z_Free(var->string); // free the old value string var->string = CopyString(value); var->value = atof(var->string); var->integer = atoi(var->string); return var; }
/* ============ Cvar_Get If the variable already exists, the value will not be set unless CVAR_ROM The flags will be or'ed in if the variable exists. ============ */ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) { cvar_t *var; long hash; int index; if ( !var_name || !var_value ) { Com_Error( ERR_FATAL, "Cvar_Get: NULL parameter" ); } if ( !Cvar_ValidateString( var_name ) ) { Com_Printf( "invalid cvar name string: %s\n", var_name ); var_name = "BADNAME"; } #if 0 // FIXME: values with backslash happen if ( !Cvar_ValidateString( var_value ) ) { Com_Printf( "invalid cvar value string: %s\n", var_value ); var_value = "BADVALUE"; } #endif var = Cvar_FindVar( var_name ); if ( var ) { var_value = Cvar_Validate(var, var_value, qfalse); // Make sure the game code cannot mark engine-added variables as gamecode vars if(var->flags & CVAR_VM_CREATED) { if(!(flags & CVAR_VM_CREATED)) var->flags &= ~CVAR_VM_CREATED; } else if (!(var->flags & CVAR_USER_CREATED)) { if(flags & CVAR_VM_CREATED) flags &= ~CVAR_VM_CREATED; } // if the C code is now specifying a variable that the user already // set a value for, take the new value as the reset value if(var->flags & CVAR_USER_CREATED) { var->flags &= ~CVAR_USER_CREATED; Z_Free( var->resetString ); var->resetString = CopyString( var_value ); if(flags & CVAR_ROM) { // this variable was set by the user, // so force it to value given by the engine. if(var->latchedString) Z_Free(var->latchedString); var->latchedString = CopyString(var_value); } } // Make sure servers cannot mark engine-added variables as SERVER_CREATED if(var->flags & CVAR_SERVER_CREATED) { if(!(flags & CVAR_SERVER_CREATED)) var->flags &= ~CVAR_SERVER_CREATED; } else { if(flags & CVAR_SERVER_CREATED) flags &= ~CVAR_SERVER_CREATED; } var->flags |= flags; // only allow one non-empty reset string without a warning if ( !var->resetString[0] ) { // we don't have a reset string yet Z_Free( var->resetString ); var->resetString = CopyString( var_value ); } else if ( var_value[0] && strcmp( var->resetString, var_value ) ) { Com_DPrintf( "Warning: cvar \"%s\" given initial values: \"%s\" and \"%s\"\n", var_name, var->resetString, var_value ); } // if we have a latched string, take that value now if ( var->latchedString ) { char *s; s = var->latchedString; var->latchedString = NULL; // otherwise cvar_set2 would free it Cvar_Set2( var_name, s, qtrue ); Z_Free( s ); } // TTimo // if CVAR_USERINFO was toggled on for an existing cvar, check wether the value needs to be cleaned from foreigh characters // (for instance, seta name "name-with-foreign-chars" in the config file, and toggle to CVAR_USERINFO happens later in CL_Init) if ( flags & CVAR_USERINFO ) { char *cleaned = Cvar_ClearForeignCharacters( var->string ); // NOTE: it is probably harmless to call Cvar_Set2 in all cases, but I don't want to risk it if ( strcmp( var->string, cleaned ) ) { Cvar_Set2( var->name, var->string, qfalse ); // call Cvar_Set2 with the value to be cleaned up for verbosity } } // ZOID--needs to be set so that cvars the game sets as // SERVERINFO get sent to clients cvar_modifiedFlags |= flags; return var; } // // allocate a new cvar // // find a free cvar for(index = 0; index < MAX_CVARS; index++) { if(!cvar_indexes[index].name) break; } if(index >= MAX_CVARS) { if(!com_errorEntered) Com_Error(ERR_FATAL, "Error: Too many cvars, cannot create a new one!"); return NULL; } var = &cvar_indexes[index]; if(index >= cvar_numIndexes) cvar_numIndexes = index + 1; var->name = CopyString( var_name ); var->string = CopyString( var_value ); var->modified = qtrue; var->modificationCount = 1; var->value = atof( var->string ); var->integer = atoi( var->string ); var->resetString = CopyString( var_value ); var->validate = qfalse; // link the variable in var->next = cvar_vars; if(cvar_vars) cvar_vars->prev = var; var->prev = NULL; cvar_vars = var; var->flags = flags; // note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo) cvar_modifiedFlags |= var->flags; hash = generateHashValue( var_name ); var->hashIndex = hash; var->hashNext = hashTable[hash]; if(hashTable[hash]) hashTable[hash]->hashPrev = var; var->hashPrev = NULL; hashTable[hash] = var; return var; }