Annotation of quake2/qcommon/cmd.c, revision 1.1.1.2

1.1       root        1: // cmd.c -- Quake script command processing module
1.1.1.2 ! root        2: 
1.1       root        3: #include "qcommon.h"
1.1.1.2 ! root        4: 
1.1       root        5: void Cmd_ForwardToServer (void);
1.1.1.2 ! root        6: 
1.1       root        7: #define        MAX_ALIAS_NAME  32
1.1.1.2 ! root        8: 
1.1       root        9: typedef struct cmdalias_s
                     10: {
                     11:        struct cmdalias_s       *next;
                     12:        char    name[MAX_ALIAS_NAME];
                     13:        char    *value;
                     14: } cmdalias_t;
1.1.1.2 ! root       15: 
1.1       root       16: cmdalias_t     *cmd_alias;
1.1.1.2 ! root       17: 
1.1       root       18: qboolean       cmd_wait;
1.1.1.2 ! root       19: 
1.1       root       20: #define        ALIAS_LOOP_COUNT        16
                     21: int            alias_count;            // for detecting runaway loops
1.1.1.2 ! root       22: 
        !            23: 
1.1       root       24: //=============================================================================
1.1.1.2 ! root       25: 
1.1       root       26: /*
                     27: ============
                     28: Cmd_Wait_f
1.1.1.2 ! root       29: 
1.1       root       30: Causes execution of the remainder of the command buffer to be delayed until
                     31: next frame.  This allows commands like:
                     32: bind g "impulse 5 ; +attack ; wait ; -attack ; impulse 2"
                     33: ============
                     34: */
                     35: void Cmd_Wait_f (void)
                     36: {
                     37:        cmd_wait = true;
                     38: }
                     39: 
1.1.1.2 ! root       40: 
1.1       root       41: /*
                     42: =============================================================================
1.1.1.2 ! root       43: 
1.1       root       44:                                                COMMAND BUFFER
1.1.1.2 ! root       45: 
1.1       root       46: =============================================================================
                     47: */
1.1.1.2 ! root       48: 
1.1       root       49: sizebuf_t      cmd_text;
                     50: byte           cmd_text_buf[8192];
                     51: 
                     52: byte           defer_text_buf[8192];
1.1.1.2 ! root       53: 
1.1       root       54: /*
                     55: ============
                     56: Cbuf_Init
                     57: ============
                     58: */
                     59: void Cbuf_Init (void)
                     60: {
                     61:        SZ_Init (&cmd_text, cmd_text_buf, sizeof(cmd_text_buf));
                     62: }
                     63: 
                     64: /*
                     65: ============
                     66: Cbuf_AddText
1.1.1.2 ! root       67: 
1.1       root       68: Adds command text at the end of the buffer
                     69: ============
                     70: */
                     71: void Cbuf_AddText (char *text)
                     72: {
                     73:        int             l;
                     74:        
                     75:        l = strlen (text);
1.1.1.2 ! root       76: 
1.1       root       77:        if (cmd_text.cursize + l >= cmd_text.maxsize)
                     78:        {
                     79:                Com_Printf ("Cbuf_AddText: overflow\n");
                     80:                return;
                     81:        }
                     82:        SZ_Write (&cmd_text, text, strlen (text));
                     83: }
1.1.1.2 ! root       84: 
        !            85: 
1.1       root       86: /*
                     87: ============
                     88: Cbuf_InsertText
1.1.1.2 ! root       89: 
1.1       root       90: Adds command text immediately after the current command
                     91: Adds a \n to the text
                     92: FIXME: actually change the command buffer to do less copying
                     93: ============
                     94: */
                     95: void Cbuf_InsertText (char *text)
                     96: {
                     97:        char    *temp;
                     98:        int             templen;
1.1.1.2 ! root       99: 
1.1       root      100: // copy off any commands still remaining in the exec buffer
                    101:        templen = cmd_text.cursize;
                    102:        if (templen)
                    103:        {
                    104:                temp = Z_Malloc (templen);
                    105:                memcpy (temp, cmd_text.data, templen);
                    106:                SZ_Clear (&cmd_text);
                    107:        }
                    108:        else
                    109:                temp = NULL;    // shut up compiler
                    110:                
                    111: // add the entire text of the file
                    112:        Cbuf_AddText (text);
                    113:        
                    114: // add the copied off data
                    115:        if (templen)
                    116:        {
                    117:                SZ_Write (&cmd_text, temp, templen);
                    118:                Z_Free (temp);
                    119:        }
                    120: }
                    121: 
1.1.1.2 ! root      122: 
1.1       root      123: /*
                    124: ============
                    125: Cbuf_CopyToDefer
                    126: ============
                    127: */
                    128: void Cbuf_CopyToDefer (void)
                    129: {
                    130:        memcpy(defer_text_buf, cmd_text_buf, cmd_text.cursize);
                    131:        defer_text_buf[cmd_text.cursize] = 0;
                    132:        cmd_text.cursize = 0;
                    133: }
                    134: 
                    135: /*
                    136: ============
                    137: Cbuf_InsertFromDefer
                    138: ============
                    139: */
                    140: void Cbuf_InsertFromDefer (void)
                    141: {
                    142:        Cbuf_InsertText (defer_text_buf);
                    143:        defer_text_buf[0] = 0;
                    144: }
                    145: 
                    146: 
                    147: /*
                    148: ============
                    149: Cbuf_ExecuteText
                    150: ============
                    151: */
                    152: void Cbuf_ExecuteText (int exec_when, char *text)
                    153: {
                    154:        switch (exec_when)
                    155:        {
                    156:        case EXEC_NOW:
                    157:                Cmd_ExecuteString (text);
                    158:                break;
                    159:        case EXEC_INSERT:
                    160:                Cbuf_InsertText (text);
                    161:                break;
                    162:        case EXEC_APPEND:
                    163:                Cbuf_AddText (text);
                    164:                break;
                    165:        default:
                    166:                Com_Error (ERR_FATAL, "Cbuf_ExecuteText: bad exec_when");
                    167:        }
                    168: }
1.1.1.2 ! root      169: 
1.1       root      170: /*
                    171: ============
                    172: Cbuf_Execute
                    173: ============
                    174: */
                    175: void Cbuf_Execute (void)
                    176: {
                    177:        int             i;
                    178:        char    *text;
                    179:        char    line[1024];
                    180:        int             quotes;
                    181: 
                    182:        alias_count = 0;                // don't allow infinite alias loops
1.1.1.2 ! root      183: 
1.1       root      184:        while (cmd_text.cursize)
                    185:        {
                    186: // find a \n or ; line break
                    187:                text = (char *)cmd_text.data;
1.1.1.2 ! root      188: 
1.1       root      189:                quotes = 0;
                    190:                for (i=0 ; i< cmd_text.cursize ; i++)
                    191:                {
                    192:                        if (text[i] == '"')
                    193:                                quotes++;
                    194:                        if ( !(quotes&1) &&  text[i] == ';')
                    195:                                break;  // don't break if inside a quoted string
                    196:                        if (text[i] == '\n')
                    197:                                break;
                    198:                }
                    199:                        
                    200:                                
                    201:                memcpy (line, text, i);
                    202:                line[i] = 0;
                    203:                
                    204: // delete the text from the command buffer and move remaining commands down
                    205: // this is necessary because commands (exec, alias) can insert data at the
                    206: // beginning of the text buffer
1.1.1.2 ! root      207: 
1.1       root      208:                if (i == cmd_text.cursize)
                    209:                        cmd_text.cursize = 0;
                    210:                else
                    211:                {
                    212:                        i++;
                    213:                        cmd_text.cursize -= i;
                    214:                        memmove (text, text+i, cmd_text.cursize);
                    215:                }
1.1.1.2 ! root      216: 
1.1       root      217: // execute the command line
                    218:                Cmd_ExecuteString (line);
                    219:                
                    220:                if (cmd_wait)
                    221:                {
                    222:                        // skip out while text still remains in buffer, leaving it
                    223:                        // for next frame
                    224:                        cmd_wait = false;
                    225:                        break;
                    226:                }
                    227:        }
                    228: }
1.1.1.2 ! root      229: 
        !           230: 
1.1       root      231: /*
                    232: ===============
                    233: Cbuf_AddEarlyCommands
1.1.1.2 ! root      234: 
1.1       root      235: Adds command line parameters as script statements
                    236: Commands lead with a +, and continue until another +
1.1.1.2 ! root      237: 
1.1       root      238: Set commands are added early, so they are guaranteed to be set before
                    239: the client and server initialize for the first time.
1.1.1.2 ! root      240: 
1.1       root      241: Other commands are added late, after all initialization is complete.
                    242: ===============
                    243: */
                    244: void Cbuf_AddEarlyCommands (qboolean clear)
                    245: {
                    246:        int             i;
                    247:        char    *s;
1.1.1.2 ! root      248: 
1.1       root      249:        for (i=0 ; i<COM_Argc() ; i++)
                    250:        {
                    251:                s = COM_Argv(i);
                    252:                if (strcmp (s, "+set"))
                    253:                        continue;
                    254:                Cbuf_AddText (va("set %s %s\n", COM_Argv(i+1), COM_Argv(i+2)));
                    255:                if (clear)
                    256:                {
                    257:                        COM_ClearArgv(i);
                    258:                        COM_ClearArgv(i+1);
                    259:                        COM_ClearArgv(i+2);
                    260:                }
                    261:                i+=2;
                    262:        }
                    263: }
1.1.1.2 ! root      264: 
1.1       root      265: /*
                    266: =================
                    267: Cbuf_AddLateCommands
1.1.1.2 ! root      268: 
1.1       root      269: Adds command line parameters as script statements
                    270: Commands lead with a + and continue until another + or -
                    271: quake +vid_ref gl +map amlev1
1.1.1.2 ! root      272: 
1.1       root      273: Returns true if any late commands were added, which
                    274: will keep the demoloop from immediately starting
                    275: =================
                    276: */
                    277: qboolean Cbuf_AddLateCommands (void)
                    278: {
                    279:        int             i, j;
                    280:        int             s;
                    281:        char    *text, *build, c;
                    282:        int             argc;
                    283:        qboolean        ret;
1.1.1.2 ! root      284: 
1.1       root      285: // build the combined string to parse from
                    286:        s = 0;
                    287:        argc = COM_Argc();
                    288:        for (i=1 ; i<argc ; i++)
                    289:        {
                    290:                s += strlen (COM_Argv(i)) + 1;
                    291:        }
                    292:        if (!s)
                    293:                return false;
                    294:                
                    295:        text = Z_Malloc (s+1);
                    296:        text[0] = 0;
                    297:        for (i=1 ; i<argc ; i++)
                    298:        {
                    299:                strcat (text,COM_Argv(i));
                    300:                if (i != argc-1)
                    301:                        strcat (text, " ");
                    302:        }
                    303:        
                    304: // pull out the commands
                    305:        build = Z_Malloc (s+1);
                    306:        build[0] = 0;
                    307:        
                    308:        for (i=0 ; i<s-1 ; i++)
                    309:        {
                    310:                if (text[i] == '+')
                    311:                {
                    312:                        i++;
1.1.1.2 ! root      313: 
1.1       root      314:                        for (j=i ; (text[j] != '+') && (text[j] != '-') && (text[j] != 0) ; j++)
                    315:                                ;
1.1.1.2 ! root      316: 
1.1       root      317:                        c = text[j];
                    318:                        text[j] = 0;
                    319:                        
                    320:                        strcat (build, text+i);
                    321:                        strcat (build, "\n");
                    322:                        text[j] = c;
                    323:                        i = j-1;
                    324:                }
                    325:        }
1.1.1.2 ! root      326: 
1.1       root      327:        ret = (build[0] != 0);
                    328:        if (ret)
                    329:                Cbuf_AddText (build);
                    330:        
                    331:        Z_Free (text);
                    332:        Z_Free (build);
1.1.1.2 ! root      333: 
1.1       root      334:        return ret;
                    335: }
1.1.1.2 ! root      336: 
        !           337: 
1.1       root      338: /*
                    339: ==============================================================================
1.1.1.2 ! root      340: 
1.1       root      341:                                                SCRIPT COMMANDS
1.1.1.2 ! root      342: 
1.1       root      343: ==============================================================================
                    344: */
1.1.1.2 ! root      345: 
        !           346: 
1.1       root      347: /*
                    348: ===============
                    349: Cmd_Exec_f
                    350: ===============
                    351: */
                    352: void Cmd_Exec_f (void)
                    353: {
                    354:        char    *f, *f2;
                    355:        int             len;
1.1.1.2 ! root      356: 
1.1       root      357:        if (Cmd_Argc () != 2)
                    358:        {
                    359:                Com_Printf ("exec <filename> : execute a script file\n");
                    360:                return;
                    361:        }
1.1.1.2 ! root      362: 
1.1       root      363:        len = FS_LoadFile (Cmd_Argv(1), (void **)&f);
                    364:        if (!f)
                    365:        {
                    366:                Com_Printf ("couldn't exec %s\n",Cmd_Argv(1));
                    367:                return;
                    368:        }
                    369:        Com_Printf ("execing %s\n",Cmd_Argv(1));
                    370:        
                    371:        // the file doesn't have a trailing 0, so we need to copy it off
                    372:        f2 = Z_Malloc(len+1);
                    373:        memcpy (f2, f, len);
                    374:        f2[len] = 0;
1.1.1.2 ! root      375: 
1.1       root      376:        Cbuf_InsertText (f2);
1.1.1.2 ! root      377: 
1.1       root      378:        Z_Free (f2);
                    379:        FS_FreeFile (f);
                    380: }
1.1.1.2 ! root      381: 
        !           382: 
1.1       root      383: /*
                    384: ===============
                    385: Cmd_Echo_f
1.1.1.2 ! root      386: 
1.1       root      387: Just prints the rest of the line to the console
                    388: ===============
                    389: */
                    390: void Cmd_Echo_f (void)
                    391: {
                    392:        int             i;
                    393:        
                    394:        for (i=1 ; i<Cmd_Argc() ; i++)
                    395:                Com_Printf ("%s ",Cmd_Argv(i));
                    396:        Com_Printf ("\n");
                    397: }
1.1.1.2 ! root      398: 
1.1       root      399: /*
                    400: ===============
                    401: Cmd_Alias_f
1.1.1.2 ! root      402: 
1.1       root      403: Creates a new command that executes a command string (possibly ; seperated)
                    404: ===============
                    405: */
                    406: void Cmd_Alias_f (void)
                    407: {
                    408:        cmdalias_t      *a;
                    409:        char            cmd[1024];
                    410:        int                     i, c;
                    411:        char            *s;
1.1.1.2 ! root      412: 
1.1       root      413:        if (Cmd_Argc() == 1)
                    414:        {
                    415:                Com_Printf ("Current alias commands:\n");
                    416:                for (a = cmd_alias ; a ; a=a->next)
                    417:                        Com_Printf ("%s : %s\n", a->name, a->value);
                    418:                return;
                    419:        }
1.1.1.2 ! root      420: 
1.1       root      421:        s = Cmd_Argv(1);
                    422:        if (strlen(s) >= MAX_ALIAS_NAME)
                    423:        {
                    424:                Com_Printf ("Alias name is too long\n");
                    425:                return;
                    426:        }
1.1.1.2 ! root      427: 
1.1       root      428:        // if the alias already exists, reuse it
                    429:        for (a = cmd_alias ; a ; a=a->next)
                    430:        {
                    431:                if (!strcmp(s, a->name))
                    432:                {
                    433:                        Z_Free (a->value);
                    434:                        break;
                    435:                }
                    436:        }
1.1.1.2 ! root      437: 
1.1       root      438:        if (!a)
                    439:        {
                    440:                a = Z_Malloc (sizeof(cmdalias_t));
                    441:                a->next = cmd_alias;
                    442:                cmd_alias = a;
                    443:        }
                    444:        strcpy (a->name, s);    
1.1.1.2 ! root      445: 
1.1       root      446: // copy the rest of the command line
                    447:        cmd[0] = 0;             // start out with a null string
                    448:        c = Cmd_Argc();
                    449:        for (i=2 ; i< c ; i++)
                    450:        {
                    451:                strcat (cmd, Cmd_Argv(i));
                    452:                if (i != (c - 1))
                    453:                        strcat (cmd, " ");
                    454:        }
                    455:        strcat (cmd, "\n");
                    456:        
                    457:        a->value = CopyString (cmd);
                    458: }
1.1.1.2 ! root      459: 
1.1       root      460: /*
                    461: =============================================================================
1.1.1.2 ! root      462: 
1.1       root      463:                                        COMMAND EXECUTION
1.1.1.2 ! root      464: 
1.1       root      465: =============================================================================
                    466: */
1.1.1.2 ! root      467: 
1.1       root      468: typedef struct cmd_function_s
                    469: {
                    470:        struct cmd_function_s   *next;
                    471:        char                                    *name;
                    472:        xcommand_t                              function;
                    473: } cmd_function_t;
1.1.1.2 ! root      474: 
        !           475: 
1.1       root      476: static int                     cmd_argc;
                    477: static char            *cmd_argv[MAX_STRING_TOKENS];
                    478: static char            *cmd_null_string = "";
                    479: static char            cmd_args[MAX_STRING_CHARS];
1.1.1.2 ! root      480: 
1.1       root      481: static cmd_function_t  *cmd_functions;         // possible commands to execute
1.1.1.2 ! root      482: 
1.1       root      483: /*
                    484: ============
                    485: Cmd_Argc
                    486: ============
                    487: */
                    488: int            Cmd_Argc (void)
                    489: {
                    490:        return cmd_argc;
                    491: }
1.1.1.2 ! root      492: 
1.1       root      493: /*
                    494: ============
                    495: Cmd_Argv
                    496: ============
                    497: */
                    498: char   *Cmd_Argv (int arg)
                    499: {
                    500:        if ( (unsigned)arg >= cmd_argc )
                    501:                return cmd_null_string;
                    502:        return cmd_argv[arg];   
                    503: }
1.1.1.2 ! root      504: 
1.1       root      505: /*
                    506: ============
                    507: Cmd_Args
1.1.1.2 ! root      508: 
1.1       root      509: Returns a single string containing argv(1) to argv(argc()-1)
                    510: ============
                    511: */
                    512: char           *Cmd_Args (void)
                    513: {
                    514:        return cmd_args;
                    515: }
1.1.1.2 ! root      516: 
        !           517: 
1.1       root      518: /*
                    519: ======================
                    520: Cmd_MacroExpandString
                    521: ======================
                    522: */
                    523: char *Cmd_MacroExpandString (char *text)
                    524: {
                    525:        int             i, j, count, len;
                    526:        qboolean        inquote;
                    527:        char    *scan;
                    528:        static  char    expanded[MAX_STRING_CHARS];
                    529:        char    temporary[MAX_STRING_CHARS];
                    530:        char    *token, *start;
                    531: 
                    532:        inquote = false;
                    533:        scan = text;
                    534: 
                    535:        len = strlen (scan);
                    536:        if (len >= MAX_STRING_CHARS)
                    537:        {
                    538:                Com_Printf ("Line exceeded %i chars, discarded.\n", MAX_STRING_CHARS);
                    539:                return NULL;
                    540:        }
                    541: 
                    542:        count = 0;
                    543: 
                    544:        for (i=0 ; i<len ; i++)
                    545:        {
                    546:                if (scan[i] == '"')
                    547:                        inquote ^= 1;
                    548:                if (inquote)
                    549:                        continue;       // don't expand inside quotes
                    550:                if (scan[i] != '$')
                    551:                        continue;
                    552:                // scan out the complete macro
                    553:                start = scan+i+1;
                    554:                token = COM_Parse (&start);
                    555:                if (!start)
                    556:                        continue;
                    557:        
                    558:                token = Cvar_VariableString (token);
                    559: 
                    560:                j = strlen(token);
                    561:                len += j;
                    562:                if (len >= MAX_STRING_CHARS)
                    563:                {
                    564:                        Com_Printf ("Expanded line exceeded %i chars, discarded.\n", MAX_STRING_CHARS);
                    565:                        return NULL;
                    566:                }
                    567: 
                    568:                strncpy (temporary, scan, i);
                    569:                strcpy (temporary+i, token);
                    570:                strcpy (temporary+i+j, start);
                    571: 
                    572:                strcpy (expanded, temporary);
                    573:                scan = expanded;
                    574:                i--;
                    575: 
                    576:                if (++count == 100)
                    577:                {
                    578:                        Com_Printf ("Macro expansion loop, discarded.\n");
                    579:                        return NULL;
                    580:                }
                    581:        }
                    582: 
                    583:        if (inquote)
                    584:        {
                    585:                Com_Printf ("Line has unmatched quote, discarded.\n");
                    586:                return NULL;
                    587:        }
                    588: 
                    589:        return scan;
                    590: }
                    591: 
                    592: 
                    593: /*
                    594: ============
                    595: Cmd_TokenizeString
1.1.1.2 ! root      596: 
1.1       root      597: Parses the given string into command line tokens.
                    598: $Cvars will be expanded unless they are in a quoted token
                    599: ============
                    600: */
                    601: void Cmd_TokenizeString (char *text, qboolean macroExpand)
                    602: {
                    603:        int             i;
                    604:        char    *com_token;
1.1.1.2 ! root      605: 
1.1       root      606: // clear the args from the last string
                    607:        for (i=0 ; i<cmd_argc ; i++)
                    608:                Z_Free (cmd_argv[i]);
                    609:                
                    610:        cmd_argc = 0;
                    611:        cmd_args[0] = 0;
                    612:        
                    613:        // macro expand the text
                    614:        if (macroExpand)
                    615:                text = Cmd_MacroExpandString (text);
                    616:        if (!text)
                    617:                return;
1.1.1.2 ! root      618: 
1.1       root      619:        while (1)
                    620:        {
                    621: // skip whitespace up to a /n
                    622:                while (*text && *text <= ' ' && *text != '\n')
                    623:                {
                    624:                        text++;
                    625:                }
                    626:                
                    627:                if (*text == '\n')
                    628:                {       // a newline seperates commands in the buffer
                    629:                        text++;
                    630:                        break;
                    631:                }
1.1.1.2 ! root      632: 
1.1       root      633:                if (!*text)
                    634:                        return;
                    635: 
                    636:                // set cmd_args to everything after the first arg
                    637:                if (cmd_argc == 1)
                    638:                {
                    639:                        int             l;
                    640: 
                    641:                        strcpy (cmd_args, text);
                    642: 
                    643:                        // strip off any trailing whitespace
                    644:                        l = strlen(cmd_args) - 1;
                    645:                        for ( ; l >= 0 ; l--)
                    646:                                if (cmd_args[l] <= ' ')
                    647:                                        cmd_args[l] = 0;
                    648:                                else
                    649:                                        break;
                    650:                }
                    651:                        
                    652:                com_token = COM_Parse (&text);
                    653:                if (!text)
                    654:                        return;
1.1.1.2 ! root      655: 
1.1       root      656:                if (cmd_argc < MAX_STRING_TOKENS)
                    657:                {
                    658:                        cmd_argv[cmd_argc] = Z_Malloc (strlen(com_token)+1);
                    659:                        strcpy (cmd_argv[cmd_argc], com_token);
                    660:                        cmd_argc++;
                    661:                }
                    662:        }
                    663:        
                    664: }
1.1.1.2 ! root      665: 
        !           666: 
1.1       root      667: /*
                    668: ============
                    669: Cmd_AddCommand
                    670: ============
                    671: */
                    672: void   Cmd_AddCommand (char *cmd_name, xcommand_t function)
                    673: {
                    674:        cmd_function_t  *cmd;
                    675:        
                    676: // fail if the command is a variable name
                    677:        if (Cvar_VariableString(cmd_name)[0])
                    678:        {
                    679:                Com_Printf ("Cmd_AddCommand: %s already defined as a var\n", cmd_name);
                    680:                return;
                    681:        }
                    682:        
                    683: // fail if the command already exists
                    684:        for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
                    685:        {
                    686:                if (!strcmp (cmd_name, cmd->name))
                    687:                {
                    688:                        Com_Printf ("Cmd_AddCommand: %s already defined\n", cmd_name);
                    689:                        return;
                    690:                }
                    691:        }
1.1.1.2 ! root      692: 
1.1       root      693:        cmd = Z_Malloc (sizeof(cmd_function_t));
                    694:        cmd->name = cmd_name;
                    695:        cmd->function = function;
                    696:        cmd->next = cmd_functions;
                    697:        cmd_functions = cmd;
                    698: }
1.1.1.2 ! root      699: 
1.1       root      700: /*
                    701: ============
                    702: Cmd_RemoveCommand
                    703: ============
                    704: */
                    705: void   Cmd_RemoveCommand (char *cmd_name)
                    706: {
                    707:        cmd_function_t  *cmd, **back;
1.1.1.2 ! root      708: 
1.1       root      709:        back = &cmd_functions;
                    710:        while (1)
                    711:        {
                    712:                cmd = *back;
                    713:                if (!cmd)
                    714:                {
                    715:                        Com_Printf ("Cmd_RemoveCommand: %s not added\n", cmd_name);
                    716:                        return;
                    717:                }
                    718:                if (!strcmp (cmd_name, cmd->name))
                    719:                {
                    720:                        *back = cmd->next;
                    721:                        Z_Free (cmd);
                    722:                        return;
                    723:                }
                    724:                back = &cmd->next;
                    725:        }
                    726: }
1.1.1.2 ! root      727: 
1.1       root      728: /*
                    729: ============
                    730: Cmd_Exists
                    731: ============
                    732: */
                    733: qboolean       Cmd_Exists (char *cmd_name)
                    734: {
                    735:        cmd_function_t  *cmd;
1.1.1.2 ! root      736: 
1.1       root      737:        for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
                    738:        {
                    739:                if (!strcmp (cmd_name,cmd->name))
                    740:                        return true;
                    741:        }
1.1.1.2 ! root      742: 
1.1       root      743:        return false;
                    744: }
1.1.1.2 ! root      745: 
        !           746: 
        !           747: 
1.1       root      748: /*
                    749: ============
                    750: Cmd_CompleteCommand
                    751: ============
                    752: */
                    753: char *Cmd_CompleteCommand (char *partial)
                    754: {
                    755:        cmd_function_t  *cmd;
                    756:        int                             len;
                    757:        cmdalias_t              *a;
                    758:        
                    759:        len = strlen(partial);
                    760:        
                    761:        if (!len)
                    762:                return NULL;
                    763:                
                    764: // check for exact match
                    765:        for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
                    766:                if (!strcmp (partial,cmd->name))
                    767:                        return cmd->name;
                    768:        for (a=cmd_alias ; a ; a=a->next)
                    769:                if (!strcmp (partial, a->name))
                    770:                        return a->name;
1.1.1.2 ! root      771: 
1.1       root      772: // check for partial match
                    773:        for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
                    774:                if (!strncmp (partial,cmd->name, len))
                    775:                        return cmd->name;
                    776:        for (a=cmd_alias ; a ; a=a->next)
                    777:                if (!strncmp (partial, a->name, len))
                    778:                        return a->name;
1.1.1.2 ! root      779: 
1.1       root      780:        return NULL;
                    781: }
1.1.1.2 ! root      782: 
        !           783: 
1.1       root      784: /*
                    785: ============
                    786: Cmd_ExecuteString
1.1.1.2 ! root      787: 
1.1       root      788: A complete command line has been parsed, so try to execute it
                    789: FIXME: lookupnoadd the token to speed search?
                    790: ============
                    791: */
                    792: void   Cmd_ExecuteString (char *text)
                    793: {      
                    794:        cmd_function_t  *cmd;
                    795:        cmdalias_t              *a;
1.1.1.2 ! root      796: 
1.1       root      797:        Cmd_TokenizeString (text, true);
                    798:                        
                    799:        // execute the command line
                    800:        if (!Cmd_Argc())
                    801:                return;         // no tokens
1.1.1.2 ! root      802: 
1.1       root      803:        // check functions
                    804:        for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
                    805:        {
                    806:                if (!Q_strcasecmp (cmd_argv[0],cmd->name))
                    807:                {
                    808:                        if (!cmd->function)
                    809:                        {       // forward to server command
                    810:                                Cmd_ExecuteString (va("cmd %s", text));
                    811:                        }
                    812:                        else
                    813:                                cmd->function ();
                    814:                        return;
                    815:                }
                    816:        }
1.1.1.2 ! root      817: 
1.1       root      818:        // check alias
                    819:        for (a=cmd_alias ; a ; a=a->next)
                    820:        {
                    821:                if (!Q_strcasecmp (cmd_argv[0], a->name))
                    822:                {
                    823:                        if (++alias_count == ALIAS_LOOP_COUNT)
                    824:                        {
                    825:                                Com_Printf ("ALIAS_LOOP_COUNT\n");
                    826:                                return;
                    827:                        }
                    828:                        Cbuf_InsertText (a->value);
                    829:                        return;
                    830:                }
                    831:        }
                    832:        
                    833:        // check cvars
                    834:        if (Cvar_Command ())
                    835:                return;
                    836: 
                    837:        // send it as a server command if we are connected
                    838:        Cmd_ForwardToServer ();
                    839: }
1.1.1.2 ! root      840: 
1.1       root      841: /*
                    842: ============
                    843: Cmd_List_f
                    844: ============
                    845: */
                    846: void Cmd_List_f (void)
                    847: {
                    848:        cmd_function_t  *cmd;
                    849:        int                             i;
1.1.1.2 ! root      850: 
1.1       root      851:        i = 0;
                    852:        for (cmd=cmd_functions ; cmd ; cmd=cmd->next, i++)
                    853:                Com_Printf ("%s\n", cmd->name);
                    854:        Com_Printf ("%i commands\n", i);
                    855: }
1.1.1.2 ! root      856: 
1.1       root      857: /*
                    858: ============
                    859: Cmd_Init
                    860: ============
                    861: */
                    862: void Cmd_Init (void)
                    863: {
                    864: //
                    865: // register our commands
                    866: //
                    867:        Cmd_AddCommand ("cmdlist",Cmd_List_f);
                    868:        Cmd_AddCommand ("exec",Cmd_Exec_f);
                    869:        Cmd_AddCommand ("echo",Cmd_Echo_f);
                    870:        Cmd_AddCommand ("alias",Cmd_Alias_f);
                    871:        Cmd_AddCommand ("wait", Cmd_Wait_f);
                    872: }
1.1.1.2 ! root      873: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.