Skip to content

Commit

Permalink
Refactored away the copy of ccmd_t (used during command registration)…
Browse files Browse the repository at this point in the history
… stored in ddcmd_t
  • Loading branch information
danij-deng committed Apr 18, 2011
1 parent 375d766 commit 53752c8
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 35 deletions.
16 changes: 11 additions & 5 deletions doomsday/engine/portable/include/con_main.h
Expand Up @@ -41,7 +41,7 @@

#define OBSOLETE CVF_NO_ARCHIVE|CVF_HIDE

// Macros for accessing the console command values through the shared data ptr.
// Macros for accessing the console variable values through the shared data ptr.
#define CV_INT(var) (*(int*) var->ptr)
#define CV_BYTE(var) (*(byte*) var->ptr)
#define CV_FLOAT(var) (*(float*) var->ptr)
Expand All @@ -60,15 +60,21 @@ typedef struct ddccmd_s {
/// Next and previous overloaded versions of this command (if any).
struct ddccmd_s* nextOverload, *prevOverload;

/// List of argument types for this command.
cvartype_t args[MAX_ARGS];
/// Execute function.
int (*execFunc) (byte src, int argc, char** argv);

/// Name of the command.
const char* name;

/// @see consoleCommandFlags
int flags;

/// Minimum and maximum number of arguments. Used with commands
/// that utilize an engine-validated argument list.
int minArgs, maxArgs;

/// Publicly visible shared data.
ccmd_t shared;
/// List of argument types for this command.
cvartype_t args[MAX_ARGS];
} ddccmd_t;

typedef struct cvar_s {
Expand Down
34 changes: 23 additions & 11 deletions doomsday/engine/portable/src/con_data.c
Expand Up @@ -155,6 +155,9 @@ static cvar_t* addVariable(const cvartemplate_t* tpl)
// Make a static copy of the name in the zone (this allows the source
// data to change in case of dynamic registrations).
{ char* nameCopy = Z_Malloc(strlen(tpl->name) + 1, PU_APPSTATIC, NULL);
if(NULL == nameCopy)
Con_Error("Con_AddVariable: Failed on allocation of %lu bytes for variable name.",
(unsigned long) (strlen(tpl->name) + 1));
strcpy(nameCopy, tpl->name);
newVar->name = nameCopy;
}
Expand Down Expand Up @@ -210,7 +213,7 @@ static const char* getKnownWordName(const knownword_t* word)
assert(word);
switch(word->type)
{
case WT_CCMD: return ((ddccmd_t*)word->data)->shared.name;
case WT_CCMD: return ((ddccmd_t*)word->data)->name;
case WT_CVAR: return ((cvar_t*)word->data)->name;
case WT_CALIAS: return ((calias_t*)word->data)->name;
case WT_GAMEINFO: return Str_Text(GameInfo_IdentityKey((gameinfo_t*)word->data));
Expand Down Expand Up @@ -843,7 +846,7 @@ if(ccmd->args == NULL)
}

// Sanity check.
if(!unique && variant->shared.execFunc == ccmd->execFunc)
if(!unique && variant->execFunc == ccmd->execFunc)
Con_Error("Con_AddCommand: A CCmd by the name '%s' is "
"already registered and the callback funcs are "
"the same, is this really what you wanted?",
Expand All @@ -862,8 +865,17 @@ if(ccmd->args == NULL)
if(!ccmdBlockSet)
ccmdBlockSet = BlockSet_Construct(sizeof(ddccmd_t), 32);
newCCmd = BlockSet_Allocate(ccmdBlockSet);

memcpy(&newCCmd->shared, ccmd, sizeof(newCCmd->shared));
// Make a static copy of the name in the zone (this allows the source
// data to change in case of dynamic registrations).
{ char* nameCopy = Z_Malloc(strlen(ccmd->name) + 1, PU_APPSTATIC, NULL);
if(NULL == nameCopy)
Con_Error("Con_AddCommand: Failed on allocation of %lu bytes for command name.",
(unsigned long) (strlen(ccmd->name) + 1));
strcpy(nameCopy, ccmd->name);
newCCmd->name = nameCopy;
}
newCCmd->execFunc = ccmd->execFunc;
newCCmd->flags = ccmd->flags;
newCCmd->nextOverload = newCCmd->prevOverload = 0;
newCCmd->minArgs = minArgs;
newCCmd->maxArgs = maxArgs;
Expand Down Expand Up @@ -903,7 +915,7 @@ ddccmd_t* Con_FindCommand(const char* name)
{
ddccmd_t* ccmd;
for(ccmd = ccmdListHead; ccmd; ccmd = ccmd->next)
if(!stricmp(name, ccmd->shared.name))
if(!stricmp(name, ccmd->name))
{
// Locate the head of the overload list.
while(ccmd->prevOverload) { ccmd = ccmd->prevOverload; }
Expand Down Expand Up @@ -996,7 +1008,7 @@ void Con_PrintCCmdUsage(ddccmd_t* ccmd, boolean showExtra)
return;

// Print the expected form for this ccmd.
Con_Printf("Usage: %s", ccmd->shared.name);
Con_Printf("Usage: %s", ccmd->name);
{ int i;
for(i = 0; i < ccmd->minArgs; ++i)
{
Expand All @@ -1017,7 +1029,7 @@ void Con_PrintCCmdUsage(ddccmd_t* ccmd, boolean showExtra)
{
// Check for extra info about this ccmd's usage.
char* str;
if((str = DH_GetString(DH_Find(ccmd->shared.name), HST_INFO)))
if((str = DH_GetString(DH_Find(ccmd->name), HST_INFO)))
{
// Lets indent for neatness.
char* line;
Expand Down Expand Up @@ -1272,7 +1284,7 @@ D_CMD(HelpWhat)
if((ccmd = Con_FindCommand(argv[1])) != 0)
{
char* str;
if((str = DH_GetString(DH_Find(ccmd->shared.name), HST_DESCRIPTION)))
if((str = DH_GetString(DH_Find(ccmd->name), HST_DESCRIPTION)))
Con_Printf("%s\n", str);

// Print usage info for each variant.
Expand Down Expand Up @@ -1325,10 +1337,10 @@ static int printKnownWordWorker(const knownword_t* word, void* paramaters)
if(ccmd->prevOverload)
return 0; // Skip overloaded variants.

if((str = DH_GetString(DH_Find(ccmd->shared.name), HST_DESCRIPTION)))
Con_FPrintf(CBLF_LIGHT|CBLF_YELLOW, " %s (%s)\n", ccmd->shared.name, str);
if((str = DH_GetString(DH_Find(ccmd->name), HST_DESCRIPTION)))
Con_FPrintf(CBLF_LIGHT|CBLF_YELLOW, " %s (%s)\n", ccmd->name, str);
else
Con_FPrintf(CBLF_LIGHT|CBLF_YELLOW, " %s\n", ccmd->shared.name);
Con_FPrintf(CBLF_LIGHT|CBLF_YELLOW, " %s\n", ccmd->name);
break;
}
case WT_CVAR: {
Expand Down
38 changes: 19 additions & 19 deletions doomsday/engine/portable/src/con_main.c
Expand Up @@ -689,27 +689,27 @@ static int executeSubCmd(const char *subCmd, byte src, boolean isNetCmd)

// Trying to issue a command requiring a loaded game?
// dj: This should be considered a short-term solution. Ideally we want some namespacing mechanics.
if((ccmd->shared.flags & CMDF_NO_NULLGAME) && DD_IsNullGameInfo(DD_GameInfo()))
if((ccmd->flags & CMDF_NO_NULLGAME) && DD_IsNullGameInfo(DD_GameInfo()))
{
Con_Printf("executeSubCmd: '%s' impossible with no game loaded.\n", ccmd->shared.name);
Con_Printf("executeSubCmd: '%s' impossible with no game loaded.\n", ccmd->name);
return true;
}

// A dedicated server, trying to execute a ccmd not available to us?
if(isDedicated && (ccmd->shared.flags & CMDF_NO_DEDICATED))
if(isDedicated && (ccmd->flags & CMDF_NO_DEDICATED))
{
Con_Printf("executeSubCmd: '%s' impossible in dedicated mode.\n", ccmd->shared.name);
Con_Printf("executeSubCmd: '%s' impossible in dedicated mode.\n", ccmd->name);
return true;
}

// Net commands sent to servers have extra protection.
if(isServer && isNetCmd)
{
// Is the command permitted for use by clients?
if(ccmd->shared.flags & CMDF_CLIENT)
if(ccmd->flags & CMDF_CLIENT)
{
Con_Printf("executeSubCmd: Blocked command. A client attempted to use '%s'.\n"
"This command is not permitted for use by clients\n", ccmd->shared.name);
"This command is not permitted for use by clients\n", ccmd->name);
// \todo Tell the client!
return true;
}
Expand All @@ -736,7 +736,7 @@ static int executeSubCmd(const char *subCmd, byte src, boolean isNetCmd)
Con_Printf("executeSubCmd: Blocked command. A client"
" attempted to use '%s' via %s.\n"
"This invocation method is not permitted "
"by clients\n", ccmd->shared.name, CMDTYPESTR(src));
"by clients\n", ccmd->name, CMDTYPESTR(src));
// \todo Tell the client!
return true;

Expand All @@ -753,42 +753,42 @@ static int executeSubCmd(const char *subCmd, byte src, boolean isNetCmd)
break;

case CMDS_DDAY:
if(ccmd->shared.flags & CMDF_DDAY)
if(ccmd->flags & CMDF_DDAY)
canExecute = false;
break;

case CMDS_GAME:
if(ccmd->shared.flags & CMDF_GAME)
if(ccmd->flags & CMDF_GAME)
canExecute = false;
break;

case CMDS_CONSOLE:
if(ccmd->shared.flags & CMDF_CONSOLE)
if(ccmd->flags & CMDF_CONSOLE)
canExecute = false;
break;

case CMDS_BIND:
if(ccmd->shared.flags & CMDF_BIND)
if(ccmd->flags & CMDF_BIND)
canExecute = false;
break;

case CMDS_CONFIG:
if(ccmd->shared.flags & CMDF_CONFIG)
if(ccmd->flags & CMDF_CONFIG)
canExecute = false;
break;

case CMDS_PROFILE:
if(ccmd->shared.flags & CMDF_PROFILE)
if(ccmd->flags & CMDF_PROFILE)
canExecute = false;
break;

case CMDS_CMDLINE:
if(ccmd->shared.flags & CMDF_CMDLINE)
if(ccmd->flags & CMDF_CMDLINE)
canExecute = false;
break;

case CMDS_SCRIPT:
if(ccmd->shared.flags & CMDF_DED)
if(ccmd->flags & CMDF_DED)
canExecute = false;
break;

Expand All @@ -799,7 +799,7 @@ static int executeSubCmd(const char *subCmd, byte src, boolean isNetCmd)
if(!canExecute)
{
Con_Printf("Error: '%s' cannot be executed via %s.\n",
ccmd->shared.name, CMDTYPESTR(src));
ccmd->name, CMDTYPESTR(src));
return true;
}

Expand All @@ -812,7 +812,7 @@ static int executeSubCmd(const char *subCmd, byte src, boolean isNetCmd)
* this call.
*/
int result;
if((result = ccmd->shared.execFunc(src, args.argc, args.argv)) == false)
if((result = ccmd->execFunc(src, args.argc, args.argv)) == false)
{
Con_Printf("Error: '%s' failed.\n", args.argv[0]);
}
Expand Down Expand Up @@ -1122,7 +1122,7 @@ static int completeWord(int mode)
}
case WT_CCMD: {
ddccmd_t* ccmd = (ddccmd_t*)(*match)->data;
foundWord = ccmd->shared.name;
foundWord = ccmd->name;
if(printCompletions)
Con_FPrintf(CBLF_LIGHT|CBLF_YELLOW, " %s\n", foundWord);
break;
Expand Down Expand Up @@ -1164,7 +1164,7 @@ static int completeWord(int mode)
const char* str;
switch(completeWord->type)
{
case WT_CCMD: str = ((ddccmd_t*)completeWord->data)->shared.name; break;
case WT_CCMD: str = ((ddccmd_t*)completeWord->data)->name; break;
case WT_CVAR: str = ((cvar_t*)completeWord->data)->name; break;
case WT_CALIAS: str = ((calias_t*)completeWord->data)->name; break;
case WT_GAMEINFO: str = Str_Text(GameInfo_IdentityKey((gameinfo_t*)completeWord->data)); break;
Expand Down

0 comments on commit 53752c8

Please sign in to comment.