/* command.c: Parse a debugger command Copyright (c) 2002-2008 Philip Kendall $Id$ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Author contact information: E-mail: philip-fuse@shadowmagic.org.uk */ #include #include #include #include #include "debugger.h" #include "debugger_internals.h" #include "mempool.h" #include "ui/ui.h" #include "z80/z80.h" #include "z80/z80_macros.h" /* The last debugger command we were given to execute */ static char *command_buffer = NULL; /* And a pointer as to how much we've parsed */ static char *command_ptr; int yyparse( void ); int yywrap( void ); /* Evaluate the debugger command given in 'command' */ int debugger_command_evaluate( const char *command ) { if( !command ) return 0; if( command_buffer ) free( command_buffer ); command_buffer = strdup( command ); if( !command_buffer ) { ui_error( UI_ERROR_ERROR, "Out of memory at %s:%d", __FILE__, __LINE__ ); return 1; } /* Start parsing at the start of the given command */ command_ptr = command_buffer; /* Parse the command */ yyparse(); /* And free any memory we allocated while parsing */ mempool_free( debugger_memory_pool ); ui_debugger_update(); return 0; } /* Utility functions called from the flex scanner */ int yywrap( void ) { return 1; } /* Called to get up to 'max_size' bytes of the command to be parsed */ int debugger_command_input( char *buf, int *result, int max_size ) { size_t length = strlen( command_ptr ); if( !length ) { return 0; } else if( length < (size_t)max_size ) { memcpy( buf, command_ptr, length ); *result = length; command_ptr += length; return 1; } else { memcpy( buf, command_ptr, max_size ); *result = max_size; command_ptr += max_size; return 1; } } /* Convert a register name to a useful index value */ int debugger_register_hash( const char *name ) { int hash = 0x0000, primed = 0; size_t length; const char *ptr; length = strlen( name ); if( name[ length - 1 ] == '\'' ) { primed = 1; length--; } for( ptr = name; ptr < name + length; ptr++ ) { hash <<= 8; hash |= tolower( *ptr ); } if( primed ) hash |= 0x8000; switch( hash ) { case 0x0061: case 0x8061: /* A, A' */ case 0x0066: case 0x8066: /* F, F' */ case 0x0062: case 0x8062: /* B, B' */ case 0x0063: case 0x8063: /* C, C' */ case 0x0064: case 0x8064: /* D, D' */ case 0x0065: case 0x8065: /* E, E' */ case 0x0068: case 0x8068: /* H, H' */ case 0x006c: case 0x806c: /* L, L' */ case 0x6166: case 0xe166: /* AF, AF' */ case 0x6263: case 0xe263: /* BC, BC' */ case 0x6465: case 0xe465: /* DE, DE' */ case 0x686c: case 0xe86c: /* HL, HL' */ case 0x7370: /* SP */ case 0x7063: /* PC */ case 0x6978: /* IX */ case 0x6979: /* IY */ return hash; default: return -1; } } /* Utility functions called by the bison parser */ /* The error callback if yyparse finds an error */ void yyerror( const char *s ) { ui_error( UI_ERROR_ERROR, "Invalid debugger command: %s", s ); } /* Get the value of a register */ libspectrum_word debugger_register_get( int which ) { switch( which ) { /* 8-bit registers */ case 0x0061: return A; case 0x8061: return A_; case 0x0066: return F; case 0x8066: return F_; case 0x0062: return B; case 0x8062: return B_; case 0x0063: return C; case 0x8063: return C_; case 0x0064: return D; case 0x8064: return D_; case 0x0065: return E; case 0x8065: return E_; case 0x0068: return H; case 0x8068: return H_; case 0x006c: return L; case 0x806c: return L_; /* 16-bit registers */ case 0x6166: return AF; case 0xe166: return AF_; case 0x6263: return BC; case 0xe263: return BC_; case 0x6465: return DE; case 0xe465: return DE_; case 0x686c: return HL; case 0xe86c: return HL_; case 0x7370: return SP; case 0x7063: return PC; case 0x6978: return IX; case 0x6979: return IY; default: ui_error( UI_ERROR_ERROR, "attempt to get unknown register '%d'", which ); return 0; } } /* Set the value of a register */ void debugger_register_set( int which, libspectrum_word value ) { switch( which ) { /* 8-bit registers */ case 0x0061: A = value; break; case 0x8061: A_ = value; break; case 0x0066: F = value; break; case 0x8066: F_ = value; break; case 0x0062: B = value; break; case 0x8062: B_ = value; break; case 0x0063: C = value; break; case 0x8063: C_ = value; break; case 0x0064: D = value; break; case 0x8064: D_ = value; break; case 0x0065: E = value; break; case 0x8065: E_ = value; break; case 0x0068: H = value; break; case 0x8068: H_ = value; break; case 0x006c: L = value; break; case 0x806c: L_ = value; break; /* 16-bit registers */ case 0x6166: AF = value; break; case 0xe166: AF_ = value; break; case 0x6263: BC = value; break; case 0xe263: BC_ = value; break; case 0x6465: DE = value; break; case 0xe465: DE_ = value; break; case 0x686c: HL = value; break; case 0xe86c: HL_ = value; break; case 0x7370: SP = value; break; case 0x7063: PC = value; break; case 0x6978: IX = value; break; case 0x6979: IY = value; break; default: ui_error( UI_ERROR_ERROR, "attempt to set unknown register '%d'", which ); break; } } /* Get the textual representation of a register */ const char * debugger_register_text( int which ) { switch( which ) { /* 8-bit registers */ case 0x0061: return "A"; case 0x8061: return "A'"; case 0x0066: return "F"; case 0x8066: return "F'"; case 0x0062: return "B"; case 0x8062: return "B'"; case 0x0063: return "C"; case 0x8063: return "C'"; case 0x0064: return "D"; case 0x8064: return "D'"; case 0x0065: return "E"; case 0x8065: return "E'"; case 0x0068: return "H"; case 0x8068: return "H'"; case 0x006c: return "L"; case 0x806c: return "L'"; /* 16-bit registers */ case 0x6166: return "AF"; case 0xe166: return "AF'"; case 0x6263: return "BC"; case 0xe263: return "BC'"; case 0x6465: return "DE"; case 0xe465: return "DE'"; case 0x686c: return "HL"; case 0xe86c: return "HL'"; case 0x7370: return "SP"; case 0x7063: return "PC"; case 0x6978: return "IX"; case 0x6979: return "IY"; default: ui_error( UI_ERROR_ERROR, "attempt to get unknown register '%d'", which ); return "(invalid)"; } }