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

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

unix.superglobalmegacorp.com

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