Annotation of quake1/cmd.c, revision 1.1.1.2

1.1       root        1: // cmd.c -- Quake script command processing module
                      2: 
                      3: #include "quakedef.h"
                      4: 
                      5: void Cmd_ForwardToServer (void);
                      6: 
                      7: typedef struct cmdalias_s
                      8: {
                      9:        struct cmdalias_s       *next;
                     10:        char    *name;
                     11:        char    *value;
                     12: } cmdalias_t;
                     13: 
                     14: cmdalias_t     *cmd_alias;
                     15: 
                     16: int trashtest;
                     17: int *trashspot;
                     18: 
                     19: qboolean       cmd_wait;
                     20: 
                     21: //=============================================================================
                     22: 
                     23: /*
                     24: ============
                     25: Cmd_Wait_f
                     26: 
                     27: Causes execution of the remainder of the command buffer to be delayed until
                     28: next frame.  This allows commands like:
                     29: bind g "impulse 5 ; +attack ; wait ; -attack ; impulse 2"
                     30: ============
                     31: */
                     32: void Cmd_Wait_f (void)
                     33: {
                     34:        cmd_wait = true;
                     35: }
                     36: 
                     37: /*
                     38: =============================================================================
                     39: 
                     40:                                                COMMAND BUFFER
                     41: 
                     42: =============================================================================
                     43: */
                     44: 
                     45: sizebuf_t      cmd_text;
                     46: 
                     47: /*
                     48: ============
                     49: Cbuf_Init
                     50: ============
                     51: */
                     52: void Cbuf_Init (void)
                     53: {
                     54:        SZ_Alloc (&cmd_text, 8192);             // space for commands and script files
                     55: }
                     56: 
                     57: /*
                     58: ============
                     59: Cbuf_AddText
                     60: 
                     61: Adds command text at the end of the buffer
                     62: ============
                     63: */
                     64: void Cbuf_AddText (char *text)
                     65: {
                     66:        int             l;
                     67:        
                     68:        l = Q_strlen (text);
                     69: 
                     70:        if (cmd_text.cursize + l >= cmd_text.maxsize)
                     71:        {
                     72:                Con_Printf ("Cbuf_AddText: overflow\n");
                     73:                return;
                     74:        }
                     75:        SZ_Write (&cmd_text, text, Q_strlen (text));
                     76: }
                     77: 
                     78: 
                     79: /*
                     80: ============
                     81: Cbuf_InsertText
                     82: 
                     83: Adds command text immediately after the current command
                     84: Adds a \n to the text
                     85: FIXME: actually change the command buffer to do less copying
                     86: ============
                     87: */
                     88: void Cbuf_InsertText (char *text)
                     89: {
                     90:        char    *temp;
                     91:        int             templen;
                     92: 
                     93: // copy off any commands still remaining in the exec buffer
                     94:        templen = cmd_text.cursize;
                     95:        if (templen)
                     96:        {
                     97:                temp = Z_Malloc (templen);
                     98:                Q_memcpy (temp, cmd_text.data, templen);
                     99:                SZ_Clear (&cmd_text);
                    100:        }
                    101:        else
                    102:                temp = NULL;    // shut up compiler
                    103:                
                    104: // add the entire text of the file
                    105:        Cbuf_AddText (text);
                    106:        
                    107: // add the copied off data
                    108:        if (templen)
                    109:        {
                    110:                SZ_Write (&cmd_text, temp, templen);
                    111:                Z_Free (temp);
                    112:        }
                    113: }
                    114: 
                    115: /*
                    116: ============
                    117: Cbuf_Execute
                    118: ============
                    119: */
                    120: void Cbuf_Execute (void)
                    121: {
                    122:        int             i;
                    123:        char    *text;
                    124:        char    line[1024];
                    125:        int             quotes;
                    126:        
                    127:        while (cmd_text.cursize)
                    128:        {
                    129: // find a \n or ; line break
                    130:                text = (char *)cmd_text.data;
                    131: 
                    132:                quotes = 0;
                    133:                for (i=0 ; i< cmd_text.cursize ; i++)
                    134:                {
                    135:                        if (text[i] == '"')
                    136:                                quotes++;
                    137:                        if ( !(quotes&1) &&  text[i] == ';')
                    138:                                break;  // don't break if inside a quoted string
                    139:                        if (text[i] == '\n')
                    140:                                break;
                    141:                }
                    142:                        
                    143:                                
                    144:                memcpy (line, text, i);
                    145:                line[i] = 0;
                    146:                
                    147: // delete the text from the command buffer and move remaining commands down
                    148: // this is necessary because commands (exec, alias) can insert data at the
                    149: // beginning of the text buffer
                    150: 
                    151:                if (i == cmd_text.cursize)
                    152:                        cmd_text.cursize = 0;
                    153:                else
                    154:                {
                    155:                        i++;
                    156:                        cmd_text.cursize -= i;
                    157:                        Q_memcpy (text, text+i, cmd_text.cursize);
                    158:                }
                    159: 
                    160: // execute the command line
                    161:                Cmd_ExecuteString (line, src_command);
                    162:                
                    163:                if (cmd_wait)
                    164:                {       // skip out while text still remains in buffer, leaving it
                    165:                        // for next frame
                    166:                        cmd_wait = false;
                    167:                        break;
                    168:                }
                    169:        }
                    170: }
                    171: 
                    172: /*
                    173: ==============================================================================
                    174: 
                    175:                                                SCRIPT COMMANDS
                    176: 
                    177: ==============================================================================
                    178: */
                    179: 
                    180: /*
                    181: ===============
                    182: Cmd_StuffCmds_f
                    183: 
                    184: Adds command line parameters as script statements
                    185: Commands lead with a +, and continue until a - or another +
                    186: quake +prog jctest.qp +cmd amlev1
                    187: quake -nosound +cmd amlev1
                    188: ===============
                    189: */
                    190: void Cmd_StuffCmds_f (void)
                    191: {
                    192:        int             i, j;
                    193:        int             s;
                    194:        char    *text, *build, c;
                    195:                
                    196:        if (Cmd_Argc () != 1)
                    197:        {
                    198:                Con_Printf ("stuffcmds : execute command line parameters\n");
                    199:                return;
                    200:        }
                    201: 
                    202: // build the combined string to parse from
                    203:        s = 0;
                    204:        for (i=1 ; i<com_argc ; i++)
                    205:        {
                    206:                if (!com_argv[i])
                    207:                        continue;               // NEXTSTEP nulls out -NXHost
                    208:                s += Q_strlen (com_argv[i]) + 1;
                    209:        }
                    210:        if (!s)
                    211:                return;
                    212:                
                    213:        text = Z_Malloc (s+1);
                    214:        text[0] = 0;
                    215:        for (i=1 ; i<com_argc ; i++)
                    216:        {
                    217:                if (!com_argv[i])
                    218:                        continue;               // NEXTSTEP nulls out -NXHost
                    219:                Q_strcat (text,com_argv[i]);
                    220:                if (i != com_argc-1)
                    221:                        Q_strcat (text, " ");
                    222:        }
                    223:        
                    224: // pull out the commands
                    225:        build = Z_Malloc (s+1);
                    226:        build[0] = 0;
                    227:        
                    228:        for (i=0 ; i<s-1 ; i++)
                    229:        {
                    230:                if (text[i] == '+')
                    231:                {
                    232:                        i++;
                    233: 
                    234:                        for (j=i ; (text[j] != '+') && (text[j] != '-') && (text[j] != 0) ; j++)
                    235:                                ;
                    236: 
                    237:                        c = text[j];
                    238:                        text[j] = 0;
                    239:                        
                    240:                        Q_strcat (build, text+i);
                    241:                        Q_strcat (build, "\n");
                    242:                        text[j] = c;
                    243:                        i = j-1;
                    244:                }
                    245:        }
                    246:        
                    247:        if (build[0])
                    248:                Cbuf_InsertText (build);
                    249:        
                    250:        Z_Free (text);
                    251:        Z_Free (build);
                    252: }
                    253: 
                    254: 
                    255: /*
                    256: ===============
                    257: Cmd_Exec_f
                    258: ===============
                    259: */
                    260: void Cmd_Exec_f (void)
                    261: {
                    262:        char    *f;
                    263:        int             mark;
                    264: 
                    265:        if (Cmd_Argc () != 2)
                    266:        {
                    267:                Con_Printf ("exec <filename> : execute a script file\n");
                    268:                return;
                    269:        }
                    270: 
                    271:        mark = Hunk_LowMark ();
                    272:        f = (char *)COM_LoadHunkFile (Cmd_Argv(1));
                    273:        if (!f)
                    274:        {
                    275:                Con_Printf ("couldn't exec %s\n",Cmd_Argv(1));
                    276:                return;
                    277:        }
                    278:        Con_Printf ("execing %s\n",Cmd_Argv(1));
                    279:        
                    280:        Cbuf_InsertText (f);
                    281:        Hunk_FreeToLowMark (mark);
                    282: }
                    283: 
                    284: 
                    285: /*
                    286: ===============
                    287: Cmd_Echo_f
                    288: 
                    289: Just prints the rest of the line to the console
                    290: ===============
                    291: */
                    292: void Cmd_Echo_f (void)
                    293: {
                    294:        int             i;
                    295:        
                    296:        for (i=1 ; i<Cmd_Argc() ; i++)
                    297:                Con_Printf ("%s ",Cmd_Argv(i));
                    298:        Con_Printf ("\n");
                    299: }
                    300: 
                    301: /*
                    302: ===============
                    303: Cmd_Alias_f
                    304: 
                    305: Creates a new command that executes a command string (possibly ; seperated)
                    306: ===============
                    307: */
                    308: 
                    309: char *CopyString (char *in)
                    310: {
                    311:        char    *out;
                    312:        
                    313:        out = Z_Malloc (strlen(in)+1);
                    314:        strcpy (out, in);
                    315:        return out;
                    316: }
                    317: 
                    318: void Cmd_Alias_f (void)
                    319: {
                    320:        cmdalias_t      *a;
                    321:        char            cmd[1024];
                    322:        int                     i, c;
                    323: 
                    324:        a = Z_Malloc (sizeof(cmdalias_t));
                    325:        a->next = cmd_alias;
                    326:        cmd_alias = a;
                    327:        
                    328:        a->name = CopyString (Cmd_Argv(1));
                    329: 
                    330: // copy the rest of the command line
                    331:        cmd[0] = 0;             // start out with a null string
                    332:        c = Cmd_Argc();
                    333:        for (i=2 ; i< c ; i++)
                    334:        {
                    335:                strcat (cmd, Cmd_Argv(i));
                    336:                if (i != c)
                    337:                        strcat (cmd, " ");
                    338:        }
                    339:        strcat (cmd, "\n");
                    340:        
                    341:        a->value = CopyString (cmd);
                    342: }
                    343: 
                    344: /*
                    345: =============================================================================
                    346: 
                    347:                                        COMMAND EXECUTION
                    348: 
                    349: =============================================================================
                    350: */
                    351: 
                    352: typedef struct cmd_function_s
                    353: {
                    354:        struct cmd_function_s   *next;
                    355:        char                                    *name;
                    356:        xcommand_t                              function;
                    357: } cmd_function_t;
                    358: 
                    359: 
                    360: #define        MAX_ARGS                80
                    361: 
                    362: static int                     cmd_argc;
                    363: static char            *cmd_argv[MAX_ARGS];
                    364: static char            *cmd_null_string = "";
                    365: static char            *cmd_args = NULL;
                    366: 
                    367: cmd_source_t   cmd_source;
                    368: 
                    369: 
                    370: static cmd_function_t  *cmd_functions;         // possible commands to execute
                    371: 
                    372: /*
                    373: ============
                    374: Cmd_Init
                    375: ============
                    376: */
                    377: void Cmd_Init (void)
                    378: {
                    379: //
                    380: // register our commands
                    381: //
                    382:        Cmd_AddCommand ("stuffcmds",Cmd_StuffCmds_f);
                    383:        Cmd_AddCommand ("exec",Cmd_Exec_f);
                    384:        Cmd_AddCommand ("echo",Cmd_Echo_f);
                    385:        Cmd_AddCommand ("alias",Cmd_Alias_f);
                    386:        Cmd_AddCommand ("cmd", Cmd_ForwardToServer);
                    387:        Cmd_AddCommand ("wait", Cmd_Wait_f);
                    388: }
                    389: 
                    390: /*
                    391: ============
                    392: Cmd_Argc
                    393: ============
                    394: */
                    395: int            Cmd_Argc (void)
                    396: {
                    397:        return cmd_argc;
                    398: }
                    399: 
                    400: /*
                    401: ============
                    402: Cmd_Argv
                    403: ============
                    404: */
                    405: char   *Cmd_Argv (int arg)
                    406: {
                    407:        if ( (unsigned)arg >= cmd_argc )
                    408:                return cmd_null_string;
                    409:        return cmd_argv[arg];   
                    410: }
                    411: 
                    412: /*
                    413: ============
                    414: Cmd_Args
                    415: ============
                    416: */
                    417: char           *Cmd_Args (void)
                    418: {
                    419:        return cmd_args;
                    420: }
                    421: 
                    422: 
                    423: /*
                    424: ============
                    425: Cmd_TokenizeString
                    426: 
                    427: Parses the given string into command line tokens.
                    428: ============
                    429: */
                    430: void Cmd_TokenizeString (char *text)
                    431: {
                    432:        int             i;
                    433:        
                    434: // clear the args from the last string
                    435:        for (i=0 ; i<cmd_argc ; i++)
                    436:                Z_Free (cmd_argv[i]);
                    437:                
                    438:        cmd_argc = 0;
                    439:        cmd_args = NULL;
                    440:        
                    441:        while (1)
                    442:        {
                    443: // skip whitespace up to a /n
                    444:                while (*text && *text <= ' ' && *text != '\n')
                    445:                {
                    446:                        text++;
                    447:                }
                    448:                
                    449:                if (*text == '\n')
                    450:                {       // a newline seperates commands in the buffer
                    451:                        text++;
                    452:                        break;
                    453:                }
                    454: 
                    455:                if (!*text)
                    456:                        return;
                    457:        
                    458:                if (cmd_argc == 1)
                    459:                         cmd_args = text;
                    460:                        
                    461:                text = COM_Parse (text);
                    462:                if (!text)
                    463:                        return;
                    464: 
                    465:                if (cmd_argc < MAX_ARGS)
                    466:                {
                    467:                        cmd_argv[cmd_argc] = Z_Malloc (Q_strlen(com_token)+1);
                    468:                        Q_strcpy (cmd_argv[cmd_argc], com_token);
                    469:                        cmd_argc++;
                    470:                }
                    471:        }
                    472:        
                    473: }
                    474: 
                    475: 
                    476: /*
                    477: ============
                    478: Cmd_AddCommand
                    479: ============
                    480: */
                    481: void   Cmd_AddCommand (char *cmd_name, xcommand_t function)
                    482: {
                    483:        cmd_function_t  *cmd;
                    484:        
                    485:        if (host_initialized)   // because hunk allocation would get stomped
                    486:                Sys_Error ("Cmd_AddCommand after host_initialized");
                    487:                
                    488: // fail if the command is a variable name
                    489:        if (Cvar_VariableString(cmd_name)[0])
                    490:        {
                    491:                Con_Printf ("Cmd_AddCommand: %s already defined as a var\n", cmd_name);
                    492:                return;
                    493:        }
                    494:        
                    495: // fail if the command already exists
                    496:        for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
                    497:        {
                    498:                if (!Q_strcmp (cmd_name, cmd->name))
                    499:                {
                    500:                        Con_Printf ("Cmd_AddCommand: %s already defined\n", cmd_name);
                    501:                        return;
                    502:                }
                    503:        }
                    504: 
                    505:        cmd = Hunk_Alloc (sizeof(cmd_function_t));
                    506:        cmd->name = cmd_name;
                    507:        cmd->function = function;
                    508:        cmd->next = cmd_functions;
                    509:        cmd_functions = cmd;
                    510: }
                    511: 
                    512: /*
                    513: ============
                    514: Cmd_Exists
                    515: ============
                    516: */
                    517: qboolean       Cmd_Exists (char *cmd_name)
                    518: {
                    519:        cmd_function_t  *cmd;
                    520: 
                    521:        for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
                    522:        {
                    523:                if (!Q_strcmp (cmd_name,cmd->name))
                    524:                        return true;
                    525:        }
                    526: 
                    527:        return false;
                    528: }
                    529: 
                    530: 
                    531: 
                    532: /*
                    533: ============
                    534: Cmd_CompleteCommand
                    535: ============
                    536: */
                    537: char *Cmd_CompleteCommand (char *partial)
                    538: {
                    539:        cmd_function_t  *cmd;
                    540:        int                             len;
                    541:        
                    542:        len = Q_strlen(partial);
                    543:        
                    544:        if (!len)
                    545:                return NULL;
                    546:                
                    547: // check functions
                    548:        for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
                    549:                if (!Q_strncmp (partial,cmd->name, len))
                    550:                        return cmd->name;
                    551: 
                    552:        return NULL;
                    553: }
                    554: 
                    555: /*
                    556: ============
                    557: Cmd_ExecuteString
                    558: 
                    559: A complete command line has been parsed, so try to execute it
                    560: FIXME: lookupnoadd the token to speed search?
                    561: ============
                    562: */
                    563: void   Cmd_ExecuteString (char *text, cmd_source_t src)
                    564: {      
                    565:        cmd_function_t  *cmd;
                    566:        cmdalias_t              *a;
                    567: 
                    568:        cmd_source = src;
                    569:        Cmd_TokenizeString (text);
                    570:                        
                    571: // execute the command line
                    572:        if (!Cmd_Argc())
                    573:                return;         // no tokens
                    574: 
                    575: // check functions
                    576:        for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
                    577:        {
                    578:                if (!Q_strcasecmp (cmd_argv[0],cmd->name))
                    579:                {
                    580:                        cmd->function ();
                    581:                        return;
                    582:                }
                    583:        }
                    584: 
                    585: // check alias
                    586:        for (a=cmd_alias ; a ; a=a->next)
                    587:        {
                    588:                if (!Q_strcasecmp (cmd_argv[0], a->name))
                    589:                {
                    590:                        Cbuf_InsertText (a->value);
                    591:                        return;
                    592:                }
                    593:        }
                    594:        
                    595: // check cvars
                    596:        if (!Cvar_Command ())
                    597:                Con_Printf ("Unknown command \"%s\"\n", Cmd_Argv(0));
                    598:        
                    599: }
                    600: 
                    601: 
                    602: /*
                    603: ===================
                    604: Cmd_ForwardToServer
                    605: 
                    606: Sends the entire command line over to the server
                    607: ===================
                    608: */
                    609: void Cmd_ForwardToServer (void)
                    610: {
                    611:        if (cls.state != ca_connected)
                    612:        {
                    613:                Con_Printf ("Can't \"%s\", not connected\n", Cmd_Argv(0));
                    614:                return;
                    615:        }
                    616:        
                    617:        if (cls.demoplayback)
                    618:                return;         // not really connected
                    619: 
                    620:        MSG_WriteByte (&cls.message, clc_stringcmd);
1.1.1.2 ! root      621:        SZ_Print (&cls.message, Cmd_Argv(0));
        !           622:        if (Cmd_Argc() > 1)
1.1       root      623:        {
                    624:                SZ_Print (&cls.message, " ");
                    625:                SZ_Print (&cls.message, Cmd_Args());
1.1.1.2 ! root      626:        }
1.1       root      627: }
                    628: 
                    629: 
                    630: /*
                    631: ================
                    632: Cmd_CheckParm
                    633: 
                    634: Returns the position (1 to argc-1) in the command's argument list
                    635: where the given parameter apears, or 0 if not present
                    636: ================
                    637: */
                    638: 
                    639: int Cmd_CheckParm (char *parm)
                    640: {
                    641:        int i;
                    642:        
                    643:        if (!parm)
                    644:                Sys_Error ("Cmd_CheckParm: NULL");
                    645: 
                    646:        for (i = 1; i < Cmd_Argc (); i++)
                    647:                if (! Q_strcasecmp (parm, Cmd_Argv (i)))
                    648:                        return i;
                    649:                        
                    650:        return 0;
                    651: }

unix.superglobalmegacorp.com

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