mirror of
https://git.code.sf.net/p/fuse-emulator/fuse
synced 2026-01-28 14:20:54 +03:00
268 lines
7.0 KiB
Plaintext
268 lines
7.0 KiB
Plaintext
/* commandy.y: Parse a debugger command
|
|
Copyright (c) 2002-2004 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 <config.h>
|
|
|
|
#include <stdio.h> /* Needed by NetBSD yacc */
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "debugger.h"
|
|
#include "debugger_internals.h"
|
|
#include "ui/ui.h"
|
|
#include "z80/z80.h"
|
|
#include "z80/z80_macros.h"
|
|
|
|
#define YYDEBUG 1
|
|
#define YYERROR_VERBOSE
|
|
|
|
%}
|
|
|
|
%union {
|
|
|
|
int token;
|
|
int reg;
|
|
|
|
libspectrum_dword integer;
|
|
debugger_breakpoint_type bptype;
|
|
debugger_breakpoint_life bplife;
|
|
struct { int value1; libspectrum_word value2; } pair;
|
|
|
|
debugger_expression* exp;
|
|
|
|
}
|
|
|
|
/* Tokens as returned from the Flex scanner (commandl.l) */
|
|
|
|
/* Some tokens are named DEBUGGER_* to avoid clashes with <windows.h> */
|
|
|
|
%token LOGICAL_OR /* || */
|
|
%token LOGICAL_AND /* && */
|
|
%token <token> COMPARISION /* < > <= >= */
|
|
%token <token> EQUALITY /* == != */
|
|
%token <token> NEGATE /* ! ~ */
|
|
%token <token> TIMES_DIVIDE /* * / */
|
|
|
|
%token BASE
|
|
%token BREAK
|
|
%token TBREAK
|
|
%token CLEAR
|
|
%token CONDITION
|
|
%token CONTINUE
|
|
%token DEBUGGER_DELETE
|
|
%token DISASSEMBLE
|
|
%token FINISH
|
|
%token IF
|
|
%token DEBUGGER_IGNORE
|
|
%token NEXT
|
|
%token DEBUGGER_OUT
|
|
%token PORT
|
|
%token READ
|
|
%token SET
|
|
%token STEP
|
|
%token TIME
|
|
%token WRITE
|
|
|
|
%token <integer> PAGE
|
|
%token <reg> DEBUGGER_REGISTER
|
|
|
|
%token <integer> NUMBER
|
|
|
|
%token DEBUGGER_ERROR
|
|
|
|
/* Derived types */
|
|
|
|
%type <bplife> breakpointlife
|
|
%type <bptype> breakpointtype
|
|
%type <integer> pageornumber
|
|
%type <pair> breakpointpair
|
|
%type <bptype> portbreakpointtype
|
|
%type <integer> numberorpc
|
|
%type <integer> number
|
|
|
|
%type <exp> optionalcondition
|
|
|
|
%type <exp> expressionornull
|
|
%type <exp> expression;
|
|
|
|
/* Operator precedences */
|
|
|
|
/* Low precedence */
|
|
|
|
%left LOGICAL_OR
|
|
%left LOGICAL_AND
|
|
%left '|'
|
|
%left '^'
|
|
%left '&'
|
|
%left EQUALITY
|
|
%left COMPARISION
|
|
%left '+' '-'
|
|
%left TIMES_DIVIDE
|
|
%right NEGATE /* Unary minus, unary plus, !, ~ */
|
|
|
|
/* High precedence */
|
|
|
|
%%
|
|
|
|
input: /* empty */
|
|
| command
|
|
| error
|
|
;
|
|
|
|
command: BASE number { debugger_output_base = $2; }
|
|
| breakpointlife breakpointtype breakpointpair optionalcondition {
|
|
debugger_breakpoint_add_address( $2, $3.value1, $3.value2, 0, $1,
|
|
$4 );
|
|
}
|
|
| breakpointlife PORT portbreakpointtype breakpointpair optionalcondition {
|
|
int mask; libspectrum_word port;
|
|
mask = $4.value1; port = $4.value2;
|
|
if( mask == -1 ) mask = ( port < 0x100 ? 0x00ff : 0xffff );
|
|
debugger_breakpoint_add_port( $3, port, mask, 0, $1, $5 );
|
|
}
|
|
| breakpointlife TIME number optionalcondition {
|
|
debugger_breakpoint_add_time( DEBUGGER_BREAKPOINT_TYPE_TIME,
|
|
$3, 0, $1, $4 );
|
|
}
|
|
| CLEAR numberorpc { debugger_breakpoint_clear( $2 ); }
|
|
| CONDITION NUMBER expressionornull {
|
|
debugger_breakpoint_set_condition( $2, $3 );
|
|
}
|
|
| CONTINUE { debugger_run(); }
|
|
| DEBUGGER_DELETE { debugger_breakpoint_remove_all(); }
|
|
| DEBUGGER_DELETE number { debugger_breakpoint_remove( $2 ); }
|
|
| DISASSEMBLE number { ui_debugger_disassemble( $2 ); }
|
|
| FINISH { debugger_breakpoint_exit(); }
|
|
| DEBUGGER_IGNORE NUMBER number {
|
|
debugger_breakpoint_ignore( $2, $3 );
|
|
}
|
|
| NEXT { debugger_next(); }
|
|
| DEBUGGER_OUT number NUMBER { debugger_port_write( $2, $3 ); }
|
|
| SET NUMBER number { debugger_poke( $2, $3 ); }
|
|
| SET DEBUGGER_REGISTER number { debugger_register_set( $2, $3 ); }
|
|
| STEP { debugger_step(); }
|
|
;
|
|
|
|
breakpointlife: BREAK { $$ = DEBUGGER_BREAKPOINT_LIFE_PERMANENT; }
|
|
| TBREAK { $$ = DEBUGGER_BREAKPOINT_LIFE_ONESHOT; }
|
|
;
|
|
|
|
breakpointtype: /* empty */ { $$ = DEBUGGER_BREAKPOINT_TYPE_EXECUTE; }
|
|
| READ { $$ = DEBUGGER_BREAKPOINT_TYPE_READ; }
|
|
| WRITE { $$ = DEBUGGER_BREAKPOINT_TYPE_WRITE; }
|
|
;
|
|
|
|
breakpointpair: numberorpc { $$.value1 = -1; $$.value2 = $1; }
|
|
| pageornumber ':' number { $$.value1 = $1; $$.value2 = $3; }
|
|
;
|
|
|
|
pageornumber: PAGE { $$ = $1; }
|
|
| number { $$ = $1; }
|
|
|
|
portbreakpointtype: READ { $$ = DEBUGGER_BREAKPOINT_TYPE_PORT_READ; }
|
|
| WRITE { $$ = DEBUGGER_BREAKPOINT_TYPE_PORT_WRITE; }
|
|
;
|
|
|
|
optionalcondition: /* empty */ { $$ = NULL; }
|
|
| IF expression { $$ = $2; }
|
|
;
|
|
|
|
numberorpc: /* empty */ { $$ = PC; }
|
|
| number { $$ = $1; }
|
|
;
|
|
|
|
expressionornull: /* empty */ { $$ = NULL; }
|
|
| expression { $$ = $1; }
|
|
;
|
|
|
|
number: expression { $$ = debugger_expression_evaluate( $1 ); }
|
|
;
|
|
|
|
expression: NUMBER { $$ = debugger_expression_new_number( $1 );
|
|
if( !$$ ) YYABORT;
|
|
}
|
|
| DEBUGGER_REGISTER { $$ = debugger_expression_new_register( $1 );
|
|
if( !$$ ) YYABORT;
|
|
}
|
|
| '(' expression ')' { $$ = $2; }
|
|
| '+' expression %prec NEGATE { $$ = $2; }
|
|
| '-' expression %prec NEGATE {
|
|
$$ = debugger_expression_new_unaryop( '-', $2 );
|
|
if( !$$ ) YYABORT;
|
|
}
|
|
| NEGATE expression {
|
|
$$ = debugger_expression_new_unaryop( $1, $2 );
|
|
if( !$$ ) YYABORT;
|
|
}
|
|
| expression '+' expression {
|
|
$$ = debugger_expression_new_binaryop( '+', $1, $3 );
|
|
if( !$$ ) YYABORT;
|
|
}
|
|
| expression '-' expression {
|
|
$$ = debugger_expression_new_binaryop( '-', $1, $3 );
|
|
if( !$$ ) YYABORT;
|
|
}
|
|
| expression TIMES_DIVIDE expression {
|
|
$$ = debugger_expression_new_binaryop( $2, $1, $3 );
|
|
if( !$$ ) YYABORT;
|
|
}
|
|
| expression EQUALITY expression {
|
|
$$ = debugger_expression_new_binaryop( $2, $1, $3 );
|
|
if( !$$ ) YYABORT;
|
|
}
|
|
| expression COMPARISION expression {
|
|
$$ = debugger_expression_new_binaryop( $2, $1, $3 );
|
|
if( !$$ ) YYABORT;
|
|
}
|
|
| expression '&' expression {
|
|
$$ = debugger_expression_new_binaryop( '&', $1, $3 );
|
|
if( !$$ ) YYABORT;
|
|
}
|
|
| expression '^' expression {
|
|
$$ = debugger_expression_new_binaryop( '^', $1, $3 );
|
|
if( !$$ ) YYABORT;
|
|
}
|
|
| expression '|' expression {
|
|
$$ = debugger_expression_new_binaryop( '|', $1, $3 );
|
|
if( !$$ ) YYABORT;
|
|
}
|
|
| expression LOGICAL_AND expression {
|
|
$$ = debugger_expression_new_binaryop(
|
|
DEBUGGER_TOKEN_LOGICAL_AND, $1, $3
|
|
);
|
|
if( !$$ ) YYABORT;
|
|
}
|
|
| expression LOGICAL_OR expression {
|
|
$$ = debugger_expression_new_binaryop(
|
|
DEBUGGER_TOKEN_LOGICAL_OR, $1, $3
|
|
);
|
|
if( !$$ ) YYABORT;
|
|
}
|
|
;
|
|
|
|
%%
|