00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "../game/q_shared.h"
00025 #include "qcommon.h"
00026
00027 #define MAX_CMD_BUFFER 16384
00028 #define MAX_CMD_LINE 1024
00029
00030 typedef struct {
00031 byte *data;
00032 int maxsize;
00033 int cursize;
00034 } cmd_t;
00035
00036 int cmd_wait;
00037 cmd_t cmd_text;
00038 byte cmd_text_buf[MAX_CMD_BUFFER];
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 void Cmd_Wait_f( void ) {
00053 if ( Cmd_Argc() == 2 ) {
00054 cmd_wait = atoi( Cmd_Argv( 1 ) );
00055 } else {
00056 cmd_wait = 1;
00057 }
00058 }
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 void Cbuf_Init (void)
00075 {
00076 cmd_text.data = cmd_text_buf;
00077 cmd_text.maxsize = MAX_CMD_BUFFER;
00078 cmd_text.cursize = 0;
00079 }
00080
00081
00082
00083
00084
00085
00086
00087
00088 void Cbuf_AddText( const char *text ) {
00089 int l;
00090
00091 l = strlen (text);
00092
00093 if (cmd_text.cursize + l >= cmd_text.maxsize)
00094 {
00095 Com_Printf ("Cbuf_AddText: overflow\n");
00096 return;
00097 }
00098 Com_Memcpy(&cmd_text.data[cmd_text.cursize], text, l);
00099 cmd_text.cursize += l;
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 void Cbuf_InsertText( const char *text ) {
00112 int len;
00113 int i;
00114
00115 len = strlen( text ) + 1;
00116 if ( len + cmd_text.cursize > cmd_text.maxsize ) {
00117 Com_Printf( "Cbuf_InsertText overflowed\n" );
00118 return;
00119 }
00120
00121
00122 for ( i = cmd_text.cursize - 1 ; i >= 0 ; i-- ) {
00123 cmd_text.data[ i + len ] = cmd_text.data[ i ];
00124 }
00125
00126
00127 Com_Memcpy( cmd_text.data, text, len - 1 );
00128
00129
00130 cmd_text.data[ len - 1 ] = '\n';
00131
00132 cmd_text.cursize += len;
00133 }
00134
00135
00136
00137
00138
00139
00140
00141 void Cbuf_ExecuteText (int exec_when, const char *text)
00142 {
00143 switch (exec_when)
00144 {
00145 case EXEC_NOW:
00146 if (text && strlen(text) > 0) {
00147 Cmd_ExecuteString (text);
00148 } else {
00149 Cbuf_Execute();
00150 }
00151 break;
00152 case EXEC_INSERT:
00153 Cbuf_InsertText (text);
00154 break;
00155 case EXEC_APPEND:
00156 Cbuf_AddText (text);
00157 break;
00158 default:
00159 Com_Error (ERR_FATAL, "Cbuf_ExecuteText: bad exec_when");
00160 }
00161 }
00162
00163
00164
00165
00166
00167
00168 void Cbuf_Execute (void)
00169 {
00170 int i;
00171 char *text;
00172 char line[MAX_CMD_LINE];
00173 int quotes;
00174
00175 while (cmd_text.cursize)
00176 {
00177 if ( cmd_wait ) {
00178
00179
00180 cmd_wait--;
00181 break;
00182 }
00183
00184
00185 text = (char *)cmd_text.data;
00186
00187 quotes = 0;
00188 for (i=0 ; i< cmd_text.cursize ; i++)
00189 {
00190 if (text[i] == '"')
00191 quotes++;
00192 if ( !(quotes&1) && text[i] == ';')
00193 break;
00194 if (text[i] == '\n' || text[i] == '\r' )
00195 break;
00196 }
00197
00198 if( i >= (MAX_CMD_LINE - 1)) {
00199 i = MAX_CMD_LINE - 1;
00200 }
00201
00202 Com_Memcpy (line, text, i);
00203 line[i] = 0;
00204
00205
00206
00207
00208
00209 if (i == cmd_text.cursize)
00210 cmd_text.cursize = 0;
00211 else
00212 {
00213 i++;
00214 cmd_text.cursize -= i;
00215 memmove (text, text+i, cmd_text.cursize);
00216 }
00217
00218
00219
00220 Cmd_ExecuteString (line);
00221 }
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 void Cmd_Exec_f( void ) {
00240 char *f;
00241 int len;
00242 char filename[MAX_QPATH];
00243
00244 if (Cmd_Argc () != 2) {
00245 Com_Printf ("exec <filename> : execute a script file\n");
00246 return;
00247 }
00248
00249 Q_strncpyz( filename, Cmd_Argv(1), sizeof( filename ) );
00250 COM_DefaultExtension( filename, sizeof( filename ), ".cfg" );
00251 len = FS_ReadFile( filename, (void **)&f);
00252 if (!f) {
00253 Com_Printf ("couldn't exec %s\n",Cmd_Argv(1));
00254 return;
00255 }
00256 Com_Printf ("execing %s\n",Cmd_Argv(1));
00257
00258 Cbuf_InsertText (f);
00259
00260 FS_FreeFile (f);
00261 }
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 void Cmd_Vstr_f( void ) {
00272 char *v;
00273
00274 if (Cmd_Argc () != 2) {
00275 Com_Printf ("vstr <variablename> : execute a variable command\n");
00276 return;
00277 }
00278
00279 v = Cvar_VariableString( Cmd_Argv( 1 ) );
00280 Cbuf_InsertText( va("%s\n", v ) );
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 void Cmd_Echo_f (void)
00292 {
00293 int i;
00294
00295 for (i=1 ; i<Cmd_Argc() ; i++)
00296 Com_Printf ("%s ",Cmd_Argv(i));
00297 Com_Printf ("\n");
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309 typedef struct cmd_function_s
00310 {
00311 struct cmd_function_s *next;
00312 char *name;
00313 xcommand_t function;
00314 } cmd_function_t;
00315
00316
00317 static int cmd_argc;
00318 static char *cmd_argv[MAX_STRING_TOKENS];
00319 static char cmd_tokenized[BIG_INFO_STRING+MAX_STRING_TOKENS];
00320 static char cmd_cmd[BIG_INFO_STRING];
00321
00322 static cmd_function_t *cmd_functions;
00323
00324
00325
00326
00327
00328
00329 int Cmd_Argc( void ) {
00330 return cmd_argc;
00331 }
00332
00333
00334
00335
00336
00337
00338 char *Cmd_Argv( int arg ) {
00339 if ( (unsigned)arg >= cmd_argc ) {
00340 return "";
00341 }
00342 return cmd_argv[arg];
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 void Cmd_ArgvBuffer( int arg, char *buffer, int bufferLength ) {
00354 Q_strncpyz( buffer, Cmd_Argv( arg ), bufferLength );
00355 }
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365 char *Cmd_Args( void ) {
00366 static char cmd_args[MAX_STRING_CHARS];
00367 int i;
00368
00369 cmd_args[0] = 0;
00370 for ( i = 1 ; i < cmd_argc ; i++ ) {
00371 strcat( cmd_args, cmd_argv[i] );
00372 if ( i != cmd_argc-1 ) {
00373 strcat( cmd_args, " " );
00374 }
00375 }
00376
00377 return cmd_args;
00378 }
00379
00380
00381
00382
00383
00384
00385
00386
00387 char *Cmd_ArgsFrom( int arg ) {
00388 static char cmd_args[BIG_INFO_STRING];
00389 int i;
00390
00391 cmd_args[0] = 0;
00392 if (arg < 0)
00393 arg = 0;
00394 for ( i = arg ; i < cmd_argc ; i++ ) {
00395 strcat( cmd_args, cmd_argv[i] );
00396 if ( i != cmd_argc-1 ) {
00397 strcat( cmd_args, " " );
00398 }
00399 }
00400
00401 return cmd_args;
00402 }
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412 void Cmd_ArgsBuffer( char *buffer, int bufferLength ) {
00413 Q_strncpyz( buffer, Cmd_Args(), bufferLength );
00414 }
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425 char *Cmd_Cmd()
00426 {
00427 return cmd_cmd;
00428 }
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 void Cmd_TokenizeString( const char *text_in ) {
00443 const char *text;
00444 char *textOut;
00445
00446 #ifdef TKN_DBG
00447
00448 Com_DPrintf("Cmd_TokenizeString: %s\n", text_in);
00449 #endif
00450
00451
00452 cmd_argc = 0;
00453
00454 if ( !text_in ) {
00455 return;
00456 }
00457
00458 Q_strncpyz( cmd_cmd, text_in, sizeof(cmd_cmd) );
00459
00460 text = text_in;
00461 textOut = cmd_tokenized;
00462
00463 while ( 1 ) {
00464 if ( cmd_argc == MAX_STRING_TOKENS ) {
00465 return;
00466 }
00467
00468 while ( 1 ) {
00469
00470 while ( *text && *text <= ' ' ) {
00471 text++;
00472 }
00473 if ( !*text ) {
00474 return;
00475 }
00476
00477
00478 if ( text[0] == '/' && text[1] == '/' ) {
00479 return;
00480 }
00481
00482
00483 if ( text[0] == '/' && text[1] =='*' ) {
00484 while ( *text && ( text[0] != '*' || text[1] != '/' ) ) {
00485 text++;
00486 }
00487 if ( !*text ) {
00488 return;
00489 }
00490 text += 2;
00491 } else {
00492 break;
00493 }
00494 }
00495
00496
00497
00498 if ( *text == '"' ) {
00499 cmd_argv[cmd_argc] = textOut;
00500 cmd_argc++;
00501 text++;
00502 while ( *text && *text != '"' ) {
00503 *textOut++ = *text++;
00504 }
00505 *textOut++ = 0;
00506 if ( !*text ) {
00507 return;
00508 }
00509 text++;
00510 continue;
00511 }
00512
00513
00514 cmd_argv[cmd_argc] = textOut;
00515 cmd_argc++;
00516
00517
00518 while ( *text > ' ' ) {
00519 if ( text[0] == '"' ) {
00520 break;
00521 }
00522
00523 if ( text[0] == '/' && text[1] == '/' ) {
00524 break;
00525 }
00526
00527
00528 if ( text[0] == '/' && text[1] =='*' ) {
00529 break;
00530 }
00531
00532 *textOut++ = *text++;
00533 }
00534
00535 *textOut++ = 0;
00536
00537 if ( !*text ) {
00538 return;
00539 }
00540 }
00541
00542 }
00543
00544
00545
00546
00547
00548
00549
00550 void Cmd_AddCommand( const char *cmd_name, xcommand_t function ) {
00551 cmd_function_t *cmd;
00552
00553
00554 for ( cmd = cmd_functions ; cmd ; cmd=cmd->next ) {
00555 if ( !strcmp( cmd_name, cmd->name ) ) {
00556
00557 if ( function != NULL ) {
00558 Com_Printf ("Cmd_AddCommand: %s already defined\n", cmd_name);
00559 }
00560 return;
00561 }
00562 }
00563
00564
00565 cmd = S_Malloc (sizeof(cmd_function_t));
00566 cmd->name = CopyString( cmd_name );
00567 cmd->function = function;
00568 cmd->next = cmd_functions;
00569 cmd_functions = cmd;
00570 }
00571
00572
00573
00574
00575
00576
00577 void Cmd_RemoveCommand( const char *cmd_name ) {
00578 cmd_function_t *cmd, **back;
00579
00580 back = &cmd_functions;
00581 while( 1 ) {
00582 cmd = *back;
00583 if ( !cmd ) {
00584
00585 return;
00586 }
00587 if ( !strcmp( cmd_name, cmd->name ) ) {
00588 *back = cmd->next;
00589 if (cmd->name) {
00590 Z_Free(cmd->name);
00591 }
00592 Z_Free (cmd);
00593 return;
00594 }
00595 back = &cmd->next;
00596 }
00597 }
00598
00599
00600
00601
00602
00603
00604
00605 void Cmd_CommandCompletion( void(*callback)(const char *s) ) {
00606 cmd_function_t *cmd;
00607
00608 for (cmd=cmd_functions ; cmd ; cmd=cmd->next) {
00609 callback( cmd->name );
00610 }
00611 }
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621 void Cmd_ExecuteString( const char *text ) {
00622 cmd_function_t *cmd, **prev;
00623
00624
00625 Cmd_TokenizeString( text );
00626 if ( !Cmd_Argc() ) {
00627 return;
00628 }
00629
00630
00631 for ( prev = &cmd_functions ; *prev ; prev = &cmd->next ) {
00632 cmd = *prev;
00633 if ( !Q_stricmp( cmd_argv[0],cmd->name ) ) {
00634
00635
00636 *prev = cmd->next;
00637 cmd->next = cmd_functions;
00638 cmd_functions = cmd;
00639
00640
00641 if ( !cmd->function ) {
00642
00643 break;
00644 } else {
00645 cmd->function ();
00646 }
00647 return;
00648 }
00649 }
00650
00651
00652 if ( Cvar_Command() ) {
00653 return;
00654 }
00655
00656
00657 if ( com_cl_running && com_cl_running->integer && CL_GameCommand() ) {
00658 return;
00659 }
00660
00661
00662 if ( com_sv_running && com_sv_running->integer && SV_GameCommand() ) {
00663 return;
00664 }
00665
00666
00667 if ( com_cl_running && com_cl_running->integer && UI_GameCommand() ) {
00668 return;
00669 }
00670
00671
00672
00673 CL_ForwardCommandToServer ( text );
00674 }
00675
00676
00677
00678
00679
00680
00681 void Cmd_List_f (void)
00682 {
00683 cmd_function_t *cmd;
00684 int i;
00685 char *match;
00686
00687 if ( Cmd_Argc() > 1 ) {
00688 match = Cmd_Argv( 1 );
00689 } else {
00690 match = NULL;
00691 }
00692
00693 i = 0;
00694 for (cmd=cmd_functions ; cmd ; cmd=cmd->next) {
00695 if (match && !Com_Filter(match, cmd->name, qfalse)) continue;
00696
00697 Com_Printf ("%s\n", cmd->name);
00698 i++;
00699 }
00700 Com_Printf ("%i commands\n", i);
00701 }
00702
00703
00704
00705
00706
00707
00708 void Cmd_Init (void) {
00709 Cmd_AddCommand ("cmdlist",Cmd_List_f);
00710 Cmd_AddCommand ("exec",Cmd_Exec_f);
00711 Cmd_AddCommand ("vstr",Cmd_Vstr_f);
00712 Cmd_AddCommand ("echo",Cmd_Echo_f);
00713 Cmd_AddCommand ("wait", Cmd_Wait_f);
00714 }
00715