Annotation of quake1/cmd.c, revision 1.1.1.3

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

unix.superglobalmegacorp.com

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