/* * Copyright (C) Volition, Inc. 1999. All rights reserved. * * All source code herein is the property of Volition, Inc. You may not sell * or otherwise commercially exploit the source or things you created based on the * source. * */ #include #include #include #include #include #include "globalincs/pstypes.h" #include "graphics/font.h" #include "io/timer.h" #include "io/key.h" #include "globalincs/alphacolors.h" #include "osapi/osapi.h" #define MAX_COMMANDS 300 static int Num_debug_commands = 0; static debug_command *Debug_command[MAX_COMMANDS]; debug_command::debug_command(char *_name, char *_help, void (*_func)() ) { int i; if ( Num_debug_commands >= MAX_COMMANDS ) { Int3(); // Too many debug console commands!! Increase MAX_COMMANDS!! return; } for (i=0; iname, _name ); if ( ret == 0) { Int3(); // This debug console command already exists!!!! return; } else if ( ret > 0 ) { break; // Insert it here } else if ( ret < 0 ) { // do nothing } } if ( i < Num_debug_commands ) { // Insert it at element i int j; for (j=Num_debug_commands; j>i; j-- ) { Debug_command[j] = Debug_command[j-1]; } Debug_command[i] = this; Num_debug_commands++; } else { Debug_command[Num_debug_commands] = this; Num_debug_commands++; } name = _name; help = _help; func = _func; } // some global variables int Dc_command; // If this is set, then process the command int Dc_help; // If this is set, then print out the help text in the form, "usage: ... \nLong description\n" ); int Dc_status; // If this is set, then print out the current status of the command. char *Dc_arg; // The (lowercased) string value of the argument retrieved from dc_arg char *Dc_arg_org; // Dc_arg before it got converted to lowercase uint Dc_arg_type; // The type of dc_arg. char *Dc_command_line; // The rest of the command line, from the end of the last processed arg on. int Dc_arg_int; // If Dc_arg_type & ARG_INT is set, then this is the value ubyte Dc_arg_ubyte; // If Dc_arg_type & ARG_UBYTE is set, then this is the value float Dc_arg_float; // If Dc_arg_type & ARG_FLOAT is set, then this is the value int scroll_times = 0; // incremented each time display scrolls int debug_inited = 0; #define DROWS 25 #define DCOLS 80 int debug_x=0, debug_y=0; char debug_text[DROWS][DCOLS]; static char command_line[1024]; static int command_line_pos = 0; #define DEBUG_HISTORY 16 static char oldcommand_line[DEBUG_HISTORY][1024]; int last_oldcommand=-1; int command_scroll = 0; ///=========================== SCANNER ======================= typedef enum { LETTER, QUOTE, SPECIAL, EOF_CODE, DIGIT } CHAR_CODE; typedef enum { NO_TOKEN, IDENTIFIER, NUMBER, STRING } TOKEN_CODE; #define MAX_TOKEN_STRING_LENGTH 128 char scanner_ch; TOKEN_CODE scanner_token; char scanner_token_string[MAX_TOKEN_STRING_LENGTH]; char scanner_word_string[MAX_TOKEN_STRING_LENGTH]; char * scanner_bufferp = ""; char * scanner_tokenp = scanner_token_string; CHAR_CODE scanner_char_table[256]; #define scanner_char_code(x) scanner_char_table[x] void scanner_get_char() { if ( *scanner_bufferp == '\0' ) { scanner_ch = 0; return; } scanner_ch = *scanner_bufferp++; } void scanner_init() { int ch; for (ch=0; ch<256; ++ch) scanner_char_table[ch] = SPECIAL; for (ch='0'; ch<='9'; ++ch) scanner_char_table[ch] = DIGIT; for (ch='A'; ch<='Z'; ++ch) scanner_char_table[ch] = LETTER; for (ch='a'; ch<='z'; ++ch) scanner_char_table[ch] = LETTER; scanner_char_table['.'] = DIGIT; scanner_char_table['-'] = DIGIT; scanner_char_table['+'] = DIGIT; scanner_char_table['_'] = LETTER; scanner_char_table[34] = QUOTE; scanner_char_table[0] = EOF_CODE; scanner_char_table[':'] = LETTER; scanner_char_table['\\'] = LETTER; scanner_ch = 0; } void scanner_skip_blanks() { while( (scanner_ch ==' ') || (scanner_ch =='\t') ) scanner_get_char(); } void scanner_downshift_word() { int offset = 'a' - 'A'; char * tp; strcpy_s( scanner_word_string, scanner_token_string ); tp = scanner_word_string; do { *tp = (char)((*tp>='A') && (*tp <='Z') ? *tp + offset : *tp) ; tp++; } while (*tp != '\0' ); } void scanner_get_word() { while( (scanner_char_code(scanner_ch)==LETTER) || (scanner_char_code(scanner_ch)==DIGIT) ) { *scanner_tokenp++ = scanner_ch; scanner_get_char(); } *scanner_tokenp = '\0'; scanner_token = IDENTIFIER; } void scanner_get_string() { *scanner_tokenp++ = 34; scanner_get_char(); while(scanner_ch != 34 ) { *scanner_tokenp++ = scanner_ch; scanner_get_char(); } scanner_get_char(); *scanner_tokenp++ = 34; *scanner_tokenp = '\0'; scanner_token = STRING; } void scanner_get_token() { scanner_skip_blanks(); scanner_tokenp = scanner_token_string; *scanner_tokenp = 0; switch( scanner_char_code(scanner_ch) ) { case QUOTE: scanner_get_string(); break; case EOF_CODE: scanner_token = NO_TOKEN; break; case DIGIT: case LETTER: scanner_get_word(); break; default: *scanner_tokenp++ = scanner_ch; *scanner_tokenp = '\0'; scanner_get_char(); scanner_token = IDENTIFIER; break; } scanner_downshift_word(); } void scanner_start_command( char * s ) { scanner_bufferp = s; scanner_get_char(); } int Dc_debug_on = 0; jmp_buf dc_bad_arg; void dc_get_arg(uint type) { scanner_get_token(); Dc_command_line = scanner_bufferp; Dc_arg_org = scanner_token_string; Dc_arg = scanner_word_string; if (Dc_debug_on) { dc_printf( "next arg is '%s', was originally '%s'\n", Dc_arg, Dc_arg_org ); dc_printf( "Rest of the command line is '%s'\n", Dc_command_line ); } if ( scanner_token == NO_TOKEN ) { Dc_arg_type = ARG_NONE; } else if ( scanner_token == IDENTIFIER ) { Dc_arg_type = ARG_STRING; } else if ( scanner_token == STRING ) { Dc_arg_type = ARG_QUOTE; } else { Dc_arg_type = ARG_STRING; } if ( Dc_arg_type & ARG_STRING ) { int i, num_digits, len; len = strlen(Dc_arg); num_digits = 0; for (i=0; iname, Dc_arg ) ) { if (mode==0) { if (Dc_debug_on) { dc_printf( "Calling function '%s'\n", Dc_arg ); } Dc_command = 1; Dc_help = 0; Dc_status = 1; } else if (mode==1) { if (Dc_debug_on) { dc_printf( "Checking status for '%s'\n", Dc_arg ); } Dc_command = 0; Dc_help = 0; Dc_status = 1; } else { if (Dc_debug_on) { dc_printf( "Doing help for '%s'\n", Dc_arg ); } Dc_command = 0; Dc_help = 1; Dc_status = 0; } (*Debug_command[i]->func)(); if (mode==0) { dc_get_arg(ARG_ANY); if (!(Dc_arg_type&ARG_NONE)) { dc_printf( "Ignoring the unused command line tail '%s %s'\n", Dc_arg_org, Dc_command_line ); } } return; } } dc_printf( "Unknown command '%s'\n", Dc_arg ); } void debug_draw() { int i; gr_clear(); gr_set_font(FONT1); gr_set_color_fast( &Color_bright ); gr_string( 0x8000, 3, "Debug Console", GR_RESIZE_MENU ); gr_set_color_fast( &Color_normal ); for (i=0; i= DCOLS-1 ) { debug_x=0; debug_y++; scroll_times++; if ( debug_y >= DROWS ) { int i; for (i=1; i= DCOLS-1) ) { debug_x=0; debug_y++; scroll_times++; if ( debug_y >= DROWS ) { int i; for (i=1; i 0 ) { command_line[--command_line_pos] = 0; } break; case KEY_F3: if ( last_oldcommand > -1 ) { strcpy_s( command_line, oldcommand_line[last_oldcommand] ); command_line_pos = strlen(command_line); command_line[command_line_pos] = 0; } break; case KEY_UP: command_scroll--; if (command_scroll<0) { command_scroll = last_oldcommand; } if ( command_scroll > -1 ) { strcpy_s( command_line, oldcommand_line[command_scroll] ); command_line_pos = strlen(command_line); command_line[command_line_pos] = 0; } break; case KEY_DOWN: command_scroll++; if (command_scroll>last_oldcommand) { command_scroll = 0; } if (command_scroll>last_oldcommand) { command_scroll = -1; } if ( command_scroll > -1 ) { strcpy_s( command_line, oldcommand_line[command_scroll] ); command_line_pos = strlen(command_line); command_line[command_line_pos] = 0; } break; case KEY_ENTER: { debug_output( '\n' ); debug_draw(); debug_do_command(command_line); int i, found = 0; for (i=0; i<=last_oldcommand; i++ ) { if (!stricmp( oldcommand_line[i], command_line )) { found = 1; } } if ( !found ) { if ( last_oldcommand < DEBUG_HISTORY-1 ) { last_oldcommand++; strcpy_s( oldcommand_line[last_oldcommand], command_line); } else { int iLoop; for (iLoop=0; iLoop" ); strcat_s( debug_text[debug_y], command_line ); debug_draw(); if ( _func ) { _func(); } } while( key_inkey() ) { os_poll(); } } void debug_help() { int s, i; dc_printf( "Available functions:\n\n" ); s = scroll_times; for (i=0; iname, Debug_command[i]->help ); if ( scroll_times - s > DROWS - 3 ) { int k; dc_printf( " Press a key...B for back\n" ); debug_draw(); k = key_getch(); s = scroll_times; if ( k == KEY_B ) { i -= ((DROWS-3)*2); if ( i <= 0 ) { i = -1; } } } debug_draw(); } dc_printf( "\n" ); dc_printf( "Typing '? function_name' will give the current status.\n" ); dc_printf( "Typing 'function_name ?' will give help on the function.\n" ); dc_printf( "Typing ? or help will give you help.\n"); dc_printf( "F3 selects last command line.\n" ); }