From: Cloudwalk Date: Sun, 18 Jul 2021 04:34:11 +0000 (-0400) Subject: cvar: Use the generic linked list for cvars. Made virtual cvars actual cvar_t's X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=4ae5fd3802a78c22f333232889f5a8f674f1d81c;p=xonotic%2Fdarkplaces.git cvar: Use the generic linked list for cvars. Made virtual cvars actual cvar_t's * cvar_hash_t is gone * Virtual cvars now use a linked list around their parent and have a pointer to their parent. * Cvars will now store their own hashindex to make deletions from the hashtable easier. Implemented Cvar_Delete where this is leveraged. Cvar_FindVarLink is eliminated also. Not needed anymore. * Implemented Cvar_DeleteVirtual and Cvar_DeleteVirtual_All to... delete virtual cvars. * Eliminated redundancy of Cvar_SetQuick_Internal by merging it with Cvar_SetQuick. * Misc cleanups --- diff --git a/cl_cmd.c b/cl_cmd.c index 9277ad50..d3a855be 100644 --- a/cl_cmd.c +++ b/cl_cmd.c @@ -211,7 +211,7 @@ static void CL_SendCvar_f(cmd_state_t *cmd) if(!c || (c->flags & CF_PRIVATE)) CL_ForwardToServer(va(vabuf, sizeof(vabuf), "sentcvar %s", cvarname)); else - CL_ForwardToServer(va(vabuf, sizeof(vabuf), "sentcvar %s \"%s\"", c->name, c->string)); + CL_ForwardToServer(va(vabuf, sizeof(vabuf), "sentcvar %s \"%s\"", c->name, c->parent ? c->parent->string : c->string)); return; } } diff --git a/cmd.c b/cmd.c index abc512ee..ed76ba87 100644 --- a/cmd.c +++ b/cmd.c @@ -925,6 +925,7 @@ static void Cmd_Toggle_f(cmd_state_t *cmd) { // Correct Arguments Specified // Acquire Potential CVar cvar_t* cvCVar = Cvar_FindVar(cmd->cvars, Cmd_Argv(cmd, 1), cmd->cvars_flagsmask); + cvCVar = cvCVar->parent ? cvCVar->parent : cvCVar; if(cvCVar != NULL) { // Valid CVar @@ -1173,7 +1174,7 @@ static const char *Cmd_GetDirectCvarValue(cmd_state_t *cmd, const char *varname, } if((cvar = Cvar_FindVar(cmd->cvars, varname, cmd->cvars_flagsmask)) && !(cvar->flags & CF_PRIVATE)) - return cvar->string; + return cvar->parent ? cvar->parent->string : cvar->string; return NULL; } @@ -1579,24 +1580,15 @@ static void Cmd_Apropos_f(cmd_state_t *cmd) partial = va(vabuf, sizeof(vabuf), "*%s*", partial); count = 0; - for (cvar = cmd->cvars->vars; cvar; cvar = cvar->next) + List_For_Each_Entry(cvar, &cmd->cvars->vars->list, list) { if (matchpattern_with_separator(cvar->name, partial, true, "", false) || matchpattern_with_separator(cvar->description, partial, true, "", false)) { Con_Printf ("cvar "); - Cvar_PrintHelp(cvar, cvar->name, true); + Cvar_PrintHelp(cvar->parent ? cvar->parent : cvar, cvar->name, true); count++; } - for (char **cvar_alias = cvar->aliases; cvar_alias && *cvar_alias; cvar_alias++) - { - if (matchpattern_with_separator(*cvar_alias, partial, true, "", false)) - { - Con_Printf ("cvar "); - Cvar_PrintHelp(cvar, *cvar_alias, true); - count++; - } - } } for (func = cmd->userdefined->qc_functions; func; func = func->next) { @@ -1636,6 +1628,8 @@ static cmd_state_t *Cmd_AddInterpreter(cmd_buf_t *cbuf, cvar_state_t *cvars, int cmd->null_string = ""; cmd->cvars = cvars; + cmd->cvars->vars = (cvar_t *)Z_Malloc(sizeof(cvar_t)); + cmd->cvars->vars->list.next = cmd->cvars->vars->list.prev = &cmd->cvars->vars->list; cmd->cvars_flagsmask = cvars_flagsmask; cmd->cmd_flags = cmds_flagsmask; cmd->userdefined = userdefined; diff --git a/cvar.c b/cvar.c index cbe8b0f6..98d2a666 100644 --- a/cvar.c +++ b/cvar.c @@ -36,17 +36,13 @@ Cvar_FindVar cvar_t *Cvar_FindVar(cvar_state_t *cvars, const char *var_name, int neededflags) { int hashindex; - cvar_hash_t *hash; + cvar_t *hash; // use hash lookup to minimize search time hashindex = CRC_Block((const unsigned char *)var_name, strlen(var_name)) % CVAR_HASHSIZE; - for (hash = cvars->hashtable[hashindex];hash;hash = hash->next) - if (!strcmp (var_name, hash->cvar->name) && (hash->cvar->flags & neededflags)) - return hash->cvar; - else - for (char **alias = hash->cvar->aliases; alias && *alias; alias++) - if (!strcmp (var_name, *alias) && (hash->cvar->flags & neededflags)) - return hash->cvar; + for (hash = cvars->hashtable[hashindex];hash;hash = hash->hnext) + if (!strcmp (var_name, hash->name) && (hash->flags & neededflags)) + return hash; return NULL; } @@ -59,54 +55,22 @@ cvar_t *Cvar_FindVarAfter(cvar_state_t *cvars, const char *prev_var_name, int ne var = Cvar_FindVar(cvars, prev_var_name, neededflags); if (!var) return NULL; - var = var->next; + var = List_Next_Entry(var->parent ? var->parent : var, list); } else var = cvars->vars; // search for the next cvar matching the needed flags - while (var) + List_For_Each_Entry_From(var, &cvars->vars->list, list) { + if (var->parent) + continue; if (var->flags & neededflags) break; - var = var->next; } return var; } -static cvar_t *Cvar_FindVarLink(cvar_state_t *cvars, const char *var_name, cvar_t **parent, cvar_t ***link, cvar_t **prev_alpha, int neededflags) -{ - int hashindex; - cvar_hash_t *hash; - - // use hash lookup to minimize search time - hashindex = CRC_Block((const unsigned char *)var_name, strlen(var_name)) % CVAR_HASHSIZE; - if(parent) *parent = NULL; - if(prev_alpha) *prev_alpha = NULL; - if(link) *link = &cvars->hashtable[hashindex]->cvar; - for (hash = cvars->hashtable[hashindex];hash;hash = hash->next) - { - if (!strcmp (var_name, hash->cvar->name) && (hash->cvar->flags & neededflags)) - goto match; - else - for (char **alias = hash->cvar->aliases; alias && *alias; alias++) - if (!strcmp (var_name, *alias) && (hash->cvar->flags & neededflags)) - goto match; - if(parent) *parent = hash->cvar; - } - return NULL; -match: - if(!prev_alpha || hash->cvar == cvars->vars) - return hash->cvar; - - *prev_alpha = cvars->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 != hash->cvar) - *prev_alpha = (*prev_alpha)->next; - return hash->cvar; -} - /* ============ Cvar_VariableValue @@ -119,7 +83,7 @@ float Cvar_VariableValueOr(cvar_state_t *cvars, const char *var_name, float def, var = Cvar_FindVar(cvars, var_name, neededflags); if (!var) return def; - return atof (var->string); + return atof (var->parent ? var->parent->string : var->string); } float Cvar_VariableValue(cvar_state_t *cvars, const char *var_name, int neededflags) @@ -139,7 +103,7 @@ const char *Cvar_VariableStringOr(cvar_state_t *cvars, const char *var_name, con var = Cvar_FindVar(cvars, var_name, neededflags); if (!var) return def; - return var->string; + return var->parent ? var->parent->string : var->string; } const char *Cvar_VariableString(cvar_state_t *cvars, const char *var_name, int neededflags) @@ -159,7 +123,7 @@ const char *Cvar_VariableDefString(cvar_state_t *cvars, const char *var_name, in var = Cvar_FindVar(cvars, var_name, neededflags); if (!var) return cvar_null_string; - return var->defstring; + return var->parent ? var->parent->defstring : var->defstring; } /* @@ -194,14 +158,13 @@ const char *Cvar_CompleteVariable(cvar_state_t *cvars, const char *partial, int return NULL; // check functions - for (cvar=cvars->vars ; cvar ; cvar=cvar->next) + List_For_Each_Entry(cvar, &cvars->vars->list, list) if (!strncasecmp (partial,cvar->name, len) && (cvar->flags & neededflags)) return cvar->name; return NULL; } - /* CVar_CompleteCountPossible @@ -223,14 +186,9 @@ int Cvar_CompleteCountPossible(cvar_state_t *cvars, const char *partial, int nee return 0; // Loop through the cvars and count all possible matches - for (cvar = cvars->vars; cvar; cvar = cvar->next) + List_For_Each_Entry(cvar, &cvars->vars->list, list) if (!strncasecmp(partial, cvar->name, len) && (cvar->flags & neededflags)) h++; - else - for (char **alias = cvar->aliases; alias && *alias; alias++) - if (!strncasecmp(partial, *alias, len) && (cvar->flags & neededflags)) - h++; - return h; } @@ -254,14 +212,9 @@ const char **Cvar_CompleteBuildList(cvar_state_t *cvars, const char *partial, in len = strlen(partial); buf = (const char **)Mem_Alloc(tempmempool, sizeofbuf + sizeof(const char *)); // Loop through the alias list and print all matches - for (cvar = cvars->vars; cvar; cvar = cvar->next) + List_For_Each_Entry(cvar, &cvars->vars->list, list) if (!strncasecmp(partial, cvar->name, len) && (cvar->flags & neededflags)) buf[bpos++] = cvar->name; - else - for (char **alias = cvar->aliases; alias && *alias; alias++) - if (!strncasecmp(partial, *alias, len) && (cvar->flags & neededflags)) - buf[bpos++] = *alias; - buf[bpos] = NULL; return buf; @@ -288,15 +241,9 @@ void Cvar_CompleteCvarPrint(cvar_state_t *cvars, const char *partial, int needed cvar_t *cvar; size_t len = strlen(partial); // Loop through the command list and print all matches - for (cvar = cvars->vars; cvar; cvar = cvar->next) + List_For_Each_Entry(cvar, &cvars->vars->list, list) if (!strncasecmp(partial, cvar->name, len) && (cvar->flags & neededflags)) - Cvar_PrintHelp(cvar, cvar->name, true); - else - for (char **alias = cvar->aliases; alias && *alias; alias++) - if (!strncasecmp (partial, *alias, len) && (cvar->flags & neededflags)) - Cvar_PrintHelp(cvar, *alias, true); - - + Cvar_PrintHelp(cvar->parent ? cvar->parent : cvar, cvar->name, true); } // check if a cvar is held by some progs @@ -362,8 +309,12 @@ static void Cvar_UpdateAutoCvar(cvar_t *var) void Cvar_UpdateAllAutoCvars(cvar_state_t *cvars) { cvar_t *var; - for (var = cvars->vars ; var ; var = var->next) + List_For_Each_Entry(var, &cvars->vars->list, list) + { + if(var->parent) + continue; Cvar_UpdateAutoCvar(var); + } } void Cvar_Callback(cvar_t *var) @@ -384,14 +335,18 @@ Cvar_Set ============ */ extern cvar_t sv_disablenotify; -static void Cvar_SetQuick_Internal (cvar_t *var, const char *value) +void Cvar_SetQuick (cvar_t *var, const char *value) { - qbool changed; size_t valuelen; - changed = strcmp(var->string, value) != 0; - // LadyHavoc: don't reallocate when there is no change - if (!changed) + if (var == NULL) + { + Con_Print("Cvar_SetQuick: var == NULL\n"); + return; + } + + // Don't reallocate when there is no change + if (!strcmp(var->string, value)) return; // LadyHavoc: don't reallocate when the buffer is the same size @@ -429,20 +384,6 @@ static void Cvar_SetQuick_Internal (cvar_t *var, const char *value) Cvar_Callback(var); } -void Cvar_SetQuick (cvar_t *var, const char *value) -{ - if (var == NULL) - { - Con_Print("Cvar_SetQuick: var == NULL\n"); - return; - } - - if (developer_extra.integer) - Con_DPrintf("Cvar_SetQuick({\"%s\", \"%s\", %i, \"%s\"}, \"%s\");\n", var->name, var->string, var->flags, var->defstring, value); - - Cvar_SetQuick_Internal(var, value); -} - void Cvar_Set(cvar_state_t *cvars, const char *var_name, const char *value) { cvar_t *var; @@ -452,7 +393,7 @@ void Cvar_Set(cvar_state_t *cvars, const char *var_name, const char *value) Con_Printf("Cvar_Set: variable %s not found\n", var_name); return; } - Cvar_SetQuick(var, value); + Cvar_SetQuick(var->parent ? var->parent : var, value); } /* @@ -482,6 +423,32 @@ void Cvar_SetValue(cvar_state_t *cvars, const char *var_name, float value) Cvar_Set(cvars, var_name, val); } +/* +============ +Cvar_Link + +Links a variable to the variable list and hashtable +============ +*/ +static void Cvar_Link(cvar_t *variable, cvar_state_t *cvars) +{ + cvar_t *current; + int hashindex; + + // Link the object in alphanumerical order + List_For_Each_Entry(current, &cvars->vars->list, list) + if(strcmp(current->name, variable->name) > 0) + break; + + List_Add_Tail(&variable->list, ¤t->list); + + // link to head of list in this hash table index + hashindex = CRC_Block((const unsigned char *)variable->name, strlen(variable->name)) % CVAR_HASHSIZE; + variable->hnext = cvars->hashtable[hashindex]; + cvars->hashtable[hashindex] = variable; + variable->hashindex = hashindex; +} + void Cvar_RegisterCallback(cvar_t *variable, void (*callback)(cvar_t *)) { if (variable == NULL) @@ -492,11 +459,25 @@ void Cvar_RegisterCallback(cvar_t *variable, void (*callback)(cvar_t *)) variable->callback = callback; } -void Cvar_RegisterVirtual(cvar_t *variable, const char *name ) +static void Cvar_DeleteVirtual(cvar_t *vcvar) +{ + List_Delete(&vcvar->vlist); + Z_Free((char *)vcvar->name); + Z_Free(vcvar); +} + +static void Cvar_DeleteVirtual_All(cvar_t *var) +{ + cvar_t *vcvar, *vcvar_next; + + List_For_Each_Entry_Safe(vcvar, vcvar_next, &var->vlist, vlist) + Cvar_DeleteVirtual(vcvar); +} + +void Cvar_RegisterVirtual(cvar_t *variable, const char *name) { cvar_state_t *cvars = &cvars_all; - cvar_hash_t *hash; - int hashindex; + cvar_t *vcvar; if(!*name) { @@ -517,56 +498,16 @@ void Cvar_RegisterVirtual(cvar_t *variable, const char *name ) return; } - if(!variable->aliases) - variable->aliases = (char **)Z_Malloc(sizeof(char *) * 2); // For NULL terminator - else - variable->aliases = (char **)Mem_Realloc(zonemempool, variable->aliases, sizeof(char *) * (variable->aliases_size + 1)); - - variable->aliases[variable->aliases_size + 1] = NULL; - - // Add to it - variable->aliases[variable->aliases_size] = (char *)Z_Malloc(strlen(name) + 1); - memcpy(variable->aliases[variable->aliases_size], name, strlen(name) + 1); - variable->aliases_size++; - - // link to head of list in this hash table index - hash = (cvar_hash_t *)Z_Malloc(sizeof(cvar_hash_t)); - hashindex = CRC_Block((const unsigned char *)name, strlen(name)) % CVAR_HASHSIZE; - hash->next = cvars->hashtable[hashindex]; - cvars->hashtable[hashindex] = hash; - hash->cvar = variable; -} - -/* -============ -Cvar_Link + vcvar = (cvar_t *)Z_Malloc(sizeof(cvar_t)); + vcvar->parent = variable; + vcvar->flags = variable->flags; + vcvar->name = (char *)Mem_strdup(zonemempool, name); + vcvar->description = variable->description; -Links a variable to the variable list and hashtable -============ -*/ -static void Cvar_Link(cvar_t *variable, cvar_state_t *cvars) -{ - cvar_t *current, *next; - cvar_hash_t *hash; - int hashindex; - /* - * Link the variable in - * alphanumerical order - */ - for( current = NULL, next = cvars->vars ; next && strcmp( next->name, variable->name ) < 0 ; current = next, next = next->next ) - ; - if(current) - current->next = variable; - else - cvars->vars = variable; - variable->next = next; + // Add to it + List_Add_Tail(&vcvar->vlist, &variable->vlist); - // link to head of list in this hash table index - hash = (cvar_hash_t *)Z_Malloc(sizeof(cvar_hash_t)); - hashindex = CRC_Block((const unsigned char *)variable->name, strlen(variable->name)) % CVAR_HASHSIZE; - hash->next = cvars->hashtable[hashindex]; - hash->cvar = variable; - cvars->hashtable[hashindex] = hash; + Cvar_Link(vcvar, cvars); } /* @@ -579,7 +520,7 @@ Adds a freestanding variable to the variable list. void Cvar_RegisterVariable (cvar_t *variable) { cvar_state_t *cvars = NULL; - cvar_t *current, *cvar; + cvar_t *cvar; int i; switch (variable->flags & (CF_CLIENT | CF_SERVER)) @@ -622,19 +563,7 @@ void Cvar_RegisterVariable (cvar_t *variable) memcpy(variable->globaldefindex, cvar->globaldefindex, sizeof(variable->globaldefindex)); memcpy(variable->globaldefindex_stringno, cvar->globaldefindex_stringno, sizeof(variable->globaldefindex_stringno)); // replace cvar with this one... - variable->next = cvar->next; - if (cvars->vars == cvar) - { - // head of the list is easy to change - cvars->vars = variable; - } - else - { - // otherwise find it somewhere in the list - for (current = cvars->vars;current->next != cvar;current = current->next) - ; - current->next = variable; - } + List_Replace(&cvar->list, &variable->list); // get rid of old allocated cvar // (but not cvar->string and cvar->defstring, because we kept those) @@ -659,9 +588,9 @@ void Cvar_RegisterVariable (cvar_t *variable) variable->defstring = (char *)Mem_strdup(zonemempool, variable->string); variable->value = atof (variable->string); variable->integer = (int) variable->value; - variable->aliases = NULL; - variable->aliases_size = 0; variable->initstate = NULL; + variable->parent = NULL; + variable->vlist.next = variable->vlist.prev = &variable->vlist; // Mark it as not an autocvar. for (i = 0;i < PRVM_PROG_MAX;i++) @@ -685,12 +614,25 @@ cvar_t *Cvar_Get(cvar_state_t *cvars, const char *name, const char *value, int f if (developer_extra.integer) Con_DPrintf("Cvar_Get(\"%s\", \"%s\", %i);\n", name, value, flags); + // check for pure evil + if (!*name) + { + Con_Printf("Cvar_Get: invalid variable name\n"); + return NULL; + } + // first check to see if it has already been defined cvar = Cvar_FindVar(cvars, name, ~0); if (cvar) { + if(cvar->parent) + { + List_Delete(&cvar->vlist); + cvar->parent = NULL; + } + cvar->flags |= flags; - Cvar_SetQuick_Internal (cvar, value); + Cvar_SetQuick (cvar, value); if(newdescription && (cvar->flags & CF_ALLOCATED)) { if(cvar->description != cvar_dummy_description) @@ -704,13 +646,6 @@ cvar_t *Cvar_Get(cvar_state_t *cvars, const char *name, const char *value, int f return cvar; } - // check for pure evil - if (!*name) - { - Con_Printf("Cvar_Get: invalid variable name\n"); - return NULL; - } - // check for overlap with a command if (Cmd_Exists(cmd_local, name)) { @@ -728,9 +663,9 @@ cvar_t *Cvar_Get(cvar_state_t *cvars, const char *name, const char *value, int f cvar->defstring = (char *)Mem_strdup(zonemempool, value); cvar->value = atof (cvar->string); cvar->integer = (int) cvar->value; - cvar->aliases = NULL; - cvar->aliases_size = 0; cvar->initstate = NULL; + cvar->parent = NULL; + cvar->vlist.next = cvar->vlist.prev = &cvar->vlist; if(newdescription && *newdescription) cvar->description = (char *)Mem_strdup(zonemempool, newdescription); @@ -746,6 +681,35 @@ cvar_t *Cvar_Get(cvar_state_t *cvars, const char *name, const char *value, int f return cvar; } +static void Cvar_Delete(cvar_t *cvar) +{ + cvar_state_t *cvars = &cvars_all; + + List_Delete(&cvar->list); + + for (cvar_t *hash = cvars->hashtable[cvar->hashindex]; hash->hnext != hash; hash = hash->hnext) + { + if(hash->hnext == cvar) + { + hash->hnext = cvar->hnext; + break; + } + } + + Cvar_DeleteVirtual_All(cvar); + + if(cvar->flags & CF_ALLOCATED) + { + if(cvar->description != cvar_dummy_description) + Z_Free((char *)cvar->description); + + Z_Free((char *)cvar->name); + Z_Free((char *)cvar->string); + Z_Free((char *)cvar->defstring); + Z_Free(cvar); + } +} + qbool Cvar_Readonly (cvar_t *var, const char *cmd_name) { if (var->flags & CF_READONLY) @@ -766,30 +730,30 @@ Cvar_Command Handles variable inspection and changing from the console ============ */ -qbool Cvar_Command (cmd_state_t *cmd) +qbool Cvar_Command (cmd_state_t *cmd) { - cvar_state_t *cvars = cmd->cvars; - cvar_t *v; + cvar_state_t *cvars = cmd->cvars; + cvar_t *var; // check variables - v = Cvar_FindVar(cvars, Cmd_Argv(cmd, 0), (cmd->cvars_flagsmask)); - if (!v) + var = Cvar_FindVar(cvars, Cmd_Argv(cmd, 0), (cmd->cvars_flagsmask)); + if (!var) return false; // perform a variable print or set if (Cmd_Argc(cmd) == 1) { - Cvar_PrintHelp(v, Cmd_Argv(cmd, 0), true); + Cvar_PrintHelp(var->parent ? var->parent : var, Cmd_Argv(cmd, 0), true); return true; } if (developer_extra.integer) Con_DPrint("Cvar_Command: "); - if(Cvar_Readonly(v, NULL)) + if(Cvar_Readonly(var, NULL)) return true; - Cvar_SetQuick(v, Cmd_Argv(cmd, 1)); + Cvar_SetQuick(var->parent ? var->parent : var, Cmd_Argv(cmd, 1)); if (developer_extra.integer) Con_DPrint("\n"); return true; @@ -800,7 +764,7 @@ void Cvar_UnlockDefaults(cmd_state_t *cmd) cvar_state_t *cvars = cmd->cvars; cvar_t *var; // unlock the default values of all cvars - for (var = cvars->vars ; var ; var = var->next) + List_For_Each_Entry(var, &cvars->vars->list, list) var->flags &= ~CF_DEFAULTSET; } @@ -809,9 +773,9 @@ void Cvar_LockDefaults_f(cmd_state_t *cmd) cvar_state_t *cvars = cmd->cvars; cvar_t *var; // lock in the default values of all cvars - for (var = cvars->vars ; var ; var = var->next) + List_For_Each_Entry(var, &cvars->vars->list, list) { - if (!(var->flags & CF_DEFAULTSET)) + if (!var->parent && !(var->flags & CF_DEFAULTSET)) { size_t alloclen; @@ -827,87 +791,81 @@ void Cvar_LockDefaults_f(cmd_state_t *cmd) void Cvar_SaveInitState(cvar_state_t *cvars) { - cvar_t *c; - for (c = cvars->vars;c;c = c->next) + cvar_t *cvar, *vcvar; + + List_For_Each_Entry(cvar, &cvars->vars->list, list) { - c->initstate = (cvar_t *)Z_Malloc(sizeof(cvar_t)); - memcpy(c->initstate, c, sizeof(cvar_t)); + // Get the the virtual cvars separately + if(cvar->parent) + continue; + + cvar->initstate = (cvar_t *)Z_Malloc(sizeof(cvar_t)); + memcpy(cvar->initstate, cvar, sizeof(cvar_t)); + + /* + * Consider any virtual cvar created up to this point as + * existing during init. Use the initstate of the parent cvar. + */ + List_For_Each_Entry(vcvar, &cvar->vlist, list) + vcvar->initstate = cvar->initstate; } } void Cvar_RestoreInitState(cvar_state_t *cvars) { - int hashindex; - cvar_t *c, **cp; - cvar_t *c2, **cp2; - for (cp = &cvars->vars;(c = *cp);) + cvar_t *var/*, *vcvar*/, *next/*, *vnext*/; + + List_For_Each_Entry_Safe(var, next, &cvars->vars->list, list) { - if (c->initstate) + // Ignore virtual cvars + if(var->parent) + continue; + + // Cloudwalk FIXME: This crashes for some reason, so it's disabled for now. + + // Destroy all virtual cvars that didn't exist at init + //List_For_Each_Entry_Safe(vcvar, vnext, &var->vlist, vlist) + // if(!vcvar->initstate) + // Cvar_DeleteVirtual(vcvar); + + if (var->initstate) { // restore this cvar, it existed at init - if (((c->flags ^ c->initstate->flags) & CF_MAXFLAGSVAL) - || strcmp(c->defstring ? c->defstring : "", c->initstate->defstring ? c->initstate->defstring : "") - || strcmp(c->string ? c->string : "", c->initstate->string ? c->initstate->string : "")) + if (((var->flags ^ var->initstate->flags) & CF_MAXFLAGSVAL) + || strcmp(var->defstring ? var->defstring : "", var->initstate->defstring ? var->initstate->defstring : "") + || strcmp(var->string ? var->string : "", var->initstate->string ? var->initstate->string : "")) { - Con_DPrintf("Cvar_RestoreInitState: Restoring cvar \"%s\"\n", c->name); - if (c->defstring) - Z_Free((char *)c->defstring); - c->defstring = Mem_strdup(zonemempool, c->initstate->defstring); - if (c->string) - Z_Free((char *)c->string); - c->string = Mem_strdup(zonemempool, c->initstate->string); + Con_DPrintf("Cvar_RestoreInitState: Restoring cvar \"%s\"\n", var->name); + if (var->defstring) + Z_Free((char *)var->defstring); + var->defstring = Mem_strdup(zonemempool, var->initstate->defstring); + if (var->string) + Z_Free((char *)var->string); + var->string = Mem_strdup(zonemempool, var->initstate->string); } - c->flags = c->initstate->flags; - c->value = c->initstate->value; - c->integer = c->initstate->integer; - VectorCopy(c->initstate->vector, c->vector); - cp = &c->next; + var->flags = var->initstate->flags; + var->value = var->initstate->value; + var->integer = var->initstate->integer; + VectorCopy(var->initstate->vector, var->vector); + } else { - if (!(c->flags & CF_ALLOCATED)) - { - Con_DPrintf("Cvar_RestoreInitState: Unable to destroy cvar \"%s\", it was registered after init!\n", c->name); - // In this case, at least reset it to the default. - if((c->flags & CF_PERSISTENT) == 0) - Cvar_SetQuick(c, c->defstring); - cp = &c->next; - continue; - } - if (Cvar_IsAutoCvar(c)) + if (!(var->flags & CF_ALLOCATED)) + Con_DPrintf("Cvar_RestoreInitState: Unable to destroy cvar \"%s\", it was registered after init!\n", var->name); + else if (Cvar_IsAutoCvar(var)) + Con_DPrintf("Cvar_RestoreInitState: Unable to destroy cvar \"%s\", it is an autocvar used by running progs!\n", var->name); + else { - Con_DPrintf("Cvar_RestoreInitState: Unable to destroy cvar \"%s\", it is an autocvar used by running progs!\n", c->name); - // In this case, at least reset it to the default. - if((c->flags & CF_PERSISTENT) == 0) - Cvar_SetQuick(c, c->defstring); - cp = &c->next; + // remove this cvar, it did not exist at init + Con_DPrintf("Cvar_RestoreInitState: Destroying cvar \"%s\"\n", var->name); + Cvar_Delete(var); continue; } - // remove this cvar, it did not exist at init - Con_DPrintf("Cvar_RestoreInitState: Destroying cvar \"%s\"\n", c->name); - // unlink struct from hash - hashindex = CRC_Block((const unsigned char *)c->name, strlen(c->name)) % CVAR_HASHSIZE; - for (cp2 = &cvars->hashtable[hashindex]->cvar;(c2 = *cp2);) - { - if (c2 == c) - { - *cp2 = cvars->hashtable[hashindex]->next->cvar; - break; - } - else - cp2 = &cvars->hashtable[hashindex]->next->cvar; - } - // unlink struct from main list - *cp = c->next; - // free strings - if (c->defstring) - Z_Free((char *)c->defstring); - if (c->string) - Z_Free((char *)c->string); - if (c->description && c->description != cvar_dummy_description) - Z_Free((char *)c->description); - // free struct - Z_Free(c); + + // At least reset it to the default. + if((var->flags & CF_PERSISTENT) == 0) + Cvar_SetQuick(var, var->defstring); } } } @@ -917,9 +875,9 @@ void Cvar_ResetToDefaults_All_f(cmd_state_t *cmd) cvar_state_t *cvars = cmd->cvars; cvar_t *var; // restore the default values of all cvars - for (var = cvars->vars ; var ; var = var->next) + List_For_Each_Entry(var, &cvars->vars->list, list) { - if((var->flags & CF_PERSISTENT) == 0) + if(!var->parent && !(var->flags & CF_PERSISTENT)) Cvar_SetQuick(var, var->defstring); } } @@ -929,22 +887,21 @@ void Cvar_ResetToDefaults_NoSaveOnly_f(cmd_state_t *cmd) cvar_state_t *cvars = cmd->cvars; cvar_t *var; // restore the default values of all cvars - for (var = cvars->vars ; var ; var = var->next) + List_For_Each_Entry(var, &cvars->vars->list, list) { - if ((var->flags & (CF_PERSISTENT | CF_ARCHIVE)) == 0) + if (!var->parent && !(var->flags & (CF_PERSISTENT | CF_ARCHIVE))) Cvar_SetQuick(var, var->defstring); } } - void Cvar_ResetToDefaults_SaveOnly_f(cmd_state_t *cmd) { cvar_state_t *cvars = cmd->cvars; cvar_t *var; // restore the default values of all cvars - for (var = cvars->vars ; var ; var = var->next) + List_For_Each_Entry(var, &cvars->vars->list, list) { - if ((var->flags & (CF_PERSISTENT | CF_ARCHIVE)) == CF_ARCHIVE) + if (!var->parent && (var->flags & (CF_PERSISTENT | CF_ARCHIVE)) == CF_ARCHIVE) Cvar_SetQuick(var, var->defstring); } } @@ -963,7 +920,10 @@ void Cvar_WriteVariables (cvar_state_t *cvars, qfile_t *f) char buf1[MAX_INPUTLINE], buf2[MAX_INPUTLINE]; // don't save cvars that match their default value - for (var = cvars->vars ; var ; var = var->next) { + List_For_Each_Entry(var, &cvars->vars->list, list) + { + if(var->parent) + continue; if ((var->flags & CF_ARCHIVE) && (strcmp(var->string, var->defstring) || ((var->flags & CF_ALLOCATED) && !(var->flags & CF_DEFAULTSET)))) { Cmd_QuoteString(buf1, sizeof(buf1), var->name, "\"\\$", false); @@ -1003,21 +963,13 @@ void Cvar_List_f(cmd_state_t *cmd) } count = 0; - for (cvar = cvars->vars; cvar; cvar = cvar->next) + List_For_Each_Entry(cvar, &cvars->vars->list, list) { if (matchpattern_with_separator(cvar->name, partial, false, "", false)) { - Cvar_PrintHelp(cvar, cvar->name, true); + Cvar_PrintHelp(cvar->parent ? cvar->parent : cvar, cvar->name, true); count++; } - for (char **alias = cvar->aliases; alias && *alias; alias++) - { - if (matchpattern_with_separator(*alias, partial, false, "", false)) - { - Cvar_PrintHelp(cvar, *alias, true); - count++; - } - } } if (Cmd_Argc(cmd) > 1) @@ -1087,8 +1039,7 @@ void Cvar_Del_f(cmd_state_t *cmd) cvar_state_t *cvars = cmd->cvars; int neededflags = ~0; int i; - cvar_t *parent, **link; - cvar_t *cvar, *prev; + cvar_t *cvar; if(Cmd_Argc(cmd) < 2) { @@ -1097,7 +1048,7 @@ void Cvar_Del_f(cmd_state_t *cmd) } for(i = 1; i < Cmd_Argc(cmd); ++i) { - cvar = Cvar_FindVarLink(cvars, Cmd_Argv(cmd, i), &parent, &link, &prev, neededflags); + cvar = Cvar_FindVar(cvars, Cmd_Argv(cmd, i), neededflags); if(!cvar) { @@ -1111,28 +1062,7 @@ void Cvar_Del_f(cmd_state_t *cmd) Con_Printf("%s: %s is static and cannot be deleted\n", Cmd_Argv(cmd, 0), cvar->name); continue; } - if(cvar == cvars->vars) - { - cvars->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->next = cvar->next; - else if(link) - *link = cvar->next; - if(cvar->description != cvar_dummy_description) - Z_Free((char *)cvar->description); - - Z_Free((char *)cvar->name); - Z_Free((char *)cvar->string); - Z_Free((char *)cvar->defstring); - Z_Free(cvar); + Cvar_Delete(cvar); } } diff --git a/cvar.h b/cvar.h index 92ea81cd..c1690f16 100644 --- a/cvar.h +++ b/cvar.h @@ -59,6 +59,8 @@ interface from being ambiguous. #include "qtypes.h" #include "qdefs.h" +#include "com_list.h" + struct cmd_state_s; struct qfile_s; @@ -78,27 +80,22 @@ typedef struct cvar_s void (*callback)(struct cvar_s *var); - char **aliases; - int aliases_size; + int globaldefindex[3]; + int globaldefindex_stringno[3]; + + int hashindex; // Index in hash table, to avoid looking up a cvar twice when unlinking struct cvar_s *initstate; // snapshot of cvar during init - int globaldefindex[3]; - int globaldefindex_stringno[3]; + struct cvar_s *parent, *hnext; - struct cvar_s *next; + llist_t list, vlist; } cvar_t; -typedef struct cvar_hash_s -{ - cvar_t *cvar; - struct cvar_hash_s *next; -} cvar_hash_t; - typedef struct cvar_state_s { cvar_t *vars; - cvar_hash_t *hashtable[CVAR_HASHSIZE]; + cvar_t *hashtable[CVAR_HASHSIZE]; } cvar_state_t; diff --git a/prvm_cmds.c b/prvm_cmds.c index 07adabf3..9606c687 100644 --- a/prvm_cmds.c +++ b/prvm_cmds.c @@ -4619,7 +4619,7 @@ void VM_buf_cvarlist(prvm_prog_t *prog) antiispattern = antipartial && (strchr(antipartial, '*') || strchr(antipartial, '?')); n = 0; - for(cvar = prog->console_cmd->cvars->vars; cvar; cvar = cvar->next) + List_For_Each_Entry(cvar, &prog->console_cmd->cvars->vars->list, list) { if(len && (ispattern ? !matchpattern_with_separator(cvar->name, partial, false, "", false) : strncmp(partial, cvar->name, len))) continue; @@ -4635,7 +4635,7 @@ void VM_buf_cvarlist(prvm_prog_t *prog) stringbuffer->strings = (char **)Mem_Alloc(prog->progs_mempool, sizeof(stringbuffer->strings[0]) * stringbuffer->max_strings); n = 0; - for(cvar = prog->console_cmd->cvars->vars; cvar; cvar = cvar->next) + List_For_Each_Entry(cvar, &prog->console_cmd->cvars->vars->list, list) { if(len && (ispattern ? !matchpattern_with_separator(cvar->name, partial, false, "", false) : strncmp(partial, cvar->name, len))) continue; diff --git a/prvm_edict.c b/prvm_edict.c index 3c50397e..27226b38 100644 --- a/prvm_edict.c +++ b/prvm_edict.c @@ -2573,7 +2573,7 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char * filename, unsigned char * da } } - for (cvar = prog->console_cmd->cvars->vars; cvar; cvar = cvar->next) + List_For_Each_Entry(cvar, &prog->console_cmd->cvars->vars->list, list) cvar->globaldefindex[prog - prvm_prog_list] = -1; for (i=0 ; inumglobaldefs ; i++)