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