
%{

/* Parser for command lines in the Wine debugger
 *
 * Version 1.0
 * Eric Youngdale
 * 9/93
 */

#include <stdio.h>
#include <signal.h>
#include "ldt.h"
#include "windows.h"
#include "wine.h"

#define YYSTYPE int

#include "regpos.h"
extern FILE * yyin;
unsigned int * regval = NULL;
unsigned int dbg_mask = 0;
unsigned int dbg_mode = 0;

void issue_prompt(void);
void mode_command(int);
%}


%token CONT
%token QUIT
%token HELP
%token BACKTRACE
%token INFO
%token STACK
%token SEGMENTS
%token REG
%token REGS
%token NUM
%token ENABLE
%token DISABLE
%token BREAK
%token SET
%token MODE
%token PRINT
%token FILE_IDENTIFIER
%token IDENTIFIER
%token NO_SYMBOL
%token SYMBOLFILE
%token DEFINE
%token ABORT

%%

 input:  /* empty */
	| input line  { issue_prompt(); }

 line:		'\n'
	| infocmd '\n'
	| error '\n'       { yyerrok; }
	| QUIT  '\n'       { exit(0); }
	| 'q' '\n'         { exit(0); }
	| HELP  '\n'       { dbg_help(); }
	| CONT '\n'        { return 0; }
	| 'c' '\n'         { return 0; }
	| ABORT '\n'       { kill(getpid(), SIGABRT); }
 	| SYMBOLFILE FILE_IDENTIFIER '\n' { read_symboltable($2); }
	| DEFINE IDENTIFIER expr '\n'  { add_hash($2, 0, $3); }
	| MODE NUM	   { mode_command($2); }
	| ENABLE NUM	   { enable_break($2); }
	| DISABLE NUM	   { disable_break($2); }
	| BREAK '*' expr   { add_break($3); }
	| x_command
	| BACKTRACE '\n'   { dbg_bt(); }
	| print_command
	| deposit_command

deposit_command:
	SET REG '=' expr '\n' { if(regval) regval[$2] = $4; else application_not_running();}
	| SET '*' expr '=' expr '\n' { *((unsigned int *) $3) = $5; }
	| SET symbol '=' expr '\n' { *((unsigned int *) $2) = $4; }


x_command:
	  'x' expr  '\n' { examine_memory($2, 1, 'x'); }
	| 'x' '/' fmt expr  '\n' { examine_memory($4, 1, $3); }
	| 'x' '/' NUM fmt expr  '\n' { examine_memory($5, $3, $4); }

print:
	  'p'
	| PRINT
	
 print_command:
	  print expr '\n' { examine_memory(((unsigned int) &$2 ), 1, 'x'); }
	| print '/' fmt expr '\n' { examine_memory((unsigned int) &$4, 1, $3); }
	| print '/' NUM fmt expr '\n' { examine_memory((unsigned int) &$5, $3, $4); }

 fmt:  'x'     { $$ = 'x'; }
	| 'd'  { $$ = 'd'; }
	| 'i'  { $$ = 'i'; }
	| 'w'  { $$ = 'w'; }
	| 's'  { $$ = 's'; }
	| 'c'  { $$ = 'c'; }
	| 'b' { $$ = 'b'; }

 symbol: IDENTIFIER             { $$ = find_hash($1);
			           if($$ == 0xffffffff) {
					   fprintf(stderr,"Symbol %s not found\n", $1);
					   YYERROR;
				   }
			        } 

 expr:  NUM			{ $$ = $1;	}
	| REG			{ if(regval) $$ = regval[$1]; else application_not_running();}
	| symbol   		{ $$ = $1; }
	| expr '+' NUM		{ $$ = $1 + $3; }
	| expr '-' NUM		{ $$ = $1 - $3; }
	| '(' expr ')'		{ $$ = $2; }
	| '*' expr		{ $$ = *((unsigned int *) $2); }
	
 infocmd: INFO REGS     { info_reg(); }
	| INFO STACK    { info_stack(); }
	| INFO SEGMENTS { LDT_Print(); }
	| INFO BREAK    { info_break(); }


%%

void 
issue_prompt(){
#ifndef USE_READLINE
	fprintf(stderr,"Wine-dbg>");
#endif
}

void mode_command(int newmode)
{
  if(newmode == 16){
    dbg_mask = 0xffff;
    dbg_mode = 16;
    return;
  }
  if(newmode == 32){ 
    dbg_mask = 0xffffffff;
    dbg_mode = 32;
    return;
  }
  fprintf(stderr,"Invalid mode (use 16 or 32)\n");
}

static int loaded_symbols = 0;

void
wine_debug(int signal, int * regs)
{
	static int dummy_regs[32];
	char SymbolTableFile[256];
#ifdef YYDEBUG
	yydebug = 0;
#endif

	yyin = stdin;
	regval = regs ? regs : dummy_regs;

	if (SC_CS == WINE_CODE_SELECTOR)
        {
		dbg_mask = 0xffffffff;
		dbg_mode = 32;
	} else
        {
		dbg_mask = 0xffff;
		dbg_mode = 16;
	}
	fprintf(stderr,"In %d bit mode.\n", dbg_mode);

	if(dbg_mode == 32 && !loaded_symbols)
        {
		loaded_symbols++;
		GetPrivateProfileString("wine", "SymbolTableFile", "wine.sym",
			SymbolTableFile, sizeof(SymbolTableFile), WINE_INI);
		read_symboltable(SymbolTableFile);
	}

	/* Remove the breakpoints from memory... */
	insert_break(0);

	/* If we stopped on a breakpoint, report this fact */
	if(signal == SIGTRAP)
	  {
	    unsigned int addr;
	    int bpnum;
	    addr = SC_EIP(dbg_mask);
	    if((addr & 0xffff0000) == 0 && dbg_mode == 16)
	      addr = PTR_SEG_OFF_TO_LIN( SC_CS, addr );
	    if(should_continue(bpnum=get_bpnum(addr))){
		insert_break(1);
		return;
	    }
	    fprintf(stderr,"Stopped on breakpoint %d\n", bpnum);
	  }

	/* Show where we crashed */
	if(regs)
	  examine_memory(SC_EIP(dbg_mask), 1, 'i');

	issue_prompt();

	yyparse();
	flush_symbols();

	/* Re-insert the breakpoints from memory... */
	insert_break(1);

	fprintf(stderr,"Returning to Wine...\n");

}


int yyerror(char * s)
{
	fprintf(stderr,"%s\n", s);
        return 0;
}

