dbg.y 24.8 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1
%{
Alexandre Julliard's avatar
Alexandre Julliard committed
2 3
/*
 * Parser for command lines in the Wine debugger
Alexandre Julliard's avatar
Alexandre Julliard committed
4
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
5
 * Copyright 1993 Eric Youngdale
Alexandre Julliard's avatar
Alexandre Julliard committed
6
 * Copyright 1995 Morten Welinder
7
 * Copyright 2000 Eric Pouech
8 9 10 11 12 13 14 15 16 17 18 19 20
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
21
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Alexandre Julliard's avatar
Alexandre Julliard committed
22 23
 */

Patrik Stridvall's avatar
Patrik Stridvall committed
24
#include "config.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
25
#include "wine/port.h"
Patrik Stridvall's avatar
Patrik Stridvall committed
26

27
#include <stdio.h>
28 29
#include <stdlib.h>
#include <string.h>
30 31 32
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
33

Alexandre Julliard's avatar
Alexandre Julliard committed
34
#include "debugger.h"
35
#include "wine/exception.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
36 37
#include "expr.h"

38 39
int dbg_lex(void);
static int dbg_error(const char*);
Alexandre Julliard's avatar
Alexandre Julliard committed
40

Alexandre Julliard's avatar
Alexandre Julliard committed
41 42
%}

Alexandre Julliard's avatar
Alexandre Julliard committed
43 44
%union
{
45 46 47 48 49 50
    struct dbg_lvalue   lvalue;
    char*               string;
    int                 integer;
    IMAGEHLP_LINE       listing;
    struct expr*        expression;
    struct type_expr_t  type;
Alexandre Julliard's avatar
Alexandre Julliard committed
51
}
Alexandre Julliard's avatar
Alexandre Julliard committed
52

53
%token tCONT tPASS tSTEP tLIST tNEXT tQUIT tHELP tBACKTRACE tALL tINFO tUP tDOWN
54 55
%token tENABLE tDISABLE tBREAK tHBREAK tWATCH tDELETE tSET tPRINT tEXAM
%token tABORT tECHO
56
%token tCLASS tMAPS tSTACK tSEGMENTS tSYMBOL tREGS tALLREGS tWND tQUEUE tLOCAL tEXCEPTION
57 58
%token tPROCESS tTHREAD tEOL tEOF
%token tFRAME tSHARE tMODULE tCOND tDISPLAY tUNDISPLAY tDISASSEMBLE
Eric Pouech's avatar
Eric Pouech committed
59
%token tSTEPI tNEXTI tFINISH tSHOW tDIR tWHATIS tSOURCE
60
%token <string> tPATH tIDENTIFIER tSTRING tDEBUGSTR tINTVAR
Alexandre Julliard's avatar
Alexandre Julliard committed
61
%token <integer> tNUM tFORMAT
62 63
%token tSYMBOLFILE tRUN tATTACH tDETACH tMAINTENANCE tTYPE tMINIDUMP
%token tNOPROCESS
Alexandre Julliard's avatar
Alexandre Julliard committed
64

65
%token tCHAR tSHORT tINT tLONG tFLOAT tDOUBLE tUNSIGNED tSIGNED
Alexandre Julliard's avatar
Alexandre Julliard committed
66 67
%token tSTRUCT tUNION tENUM

Alexandre Julliard's avatar
Alexandre Julliard committed
68 69 70 71 72 73 74 75 76 77 78 79
/* %left ',' */
/* %left '=' OP_OR_EQUAL OP_XOR_EQUAL OP_AND_EQUAL OP_SHL_EQUAL \
         OP_SHR_EQUAL OP_PLUS_EQUAL OP_MINUS_EQUAL \
         OP_TIMES_EQUAL OP_DIVIDE_EQUAL OP_MODULO_EQUAL */
/* %left OP_COND */ /* ... ? ... : ... */
%left OP_LOR
%left OP_LAND
%left '|'
%left '^'
%left '&'
%left OP_EQ OP_NE
%left '<' '>' OP_LE OP_GE
Alexandre Julliard's avatar
Alexandre Julliard committed
80
%left OP_SHL OP_SHR
Alexandre Julliard's avatar
Alexandre Julliard committed
81 82 83
%left '+' '-'
%left '*' '/' '%'
%left OP_SIGN '!' '~' OP_DEREF /* OP_INC OP_DEC OP_ADDR */
84
%left '.' '[' OP_DRF OP_SCOPE
Alexandre Julliard's avatar
Alexandre Julliard committed
85 86
%nonassoc ':'

87 88 89
%type <expression> expr lvalue
%type <lvalue> expr_lvalue lvalue_addr
%type <integer> expr_rvalue
90
%type <string> pathname identifier cpp_identifier
Alexandre Julliard's avatar
Alexandre Julliard committed
91
%type <listing> list_arg
92
%type <type> type_expr
Alexandre Julliard's avatar
Alexandre Julliard committed
93 94 95

%%

96 97
input:
      line
98
    | input line
Alexandre Julliard's avatar
Alexandre Julliard committed
99
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
100

101 102
line:
      command tEOL              { expr_free_all(); }
Alexandre Julliard's avatar
Alexandre Julliard committed
103
    | tEOL
Eric Pouech's avatar
Eric Pouech committed
104
    | tEOF                      { return 1; }
105
    | error tEOL               	{ yyerrok; expr_free_all(); }
Alexandre Julliard's avatar
Alexandre Julliard committed
106
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
107 108

command:
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
      tQUIT                     { return 1; }
    | tHELP                     { print_help(); }
    | tHELP tINFO               { info_help(); }
    | tPASS                     { dbg_wait_next_exception(DBG_EXCEPTION_NOT_HANDLED, 0, 0); }
    | tCONT                     { dbg_wait_next_exception(DBG_CONTINUE, 1,  dbg_exec_cont); }
    | tCONT tNUM              	{ dbg_wait_next_exception(DBG_CONTINUE, $2, dbg_exec_cont); }
    | tSTEP                    	{ dbg_wait_next_exception(DBG_CONTINUE, 1,  dbg_exec_step_into_line); }
    | tSTEP tNUM                { dbg_wait_next_exception(DBG_CONTINUE, $2, dbg_exec_step_into_line); }
    | tNEXT                     { dbg_wait_next_exception(DBG_CONTINUE, 1,  dbg_exec_step_over_line); }
    | tNEXT tNUM                { dbg_wait_next_exception(DBG_CONTINUE, $2, dbg_exec_step_over_line); }
    | tSTEPI                    { dbg_wait_next_exception(DBG_CONTINUE, 1,  dbg_exec_step_into_insn); }
    | tSTEPI tNUM               { dbg_wait_next_exception(DBG_CONTINUE, $2, dbg_exec_step_into_insn); }
    | tNEXTI                    { dbg_wait_next_exception(DBG_CONTINUE, 1,  dbg_exec_step_over_insn); }
    | tNEXTI tNUM               { dbg_wait_next_exception(DBG_CONTINUE, $2, dbg_exec_step_over_insn); }
    | tFINISH     	       	{ dbg_wait_next_exception(DBG_CONTINUE, 0,  dbg_exec_finish); }
    | tABORT                   	{ abort(); }
125 126 127 128 129 130 131
    | tBACKTRACE     	       	{ stack_backtrace(dbg_curr_tid); }
    | tBACKTRACE tNUM          	{ stack_backtrace($2); }
    | tBACKTRACE tALL           { stack_backtrace(-1); }
    | tUP     		       	{ stack_set_frame(dbg_curr_thread->curr_frame + 1);  }
    | tUP tNUM     	       	{ stack_set_frame(dbg_curr_thread->curr_frame + $2); }
    | tDOWN     	       	{ stack_set_frame(dbg_curr_thread->curr_frame - 1);  }
    | tDOWN tNUM     	       	{ stack_set_frame(dbg_curr_thread->curr_frame - $2); }
132 133 134
    | tFRAME tNUM              	{ stack_set_frame($2); }
    | tSHOW tDIR     	       	{ source_show_path(); }
    | tDIR pathname            	{ source_add_path($2); }
135
    | tDIR     		       	{ source_nuke_path(dbg_curr_process); }
136 137 138 139 140
    | tCOND tNUM               	{ break_add_condition($2, NULL); }
    | tCOND tNUM expr     	{ break_add_condition($2, $3); }
    | tSOURCE pathname          { parser($2); }
    | tSYMBOLFILE pathname     	{ symbol_read_symtable($2, 0); }
    | tSYMBOLFILE pathname expr_rvalue { symbol_read_symtable($2, $3); }
141
    | tWHATIS expr_lvalue       { dbg_printf("type = "); types_print_type(&$2.type, FALSE); dbg_printf("\n"); }
142
    | tATTACH tNUM     		{ dbg_attach_debuggee($2, FALSE); dbg_active_wait_for_first_exception(); }
143
    | tDETACH                   { dbg_curr_process->process_io->close_process(dbg_curr_process, FALSE); }
144
    | tMINIDUMP pathname        { minidump_write($2, (dbg_curr_thread && dbg_curr_thread->in_exception) ? &dbg_curr_thread->excpt_record : NULL);}
145
    | tECHO tSTRING             { dbg_printf("%s\n", $2); }
146
    | run_command
Alexandre Julliard's avatar
Alexandre Julliard committed
147
    | list_command
Alexandre Julliard's avatar
Alexandre Julliard committed
148
    | disassemble_command
Alexandre Julliard's avatar
Alexandre Julliard committed
149 150
    | set_command
    | x_command
151 152
    | print_command     
    | break_command
153
    | watch_command
154
    | display_command
Alexandre Julliard's avatar
Alexandre Julliard committed
155
    | info_command
156
    | maintenance_command
157
    | noprocess_state
Alexandre Julliard's avatar
Alexandre Julliard committed
158
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
159

160 161
pathname:
      identifier                { $$ = $1; }
162
    | tSTRING                   { $$ = $1; }
163
    | tPATH                     { $$ = $1; }
164 165
    ;

166
cpp_identifier:
167
      tIDENTIFIER               { $$ = $1; }
168 169
    | identifier OP_SCOPE tIDENTIFIER { $$ = lexeme_alloc_size(strlen($1) + 2 + strlen($3) + 1);
                                       sprintf($$, "%s::%s", $1, $3); }
Alexandre Julliard's avatar
Alexandre Julliard committed
170
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
171

172 173 174 175 176 177
identifier:
      cpp_identifier            { $$ = $1; }
    | tIDENTIFIER '!' cpp_identifier { $$ = lexeme_alloc_size(strlen($1) + 1 + strlen($3) + 1);
                                       sprintf($$, "%s!%s", $1, $3); }
    ;

178 179 180 181 182
list_arg:
      tNUM		        { $$.FileName = NULL; $$.LineNumber = $1; }
    | pathname ':' tNUM	        { $$.FileName = $1; $$.LineNumber = $3; }
    | identifier	        { symbol_get_line(NULL, $1, &$$); }
    | pathname ':' identifier   { symbol_get_line($3, $1, &$$); }
183 184
    | '*' expr_lvalue	        { DWORD disp; $$.SizeOfStruct = sizeof($$);
                                  SymGetLineFromAddr(dbg_curr_process->handle, (unsigned long)memory_to_linear_addr(& $2.addr), &disp, & $$); }
Alexandre Julliard's avatar
Alexandre Julliard committed
185
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
186

187 188 189
run_command:
      tRUN                      { dbg_run_debuggee(NULL); }
    | tRUN tSTRING              { dbg_run_debuggee($2); }
Alexandre Julliard's avatar
Alexandre Julliard committed
190
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
191

Alexandre Julliard's avatar
Alexandre Julliard committed
192
list_command:
193 194 195 196 197
      tLIST                     { source_list(NULL, NULL, 10); }
    | tLIST '-'                 { source_list(NULL,  NULL, -10); }
    | tLIST list_arg            { source_list(& $2, NULL, 10); }
    | tLIST ',' list_arg        { source_list(NULL, & $3, -10); }
    | tLIST list_arg ',' list_arg      { source_list(& $2, & $4, 0); }
Alexandre Julliard's avatar
Alexandre Julliard committed
198
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
199

200 201 202 203 204 205 206 207 208 209 210 211
disassemble_command:
      tDISASSEMBLE              { memory_disassemble(NULL, NULL, 10); }
    | tDISASSEMBLE expr_lvalue  { memory_disassemble(&$2, NULL, 10); }
    | tDISASSEMBLE expr_lvalue ',' expr_lvalue { memory_disassemble(&$2, &$4, 0); }
    ;

set_command:
      tSET lvalue_addr '=' expr_rvalue { memory_write_value(&$2, sizeof(int), &$4); }
    | tSET '+' tIDENTIFIER      { info_wine_dbg_channel(TRUE, NULL, $3); }
    | tSET '-' tIDENTIFIER      { info_wine_dbg_channel(FALSE, NULL, $3); }
    | tSET tIDENTIFIER '+' tIDENTIFIER { info_wine_dbg_channel(TRUE, $2, $4); }
    | tSET tIDENTIFIER '-' tIDENTIFIER { info_wine_dbg_channel(FALSE, $2, $4); }
Alexandre Julliard's avatar
Alexandre Julliard committed
212
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
213 214

x_command:
215 216
      tEXAM expr_lvalue         { memory_examine(&$2, 1, 'x'); }
    | tEXAM tFORMAT expr_lvalue { memory_examine(&$3, $2 >> 8, $2 & 0xff); }
Alexandre Julliard's avatar
Alexandre Julliard committed
217
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
218 219

print_command:
220 221
      tPRINT expr_lvalue         { print_value(&$2, 0, 0); }
    | tPRINT tFORMAT expr_lvalue { if (($2 >> 8) == 1) print_value(&$3, $2 & 0xff, 0); else dbg_printf("Count is meaningless in print command\n"); }
Alexandre Julliard's avatar
Alexandre Julliard committed
222
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
223

224
break_command:
225 226 227 228 229 230 231 232 233 234
      tBREAK '*' expr_lvalue    { break_add_break_from_lvalue(&$3, TRUE); }
    | tBREAK identifier         { break_add_break_from_id($2, -1, TRUE); }
    | tBREAK identifier ':' tNUM { break_add_break_from_id($2, $4, TRUE); }
    | tBREAK tNUM     	        { break_add_break_from_lineno($2, TRUE); }
    | tBREAK                    { break_add_break_from_lineno(-1, TRUE); }
    | tHBREAK '*' expr_lvalue   { break_add_break_from_lvalue(&$3, FALSE); }
    | tHBREAK identifier        { break_add_break_from_id($2, -1, FALSE); }
    | tHBREAK identifier ':' tNUM { break_add_break_from_id($2, $4, FALSE); }
    | tHBREAK tNUM     	        { break_add_break_from_lineno($2, FALSE); }
    | tHBREAK                   { break_add_break_from_lineno(-1, FALSE); }
235 236 237 238 239 240
    | tENABLE tNUM              { break_enable_xpoint($2, TRUE); }
    | tENABLE tBREAK tNUM     	{ break_enable_xpoint($3, TRUE); }
    | tDISABLE tNUM             { break_enable_xpoint($2, FALSE); }
    | tDISABLE tBREAK tNUM     	{ break_enable_xpoint($3, FALSE); }
    | tDELETE tNUM      	{ break_delete_xpoint($2); }
    | tDELETE tBREAK tNUM      	{ break_delete_xpoint($3); }
Alexandre Julliard's avatar
Alexandre Julliard committed
241
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
242

243
watch_command:
244
      tWATCH '*' expr_lvalue    { break_add_watch_from_lvalue(&$3); }
245
    | tWATCH identifier         { break_add_watch_from_id($2); }
Alexandre Julliard's avatar
Alexandre Julliard committed
246
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
247

248
display_command:
249
      tDISPLAY     	       	{ display_print(); }
250 251
    | tDISPLAY expr            	{ display_add($2, 1, 0); }
    | tDISPLAY tFORMAT expr     { display_add($3, $2 >> 8, $2 & 0xff); }
252 253 254 255 256 257
    | tENABLE tDISPLAY tNUM     { display_enable($3, TRUE); }
    | tDISABLE tDISPLAY tNUM    { display_enable($3, FALSE); }
    | tDELETE tDISPLAY tNUM     { display_delete($3); }
    | tDELETE tDISPLAY         	{ display_delete(-1); }
    | tUNDISPLAY tNUM          	{ display_delete($2); }
    | tUNDISPLAY               	{ display_delete(-1); }
Alexandre Julliard's avatar
Alexandre Julliard committed
258
    ;
259

260 261 262 263
info_command:
      tINFO tBREAK              { break_info(); }
    | tINFO tSHARE     		{ info_win32_module(0); }
    | tINFO tSHARE expr_rvalue  { info_win32_module($3); }
264 265
    | tINFO tREGS               { be_cpu->print_context(dbg_curr_thread->handle, &dbg_context, 0); }
    | tINFO tALLREGS            { be_cpu->print_context(dbg_curr_thread->handle, &dbg_context, 1); }
266
    | tINFO tSEGMENTS expr_rvalue { info_win32_segments($3 >> 3, 1); }
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
    | tINFO tSEGMENTS           { info_win32_segments(0, -1); }
    | tINFO tSTACK              { stack_info(); }
    | tINFO tSYMBOL tSTRING     { symbol_info($3); }
    | tINFO tLOCAL              { symbol_info_locals(); }
    | tINFO tDISPLAY            { display_info(); }
    | tINFO tCLASS              { info_win32_class(NULL, NULL); }
    | tINFO tCLASS tSTRING     	{ info_win32_class(NULL, $3); }
    | tINFO tWND                { info_win32_window(NULL, FALSE); }
    | tINFO tWND expr_rvalue    { info_win32_window((HWND)$3, FALSE); }
    | tINFO '*' tWND            { info_win32_window(NULL, TRUE); }
    | tINFO '*' tWND expr_rvalue { info_win32_window((HWND)$4, TRUE); }
    | tINFO tPROCESS            { info_win32_processes(); }
    | tINFO tTHREAD             { info_win32_threads(); }
    | tINFO tEXCEPTION          { info_win32_exceptions(dbg_curr_tid); }
    | tINFO tEXCEPTION expr_rvalue { info_win32_exceptions($3); }
    | tINFO tMAPS               { info_win32_virtual(dbg_curr_pid); }
    | tINFO tMAPS expr_rvalue   { info_win32_virtual($3); }
Alexandre Julliard's avatar
Alexandre Julliard committed
284
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
285

286
maintenance_command:
287
      tMAINTENANCE tTYPE        { print_types(); }
288 289
    | tMAINTENANCE tMODULE tSTRING { tgt_module_load($3, FALSE); }
    | tMAINTENANCE '*' tMODULE tSTRING { tgt_module_load($4, TRUE); }
290 291
    ;

292
noprocess_state:
293
      tNOPROCESS                 {} /* <CR> shall not barf anything */
294
    | tNOPROCESS tBACKTRACE tALL { stack_backtrace(-1); } /* can backtrace all threads with no attached process */
295
    | tNOPROCESS tSTRING         { dbg_printf("No process loaded, cannot execute '%s'\n", $2); }
Alexandre Julliard's avatar
Alexandre Julliard committed
296
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
297 298

type_expr:
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
      tCHAR			{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_char; }
    | tINT			{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_int; }
    | tLONG tINT		{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_long_int; }
    | tLONG     		{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_long_int; }
    | tUNSIGNED tINT		{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_int; }
    | tUNSIGNED 		{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_int; }
    | tLONG tUNSIGNED tINT	{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_long_int; }
    | tLONG tUNSIGNED   	{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_long_int; }
    | tSHORT tINT		{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_short_int; }
    | tSHORT    		{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_short_int; }
    | tSHORT tUNSIGNED tINT	{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_short_int; }
    | tSHORT tUNSIGNED  	{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_short_int; }
    | tSIGNED tCHAR		{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_char_int; }
    | tUNSIGNED tCHAR		{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_char_int; }
    | tLONG tLONG tUNSIGNED tINT{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_longlong_int; }
    | tLONG tLONG tUNSIGNED     { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_longlong_int; }
    | tLONG tLONG tINT          { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_longlong_int; }
    | tLONG tLONG               { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_longlong_int; }
    | tFLOAT			{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_short_real; }
    | tDOUBLE			{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_real; }
    | tLONG tDOUBLE		{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_long_real; }
320
    | type_expr '*'		{ $$ = $1; $$.deref_count++; }
321 322 323 324
    | tCLASS identifier         { $$.type = type_expr_udt_class; $$.deref_count = 0; $$.u.name = $2; }
    | tSTRUCT identifier        { $$.type = type_expr_udt_struct; $$.deref_count = 0; $$.u.name = $2; }
    | tUNION identifier         { $$.type = type_expr_udt_union; $$.deref_count = 0; $$.u.name = $2; }
    | tENUM identifier          { $$.type = type_expr_enumeration; $$.deref_count = 0; $$.u.name = $2; }
Alexandre Julliard's avatar
Alexandre Julliard committed
325
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
326

327 328
expr_lvalue:
      expr                      { $$ = expr_eval($1); }
Alexandre Julliard's avatar
Alexandre Julliard committed
329
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
330

331 332
expr_rvalue:
      expr_lvalue               { $$ = types_extract_as_integer(&$1); }
Alexandre Julliard's avatar
Alexandre Julliard committed
333
    ;
334

Alexandre Julliard's avatar
Alexandre Julliard committed
335 336 337 338 339 340
/*
 * The expr rule builds an expression tree.  When we are done, we call
 * EvalExpr to evaluate the value of the expression.  The advantage of
 * the two-step approach is that it is possible to save expressions for
 * use in 'display' commands, and in conditional watchpoints.
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
341
expr:
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
      tNUM                      { $$ = expr_alloc_sconstant($1); }
    | tSTRING			{ $$ = expr_alloc_string($1); }
    | tINTVAR                   { $$ = expr_alloc_internal_var($1); }
    | identifier		{ $$ = expr_alloc_symbol($1); }
    | expr OP_DRF tIDENTIFIER	{ $$ = expr_alloc_pstruct($1, $3); }
    | expr '.' tIDENTIFIER      { $$ = expr_alloc_struct($1, $3); }
    | identifier '(' ')'	{ $$ = expr_alloc_func_call($1, 0); }
    | identifier '(' expr ')'	{ $$ = expr_alloc_func_call($1, 1, $3); }
    | identifier '(' expr ',' expr ')' { $$ = expr_alloc_func_call($1, 2, $3, $5); }
    | identifier '(' expr ',' expr ',' expr ')'	{ $$ = expr_alloc_func_call($1, 3, $3, $5, $7); }
    | identifier '(' expr ',' expr ',' expr ',' expr ')' { $$ = expr_alloc_func_call($1, 4, $3, $5, $7, $9); }
    | identifier '(' expr ',' expr ',' expr ',' expr ',' expr ')' { $$ = expr_alloc_func_call($1, 5, $3, $5, $7, $9, $11); }
    | expr '[' expr ']'		 { $$ = expr_alloc_binary_op(EXP_OP_ARR, $1, $3); }
    | expr ':' expr		 { $$ = expr_alloc_binary_op(EXP_OP_SEG, $1, $3); }
    | expr OP_LOR expr           { $$ = expr_alloc_binary_op(EXP_OP_LOR, $1, $3); }
    | expr OP_LAND expr          { $$ = expr_alloc_binary_op(EXP_OP_LAND, $1, $3); }
    | expr '|' expr              { $$ = expr_alloc_binary_op(EXP_OP_OR, $1, $3); }
    | expr '&' expr              { $$ = expr_alloc_binary_op(EXP_OP_AND, $1, $3); }
    | expr '^' expr              { $$ = expr_alloc_binary_op(EXP_OP_XOR, $1, $3); }
    | expr OP_EQ expr            { $$ = expr_alloc_binary_op(EXP_OP_EQ, $1, $3); }
    | expr '>' expr              { $$ = expr_alloc_binary_op(EXP_OP_GT, $1, $3); }
    | expr '<' expr              { $$ = expr_alloc_binary_op(EXP_OP_LT, $1, $3); }
    | expr OP_GE expr            { $$ = expr_alloc_binary_op(EXP_OP_GE, $1, $3); }
    | expr OP_LE expr            { $$ = expr_alloc_binary_op(EXP_OP_LE, $1, $3); }
    | expr OP_NE expr            { $$ = expr_alloc_binary_op(EXP_OP_NE, $1, $3); }
    | expr OP_SHL expr           { $$ = expr_alloc_binary_op(EXP_OP_SHL, $1, $3); }
    | expr OP_SHR expr           { $$ = expr_alloc_binary_op(EXP_OP_SHR, $1, $3); }
    | expr '+' expr              { $$ = expr_alloc_binary_op(EXP_OP_ADD, $1, $3); }
    | expr '-' expr              { $$ = expr_alloc_binary_op(EXP_OP_SUB, $1, $3); }
    | expr '*' expr              { $$ = expr_alloc_binary_op(EXP_OP_MUL, $1, $3); }
    | expr '/' expr              { $$ = expr_alloc_binary_op(EXP_OP_DIV, $1, $3); }
    | expr '%' expr              { $$ = expr_alloc_binary_op(EXP_OP_REM, $1, $3); }
    | '-' expr %prec OP_SIGN     { $$ = expr_alloc_unary_op(EXP_OP_NEG, $2); }
Alexandre Julliard's avatar
Alexandre Julliard committed
375
    | '+' expr %prec OP_SIGN     { $$ = $2; }
376 377
    | '!' expr                   { $$ = expr_alloc_unary_op(EXP_OP_NOT, $2); }
    | '~' expr                   { $$ = expr_alloc_unary_op(EXP_OP_LNOT, $2); }
Alexandre Julliard's avatar
Alexandre Julliard committed
378
    | '(' expr ')'               { $$ = $2; }
379 380 381
    | '*' expr %prec OP_DEREF    { $$ = expr_alloc_unary_op(EXP_OP_DEREF, $2); }
    | '&' expr %prec OP_DEREF    { $$ = expr_alloc_unary_op(EXP_OP_ADDR, $2); }
    | '(' type_expr ')' expr %prec OP_DEREF { $$ = expr_alloc_typecast(&$2, $4); }
Alexandre Julliard's avatar
Alexandre Julliard committed
382 383
    ;

Alexandre Julliard's avatar
Alexandre Julliard committed
384 385 386 387
/*
 * The lvalue rule builds an expression tree.  This is a limited form
 * of expression that is suitable to be used as an lvalue.
 */
388 389
lvalue_addr: 
      lvalue                     { $$ = expr_eval($1); }
Alexandre Julliard's avatar
Alexandre Julliard committed
390 391
    ;

392 393
lvalue: 
      tNUM                       { $$ = expr_alloc_sconstant($1); }
394 395 396 397 398 399
    | tINTVAR                    { $$ = expr_alloc_internal_var($1); }
    | identifier		 { $$ = expr_alloc_symbol($1); }
    | lvalue OP_DRF tIDENTIFIER	 { $$ = expr_alloc_pstruct($1, $3); }
    | lvalue '.' tIDENTIFIER	 { $$ = expr_alloc_struct($1, $3); }
    | lvalue '[' expr ']'	 { $$ = expr_alloc_binary_op(EXP_OP_ARR, $1, $3); }
    | '*' expr			 { $$ = expr_alloc_unary_op(EXP_OP_FORCE_DEREF, $2); }
Alexandre Julliard's avatar
Alexandre Julliard committed
400
    ;
401

Alexandre Julliard's avatar
Alexandre Julliard committed
402 403
%%

404
static LONG WINAPI wine_dbg_cmd(EXCEPTION_POINTERS *eptr)
405
{
406
    switch (eptr->ExceptionRecord->ExceptionCode)
407
    {
408
    case DEBUG_STATUS_INTERNAL_ERROR:
409
        dbg_printf("\nWineDbg internal error\n");
410 411
        break;
    case DEBUG_STATUS_NO_SYMBOL:
412
        dbg_printf("\nUndefined symbol\n");
413 414
        break;
    case DEBUG_STATUS_DIV_BY_ZERO:
415
        dbg_printf("\nDivision by zero\n");
416 417
        break;
    case DEBUG_STATUS_BAD_TYPE:
418
        dbg_printf("\nNo type or type mismatch\n");
419 420
        break;
    case DEBUG_STATUS_NO_FIELD:
421 422 423 424
        dbg_printf("\nNo such field in structure or union\n");
        break;
    case DEBUG_STATUS_CANT_DEREF:
        dbg_printf("\nDereference failed (not a pointer, or out of array bounds)\n");
425 426 427
        break;
    case DEBUG_STATUS_ABORT:
        break;
428 429 430
    case DEBUG_STATUS_NOT_AN_INTEGER:
        dbg_printf("\nNeeding an integral value\n");
        break;
431 432
    case CONTROL_C_EXIT:
        /* this is generally sent by a ctrl-c when we run winedbg outside of wineconsole */
433
        /* stop the debuggee, and continue debugger execution, we will be reentered by the
434 435
         * debug events generated by stopping
         */
436
        dbg_interrupt_debuggee();
437 438
        return EXCEPTION_CONTINUE_EXECUTION;
    default:
439
        dbg_printf("\nException %x\n", eptr->ExceptionRecord->ExceptionCode);
440 441 442 443
        break;
    }

    return EXCEPTION_EXECUTE_HANDLER;
444
}
Alexandre Julliard's avatar
Alexandre Julliard committed
445

446 447 448
static HANDLE dbg_parser_input;
static HANDLE dbg_parser_output;

449
int      input_fetch_entire_line(const char* pfx, char** line)
450
{
451 452 453
    char        ch;
    DWORD	nread;
    size_t      len, alloc;
454
    
455 456 457
    /* as of today, console handles can be file handles... so better use file APIs rather than
     * console's
     */
458 459 460 461 462 463 464 465 466 467 468 469
    WriteFile(dbg_parser_output, pfx, strlen(pfx), &nread, NULL);

    if (*line)
    {
        alloc = HeapSize(GetProcessHeap(), 0, *line);
        assert(alloc);
    }
    else
    {
        *line = HeapAlloc(GetProcessHeap(), 0, alloc = 16);
        assert(*line);
    }
470 471 472 473

    len = 0;
    do
    {
474
        if (!ReadFile(dbg_parser_input, &ch, 1, &nread, NULL) || nread == 0)
475 476
            return -1;

477
        if (len + 2 > alloc)
478
        {
479 480
            while (len + 2 > alloc) alloc *= 2;
            *line = dbg_heap_realloc(*line, alloc);
481
        }
482
        (*line)[len++] = ch;
483
    }
484 485
    while (ch != '\n');
    (*line)[len] = '\0';
486

487
    return len;
488 489 490 491 492 493
}

int input_read_line(const char* pfx, char* buf, int size)
{
    char*       line = NULL;

494 495
    int len = input_fetch_entire_line(pfx, &line);
    if (len < 0) return 0;
496 497 498 499 500 501 502
    /* remove trailing \n */
    if (len > 0 && line[len - 1] == '\n') len--;
    len = min(size - 1, len);
    memcpy(buf, line, len);
    buf[len] = '\0';
    HeapFree(GetProcessHeap(), 0, line);
    return 1;
Eric Pouech's avatar
Eric Pouech committed
503 504
}

Alexandre Julliard's avatar
Alexandre Julliard committed
505
/***********************************************************************
506
 *           parser_handle
Alexandre Julliard's avatar
Alexandre Julliard committed
507
 *
508
 * Debugger command line parser
Alexandre Julliard's avatar
Alexandre Julliard committed
509
 */
510
void	parser_handle(HANDLE input)
Alexandre Julliard's avatar
Alexandre Julliard committed
511
{
512
    BOOL 	        ret_ok;
513 514 515
    HANDLE              in_copy  = dbg_parser_input;
    HANDLE              out_copy = dbg_parser_output;

516
    ret_ok = FALSE;
Eric Pouech's avatar
Eric Pouech committed
517

518
    if (input != INVALID_HANDLE_VALUE)
Eric Pouech's avatar
Eric Pouech committed
519
    {
520 521
        dbg_parser_output = INVALID_HANDLE_VALUE;
        dbg_parser_input  = input;
Eric Pouech's avatar
Eric Pouech committed
522 523
    }
    else
524 525 526 527
    {
        dbg_parser_output = GetStdHandle(STD_OUTPUT_HANDLE);
        dbg_parser_input  = GetStdHandle(STD_INPUT_HANDLE);
    }
Eric Pouech's avatar
Eric Pouech committed
528 529 530 531

    do
    {
       __TRY
532
       {
533
	  ret_ok = TRUE;
534
	  dbg_parse();
Eric Pouech's avatar
Eric Pouech committed
535 536 537
       }
       __EXCEPT(wine_dbg_cmd)
       {
538 539 540
	  ret_ok = FALSE;
       }
       __ENDTRY;
541
       lexeme_flush();
542
    } while (!ret_ok);
Eric Pouech's avatar
Eric Pouech committed
543

544 545
    dbg_parser_input  = in_copy;
    dbg_parser_output = out_copy;
Alexandre Julliard's avatar
Alexandre Julliard committed
546 547
}

548 549 550 551 552 553 554 555 556 557
void parser(const char* filename)
{
    HANDLE h = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0L, 0);
    if (h != INVALID_HANDLE_VALUE)
    {
        parser_handle(h);
        CloseHandle(h);
    }
}

558
int dbg_error(const char* s)
Alexandre Julliard's avatar
Alexandre Julliard committed
559
{
560 561
    dbg_printf("%s\n", s);
    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
562
}
563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591

HANDLE parser_generate_command_file(const char* pmt, ...)
{
    HANDLE      hFile;
    char        path[MAX_PATH], file[MAX_PATH];
    DWORD       w;
    const char* p;

    GetTempPath(sizeof(path), path);
    GetTempFileName(path, "WD", 0, file);
    hFile = CreateFileA(file, GENERIC_READ|GENERIC_WRITE|DELETE, FILE_SHARE_DELETE, 
                        NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, 0);
    if (hFile != INVALID_HANDLE_VALUE)
    {
        va_list ap;

        WriteFile(hFile, pmt, strlen(pmt), &w, 0);
        va_start(ap, pmt);
        while ((p = va_arg(ap, const char*)) != NULL)
        {
            WriteFile(hFile, "\n", 1, &w, 0);
            WriteFile(hFile, p, strlen(p), &w, 0);
        }
        va_end(ap);
        WriteFile(hFile, "\nquit\n", 6, &w, 0);
        SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
    }
    return hFile;
}