From 4dd30523a9fba5bb7bcc6f490250e49647d480a9 Mon Sep 17 00:00:00 2001 From: divverent Date: Sun, 2 May 2010 12:32:18 +0000 Subject: [PATCH] unset command From: Blub git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@10114 d7cf8633-e32d-0410-b094-e92efae38249 --- cmd.c | 1 + cvar.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cvar.h | 1 + 3 files changed, 86 insertions(+) diff --git a/cmd.c b/cmd.c index 47e40a4f..f8baf912 100644 --- a/cmd.c +++ b/cmd.c @@ -1185,6 +1185,7 @@ void Cmd_Init_Commands (void) Cmd_AddCommand ("wait", Cmd_Wait_f, "make script execution wait for next rendered frame"); Cmd_AddCommand ("set", Cvar_Set_f, "create or change the value of a console variable"); Cmd_AddCommand ("seta", Cvar_SetA_f, "create or change the value of a console variable that will be saved to config.cfg"); + Cmd_AddCommand ("unset", Cvar_Del_f, "delete a cvar (does not work for static ones like _cl_name, or read-only ones)"); #ifdef FILLALLCVARSWITHRUBBISH Cmd_AddCommand ("fillallcvarswithrubbish", Cvar_FillAll_f, "fill all cvars with a specified number of characters to provoke buffer overruns"); #endif /* FILLALLCVARSWITHRUBBISH */ diff --git a/cvar.c b/cvar.c index 8f3abc39..bf6df5ad 100644 --- a/cvar.c +++ b/cvar.c @@ -70,6 +70,36 @@ cvar_t *Cvar_FindVarAfter (const char *prev_var_name, int neededflags) return var; } +cvar_t *Cvar_FindVarLink (const char *var_name, cvar_t **parent, cvar_t ***link, cvar_t **prev_alpha) +{ + int hashindex; + cvar_t *var; + + // use hash lookup to minimize search time + hashindex = CRC_Block((const unsigned char *)var_name, strlen(var_name)); + if(parent) *parent = NULL; + if(prev_alpha) *prev_alpha = NULL; + if(link) *link = &cvar_hashtable[hashindex]; + for (var = cvar_hashtable[hashindex];var;var = var->nextonhashchain) + { + if (!strcmp (var_name, var->name)) + { + if(!prev_alpha || var == cvar_vars) + return var; + + *prev_alpha = cvar_vars; + // if prev_alpha happens to become NULL then there has been some inconsistency elsewhere + // already - should I still insert '*prev_alpha &&' in the loop? + while((*prev_alpha)->next != var) + *prev_alpha = (*prev_alpha)->next; + return var; + } + if(parent) *parent = var; + } + + return NULL; +} + /* ============ Cvar_VariableValue @@ -820,6 +850,60 @@ void Cvar_SetA_f (void) Cvar_Get(Cmd_Argv(1), Cmd_Argv(2), CVAR_SAVE, Cmd_Argc() > 3 ? Cmd_Argv(3) : NULL); } +void Cvar_Del_f (void) +{ + int i; + cvar_t *cvar, *parent, **link, *prev; + + if(Cmd_Argc() < 2) + { + Con_Printf("Del: wrong number of parameters, useage: unset [ ...]\n"); + return; + } + for(i = 1; i < Cmd_Argc(); ++i) + { + cvar = Cvar_FindVarLink(Cmd_Argv(i), &parent, &link, &prev); + if(!cvar) + { + Con_Printf("Del: %s is not defined\n", Cmd_Argv(i)); + continue; + } + if(cvar->flags & CVAR_READONLY) + { + Con_Printf("Del: %s is read-only\n", cvar->name); + continue; + } + if(!(cvar->flags & CVAR_ALLOCATED)) + { + Con_Printf("Del: %s is static and cannot be deleted\n", cvar->name); + continue; + } + if(cvar == cvar_vars) + { + cvar_vars = cvar->next; + } + else + { + // in this case, prev must be set, otherwise there has been some inconsistensy + // elsewhere already... should I still check for prev != NULL? + prev->next = cvar->next; + } + + if(parent) + parent->nextonhashchain = cvar->nextonhashchain; + else if(link) + *link = cvar->nextonhashchain; + + if(cvar->description != cvar_dummy_description) + Z_Free(cvar->description); + + Z_Free(cvar->name); + Z_Free(cvar->string); + Z_Free(cvar->defstring); + Z_Free(cvar); + } +} + #ifdef FILLALLCVARSWITHRUBBISH void Cvar_FillAll_f() { diff --git a/cvar.h b/cvar.h index 636ca40b..1c04d86e 100644 --- a/cvar.h +++ b/cvar.h @@ -205,6 +205,7 @@ void Cvar_List_f (void); void Cvar_Set_f (void); void Cvar_SetA_f (void); +void Cvar_Del_f (void); // commands to create new cvars (or set existing ones) // seta creates an archived cvar (saved to config) -- 2.39.2