// disconnect --> void Cvar_UnSet (qbool use_regex) { cvar_t *var, *next; char *name; int i; qbool re_search = false; if (Cmd_Argc() < 2) { Com_Printf ("unset <cvar> [<cvar2>..]: erase user-created variable\n"); return; } for (i=1; i<Cmd_Argc(); i++) { name = Cmd_Argv(i); if (use_regex && (re_search = IsRegexp(name))) if(!ReSearchInit(name)) continue; if (use_regex && re_search) { for (var = cvar_vars ; var ; var = next) { next = var->next; if (ReSearchMatch(var->name)) { if (var->flags & CVAR_USER_CREATED) { Cvar_Delete(var->name); } else { Com_Printf("Can't delete not user created cvars (\"%s\")\n", var->name); } } } } else { if (!(var = Cvar_Find(name))) { Com_Printf("Can't delete \"%s\": no such cvar\n", name); continue; } if (var->flags & CVAR_USER_CREATED) { Cvar_Delete(name); } else { Com_Printf("Can't delete not user created cvars (\"%s\")\n", name); } } if (use_regex && re_search) ReSearchDone(); } }
/* ============ Cvar_Register Adds a freestanding variable to the variable list. If the variable already exists, the value will not be set The flags will be or'ed in if the variable exists. ============ */ EXTERNC void Cvar_Register (cvar_t *var) { char string[512]; int key; cvar_t *old; // first check to see if it has already been defined old = Cvar_Find (var->name); if (old && !(old->flags & CVAR_DYNAMIC)) { if (old == var) return; Com_Printf ("Can't register variable %s, already defined\n", var->name); return; } #if 0 // check for overlap with a command if (Cmd_Exists (var->name)) { Com_Printf ("Cvar_Register: %s is a command\n", var->name); return; } #endif if (old) { var->flags |= old->flags & ~(CVAR_DYNAMIC|CVAR_TEMP); strlcpy (string, old->string, sizeof(string)); Cvar_Delete (old->name); if (!(var->flags & CVAR_ROM)) var->string = Q_strdup (string); else var->string = Q_strdup (var->string); } else { // allocate the string on heap because future sets will Q_free it var->string = Q_strdup (var->string); } var->value = Q_atof (var->string); // link the variable in key = Com_HashKey (var->name); var->hash_next = cvar_hash[key]; cvar_hash[key] = var; var->next = cvar_vars; cvar_vars = var; #ifndef CLIENTONLY if (var->flags & CVAR_SERVERINFO) SV_ServerinfoChanged (var->name, var->string); #endif #ifndef SERVERONLY if (var->flags & CVAR_USERINFO) CL_UserinfoChanged (var->name, var->string); #endif }
// if none of the subsystems claimed the cvar from config.cfg, remove it void Cvar_CleanUpTempVars (void) { cvar_t *var, *next; for (var = cvar_vars; var; var = next) { next = var->next; if (var->flags & CVAR_TEMP) Cvar_Delete (var->name); } }
static void DeleteUserVariables(void) { cvar_t *var, *next; for (var = cvar_vars; var; var = next) { next = var->next; if (var->flags & CVAR_USER_CREATED) Cvar_Delete(var->name); } }
/** * @brief Delete a cvar - set [cvar] "" isn't working from within the scripts * @sa Cvar_Set_f */ static void Cvar_Del_f (void) { int c; c = Cmd_Argc(); if (c != 2) { Com_Printf("Usage: %s <variable>\n", Cmd_Argv(0)); return; } Cvar_Delete(Cmd_Argv(1)); }
/* Adds a freestanding variable to the variable list. If the variable already exists, the value will not be set The flags will be or'ed in if the variable exists. */ void Cvar_Register (cvar_t *var) { char string[512]; int key; cvar_t *old; // first check to see if it has already been defined old = Cvar_Find (var->name); // we alredy register cvar, warn about it if (old && !(old->flags & CVAR_USER_CREATED)) { // allow re-register lacthed cvar if (old->flags & CVAR_LATCH) { // if we have a latched string, take that value now if ( old->latchedString ) { // I did't want bother with all this CVAR_ROM and OnChange handler, just set value Q_free(old->string); old->string = old->latchedString; old->latchedString = NULL; old->value = Q_atof (old->string); old->integer = Q_atoi (old->string); StringToRGB_W(old->string, old->color); old->modified = true; } Cvar_AutoReset(old); return; } // warn if CVAR_SILENT is not set if (!(old->flags & CVAR_SILENT)) Com_Printf ("Can't register variable %s, already defined\n", var->name); return; } if (old && old == var) Sys_Error("Cvar_Register: something wrong with %s", var->name); /* // check for overlap with a command if (Cmd_Exists (var->name)) { Com_Printf ("Cvar_Register: %s is a command\n", var->name); return; } */ if (var->defaultvalue) Sys_Error("Cvar_Register: defaultvalue alredy set for %s", var->name); var->defaultvalue = Q_strdup(var->string); if (old) { var->flags |= old->flags & ~(CVAR_USER_CREATED|CVAR_TEMP); strlcpy (string, (var->flags & CVAR_ROM) ? var->string : old->string, sizeof(string)); Cvar_Delete (old->name); var->string = Q_strdup(string); } else { // allocate the string on zone because future sets will Q_freeit var->string = Q_strdup(var->string); } var->value = Q_atof (var->string); var->integer = Q_atoi (var->string); StringToRGB_W(var->string, var->color); var->modified = true; // link the variable in key = Com_HashKey (var->name) % VAR_HASHPOOL_SIZE; var->hash_next = cvar_hash[key]; cvar_hash[key] = var; var->next = cvar_vars; cvar_vars = var; #ifdef WITH_TCL TCL_RegisterVariable (var); #endif Cvar_AddCvarToGroup(var); #ifndef CLIENTONLY if (var->flags & CVAR_SERVERINFO) SV_ServerinfoChanged (var->name, var->string); #endif if (var->flags & CVAR_USERINFO) CL_UserinfoChanged (var->name, var->string); }
/** * @brief Execute an action from a source * @param[in] context Context node * @param[in] action Action to execute */ static void UI_ExecuteAction (const uiAction_t* action, uiCallContext_t *context) { switch (action->type) { case EA_NULL: /* do nothing */ break; case EA_CMD: /* execute a command */ if (action->d.terminal.d1.constString) Cbuf_AddText(UI_GenInjectedString(action->d.terminal.d1.constString, true, context)); break; case EA_CALL: case EA_LISTENER: UI_ExecuteCallAction(action, context); break; case EA_POPVARS: { int i; const int number = action->d.terminal.d1.integer; assert(number <= context->varNumber); for (i = 0; i < number; i++) { const int varId = context->varPosition + context->varNumber - i - 1; UI_ReleaseVariable(&(ui_global.variableStack[varId])); } context->varNumber -= number; } break; case EA_PUSHVARS: #ifdef DEBUG /* check sanity */ /** @todo check var slots should be empty */ #endif context->varNumber += action->d.terminal.d1.integer; if (context->varNumber >= UI_MAX_VARIABLESTACK) Com_Error(ERR_FATAL, "UI_ExecuteAction: Variable stack full. UI_MAX_VARIABLESTACK hit."); break; case EA_ASSIGN: UI_ExecuteSetAction(action, context); break; case EA_DELETE: { const char* cvarname = action->d.nonTerminal.left->d.terminal.d1.constString; Cvar_Delete(cvarname); break; } case EA_WHILE: { int loop = 0; while (UI_GetBooleanFromExpression(action->d.nonTerminal.left, context)) { UI_ExecuteActions(action->d.nonTerminal.right, context); if (loop > 1000) { Com_Printf("UI_ExecuteAction: Infinite loop. Force breaking 'while'\n"); break; } loop++; } break; } case EA_IF: if (UI_GetBooleanFromExpression(action->d.nonTerminal.left, context)) { UI_ExecuteActions(action->d.nonTerminal.right, context); return; } action = action->next; while (action && action->type == EA_ELIF) { if (UI_GetBooleanFromExpression(action->d.nonTerminal.left, context)) { UI_ExecuteActions(action->d.nonTerminal.right, context); return; } action = action->next; } if (action && action->type == EA_ELSE) { UI_ExecuteActions(action->d.nonTerminal.right, context); } break; /** @todo Skipping actions like that is a bad way. the function should return the next action, * or we should move IF,ELSE,ELIF... in a IF block and not interleave it with default actions */ case EA_ELSE: case EA_ELIF: /* previous EA_IF execute this action */ break; default: Com_Error(ERR_FATAL, "UI_ExecuteAction: Unknown action type %i", action->type); } }
void Cmd_Alias_f (void) { cmd_alias_t *a; char cmd[1024]; int i, c; int key; char *s; // cvar_t *var; c = Cmd_Argc(); if (c == 1) { Con_Printf ("Current alias commands:\n"); for (a = cmd_alias ; a ; a=a->next) Con_Printf ("%s : %s\n\n", a->name, a->value); return; } s = Cmd_Argv(1); if (strlen(s) >= MAX_ALIAS_NAME) { Con_Printf ("Alias name is too long\n"); return; } #if 0 if ( (var = Cvar_Find(s)) != NULL ) { if (var->flags & CVAR_USER_CREATED) Cvar_Delete (var->name); else { // Con_Printf ("%s is a variable\n"); return; } } #endif key = Com_HashKey (s); // if the alias already exists, reuse it for (a = cmd_alias_hash[key] ; a ; a=a->hash_next) { if (!strcasecmp(a->name, s)) { Q_free (a->value); break; } } if (!a) { a = (cmd_alias_t*) Q_malloc (sizeof(cmd_alias_t)); a->next = cmd_alias; cmd_alias = a; a->hash_next = cmd_alias_hash[key]; cmd_alias_hash[key] = a; } strlcpy (a->name, s, MAX_ALIAS_NAME); // copy the rest of the command line cmd[0] = 0; // start out with a null string for (i=2 ; i<c ; i++) { if (i > 2) strlcat (cmd, " ", sizeof(cmd)); strlcat (cmd, Cmd_Argv(i), sizeof(cmd)); } a->value = Q_strdup (cmd); }
/** * @brief Execute an action from a source * @param[in] context Context node * @param[in] action Action to execute */ static void UI_ExecuteAction (const uiAction_t* action, uiCallContext_t* context) { switch (action->type) { case EA_NULL: /* do nothing */ break; case EA_CMD: /* execute a command */ if (action->d.terminal.d1.constString) Cbuf_AddText("%s\n", UI_GenInjectedString(action->d.terminal.d1.constString, true, context)); break; case EA_CALL: case EA_LISTENER: UI_ExecuteCallAction(action, context); break; case EA_POPVARS: { const int number = action->d.terminal.d1.integer; assert(number <= context->varNumber); for (int i = 0; i < number; i++) { const int varId = context->varPosition + context->varNumber - i - 1; UI_ReleaseVariable(&(ui_global.variableStack[varId])); } context->varNumber -= number; } break; case EA_PUSHVARS: #ifdef DEBUG /* check sanity */ /** @todo check var slots should be empty */ #endif context->varNumber += action->d.terminal.d1.integer; if (context->varNumber >= UI_MAX_VARIABLESTACK) Com_Error(ERR_FATAL, "UI_ExecuteAction: Variable stack full. UI_MAX_VARIABLESTACK hit."); break; case EA_ASSIGN: UI_ExecuteSetAction(action, context); break; case EA_DELETE: { const char* cvarname = action->d.nonTerminal.left->d.terminal.d1.constString; Cvar_Delete(cvarname); break; } case EA_WHILE: { int loop = 0; while (UI_GetBooleanFromExpression(action->d.nonTerminal.left, context)) { UI_ExecuteActions(action->d.nonTerminal.right, context); if (context->breakLoop) { context->breakLoop = false; break; } if (loop > 1000) { Com_Printf("UI_ExecuteAction: Infinite loop. Force breaking 'while'\n"); break; } loop++; } break; } /* expected usage in .ufo scripts: forchildin ( *node:someNode ) { ... *node:child <-- reference the child being iterated ... } */ case EA_FORCHILDIN: { uiNode_t* root; root = UI_GetNodeFromExpression(action->d.nonTerminal.left, context, nullptr); if (!root) { break; } int loop = 0; for (uiNode_t* node = root->firstChild; node; node = node->next, loop++) { /* associate the child node with the call context so it can be referenced inside the script block */ context->tagNode = node; /* execute the script block inside the forchildin loop */ UI_ExecuteActions(action->d.nonTerminal.right, context); /* clean the tag node */ context->tagNode = nullptr; if (context->breakLoop) { context->breakLoop = false; break; } if (loop > 1000) { Com_Printf("UI_ExecuteAction: Infinite loop. Force breaking 'forchildin'\n"); break; } } break; } case EA_BREAK: { /* flag to break, the caller must check this flag before processing the next action in the list */ Com_Printf("BREAK: break statement found\n"); context->breakLoop = true; break; } case EA_IF: if (UI_GetBooleanFromExpression(action->d.nonTerminal.left, context)) { UI_ExecuteActions(action->d.nonTerminal.right, context); return; } action = action->next; while (action && action->type == EA_ELIF) { if (UI_GetBooleanFromExpression(action->d.nonTerminal.left, context)) { UI_ExecuteActions(action->d.nonTerminal.right, context); return; } action = action->next; } if (action && action->type == EA_ELSE) { UI_ExecuteActions(action->d.nonTerminal.right, context); } break; /** @todo Skipping actions like that is a bad way. the function should return the next action, * or we should move IF, ELSE, ELIF... in a IF block and not interleave it with default actions */ case EA_ELSE: case EA_ELIF: /* previous EA_IF execute this action */ break; default: Com_Error(ERR_FATAL, "UI_ExecuteAction: Unknown action type %i", action->type); } }