dbg.y 25.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*);
40
static void parser(const char*);
Alexandre Julliard's avatar
Alexandre Julliard committed
41

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

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

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

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

Alexandre Julliard's avatar
Alexandre Julliard committed
69 70 71 72 73 74 75 76 77 78 79 80
/* %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
81
%left OP_SHL OP_SHR
Alexandre Julliard's avatar
Alexandre Julliard committed
82 83 84
%left '+' '-'
%left '*' '/' '%'
%left OP_SIGN '!' '~' OP_DEREF /* OP_INC OP_DEC OP_ADDR */
85
%left '.' '[' OP_DRF OP_SCOPE
Alexandre Julliard's avatar
Alexandre Julliard committed
86 87
%nonassoc ':'

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

%%

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

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

command:
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
      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(); }
126 127 128 129 130 131 132
    | 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); }
133 134 135
    | tFRAME tNUM              	{ stack_set_frame($2); }
    | tSHOW tDIR     	       	{ source_show_path(); }
    | tDIR pathname            	{ source_add_path($2); }
136
    | tDIR     		       	{ source_nuke_path(dbg_curr_process); }
137 138 139 140 141
    | 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); }
142
    | tWHATIS expr_lvalue       { dbg_printf("type = "); types_print_type(&$2.type, FALSE); dbg_printf("\n"); }
143
    | tATTACH tNUM     		{ dbg_attach_debuggee($2, FALSE); dbg_active_wait_for_first_exception(); }
144
    | tDETACH                   { dbg_curr_process->process_io->close_process(dbg_curr_process, FALSE); }
145
    | tKILL                     { dbg_curr_process->process_io->close_process(dbg_curr_process, TRUE); }
146
    | tMINIDUMP pathname        { minidump_write($2, (dbg_curr_thread && dbg_curr_thread->in_exception) ? &dbg_curr_thread->excpt_record : NULL);}
147
    | tECHO tSTRING             { dbg_printf("%s\n", $2); }
148
    | run_command
Alexandre Julliard's avatar
Alexandre Julliard committed
149
    | list_command
Alexandre Julliard's avatar
Alexandre Julliard committed
150
    | disassemble_command
Alexandre Julliard's avatar
Alexandre Julliard committed
151 152
    | set_command
    | x_command
153 154
    | print_command     
    | break_command
155
    | watch_command
156
    | display_command
Alexandre Julliard's avatar
Alexandre Julliard committed
157
    | info_command
158
    | maintenance_command
159
    | noprocess_state
Alexandre Julliard's avatar
Alexandre Julliard committed
160
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
161

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

168
cpp_identifier:
169
      tIDENTIFIER               { $$ = $1; }
170 171
    | 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
172
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
173

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

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

190 191 192
run_command:
      tRUN                      { dbg_run_debuggee(NULL); }
    | tRUN tSTRING              { dbg_run_debuggee($2); }
Alexandre Julliard's avatar
Alexandre Julliard committed
193
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
194

Alexandre Julliard's avatar
Alexandre Julliard committed
195
list_command:
196 197 198 199 200
      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
201
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
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); }
212
    | tSET '+' tALL             { info_wine_dbg_channel(TRUE, NULL, "all"); }
213
    | tSET '-' tIDENTIFIER      { info_wine_dbg_channel(FALSE, NULL, $3); }
214
    | tSET '-' tALL             { info_wine_dbg_channel(FALSE, NULL, "all"); }
215
    | tSET tIDENTIFIER '+' tIDENTIFIER { info_wine_dbg_channel(TRUE, $2, $4); }
216
    | tSET tIDENTIFIER '+' tALL        { info_wine_dbg_channel(TRUE, $2, "all"); }
217
    | tSET tIDENTIFIER '-' tIDENTIFIER { info_wine_dbg_channel(FALSE, $2, $4); }
218
    | tSET tIDENTIFIER '-' tALL        { info_wine_dbg_channel(FALSE, $2, "all"); }
219 220
    | tSET '!' tIDENTIFIER tIDENTIFIER  { dbg_set_option($3, $4); }
    | tSET '!' tIDENTIFIER      { dbg_set_option($3, NULL); }
Alexandre Julliard's avatar
Alexandre Julliard committed
221
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
222 223

x_command:
224 225
      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
226
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
227 228

print_command:
229 230
      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
231
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
232

233
break_command:
234 235
      tBREAK '*' expr_lvalue    { break_add_break_from_lvalue(&$3, TRUE); }
    | tBREAK identifier         { break_add_break_from_id($2, -1, TRUE); }
236 237 238
    | tBREAK pathname ':' tNUM  { break_add_break_from_lineno($2, $4, TRUE); }
    | tBREAK tNUM               { break_add_break_from_lineno(NULL, $2, TRUE); }
    | tBREAK                    { break_add_break_from_lineno(NULL, -1, TRUE); }
239 240
    | tHBREAK '*' expr_lvalue   { break_add_break_from_lvalue(&$3, FALSE); }
    | tHBREAK identifier        { break_add_break_from_id($2, -1, FALSE); }
241 242 243
    | tHBREAK pathname ':' tNUM { break_add_break_from_lineno($2, $4, FALSE); }
    | tHBREAK tNUM              { break_add_break_from_lineno(NULL, $2, FALSE); }
    | tHBREAK                   { break_add_break_from_lineno(NULL, -1, FALSE); }
244 245 246 247 248 249
    | 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
250
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
251

252
watch_command:
253 254 255 256
      tWATCH '*' expr_lvalue    { break_add_watch_from_lvalue(&$3, TRUE); }
    | tWATCH identifier         { break_add_watch_from_id($2, TRUE); }
    | tRWATCH '*' expr_lvalue   { break_add_watch_from_lvalue(&$3, FALSE); }
    | tRWATCH identifier        { break_add_watch_from_id($2, FALSE); }
Alexandre Julliard's avatar
Alexandre Julliard committed
257
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
258

259

260
display_command:
261
      tDISPLAY     	       	{ display_print(); }
262 263
    | tDISPLAY expr            	{ display_add($2, 1, 0); }
    | tDISPLAY tFORMAT expr     { display_add($3, $2 >> 8, $2 & 0xff); }
264 265 266 267 268 269
    | 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
270
    ;
271

272 273 274 275
info_command:
      tINFO tBREAK              { break_info(); }
    | tINFO tSHARE     		{ info_win32_module(0); }
    | tINFO tSHARE expr_rvalue  { info_win32_module($3); }
276 277
    | 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); }
278
    | tINFO tSEGMENTS expr_rvalue { info_win32_segments($3 >> 3, 1); }
279
    | tINFO tSEGMENTS           { info_win32_segments(0, -1); }
280 281
    | tINFO tSTACK tNUM         { stack_info($3); }
    | tINFO tSTACK              { stack_info(-1); }
282 283 284 285 286 287 288 289 290 291 292
    | 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(); }
293 294
    | tINFO tFRAME              { info_win32_frame_exceptions(dbg_curr_tid); }
    | tINFO tFRAME expr_rvalue  { info_win32_frame_exceptions($3); }
295 296
    | tINFO tMAPS               { info_win32_virtual(dbg_curr_pid); }
    | tINFO tMAPS expr_rvalue   { info_win32_virtual($3); }
297
    | tINFO tEXCEPTION          { info_win32_exception(); }
Alexandre Julliard's avatar
Alexandre Julliard committed
298
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
299

300
maintenance_command:
301
      tMAINTENANCE tTYPE        { print_types(); }
302 303
    | tMAINTENANCE tMODULE tSTRING { tgt_module_load($3, FALSE); }
    | tMAINTENANCE '*' tMODULE tSTRING { tgt_module_load($4, TRUE); }
304 305
    ;

306
noprocess_state:
307
      tNOPROCESS                 {} /* <CR> shall not barf anything */
308
    | tNOPROCESS tBACKTRACE tALL { stack_backtrace(-1); } /* can backtrace all threads with no attached process */
309
    | tNOPROCESS tSTRING         { dbg_printf("No process loaded, cannot execute '%s'\n", $2); }
Alexandre Julliard's avatar
Alexandre Julliard committed
310
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
311 312

type_expr:
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
      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; }
334
    | type_expr '*'		{ $$ = $1; $$.deref_count++; }
335 336 337 338
    | 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
339
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
340

341 342
expr_lvalue:
      expr                      { $$ = expr_eval($1); }
Alexandre Julliard's avatar
Alexandre Julliard committed
343
    ;
Alexandre Julliard's avatar
Alexandre Julliard committed
344

345 346
expr_rvalue:
      expr_lvalue               { $$ = types_extract_as_integer(&$1); }
Alexandre Julliard's avatar
Alexandre Julliard committed
347
    ;
348

Alexandre Julliard's avatar
Alexandre Julliard committed
349 350 351 352 353 354
/*
 * 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
355
expr:
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
      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
389
    | '+' expr %prec OP_SIGN     { $$ = $2; }
390 391
    | '!' 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
392
    | '(' expr ')'               { $$ = $2; }
393 394 395
    | '*' 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
396 397
    ;

Alexandre Julliard's avatar
Alexandre Julliard committed
398 399 400 401
/*
 * The lvalue rule builds an expression tree.  This is a limited form
 * of expression that is suitable to be used as an lvalue.
 */
402 403
lvalue_addr: 
      lvalue                     { $$ = expr_eval($1); }
Alexandre Julliard's avatar
Alexandre Julliard committed
404 405
    ;

406 407
lvalue: 
      tNUM                       { $$ = expr_alloc_sconstant($1); }
408 409 410 411 412 413
    | 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
414
    ;
415

Alexandre Julliard's avatar
Alexandre Julliard committed
416 417
%%

418
static LONG WINAPI wine_dbg_cmd(EXCEPTION_POINTERS *eptr)
419
{
420
    switch (eptr->ExceptionRecord->ExceptionCode)
421
    {
422
    case DEBUG_STATUS_INTERNAL_ERROR:
423
        dbg_printf("\nWineDbg internal error\n");
424 425
        break;
    case DEBUG_STATUS_NO_SYMBOL:
426
        dbg_printf("\nUndefined symbol\n");
427 428
        break;
    case DEBUG_STATUS_DIV_BY_ZERO:
429
        dbg_printf("\nDivision by zero\n");
430 431
        break;
    case DEBUG_STATUS_BAD_TYPE:
432
        dbg_printf("\nNo type or type mismatch\n");
433 434
        break;
    case DEBUG_STATUS_NO_FIELD:
435 436 437 438
        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");
439 440 441
        break;
    case DEBUG_STATUS_ABORT:
        break;
442 443 444
    case DEBUG_STATUS_NOT_AN_INTEGER:
        dbg_printf("\nNeeding an integral value\n");
        break;
445 446
    case CONTROL_C_EXIT:
        /* this is generally sent by a ctrl-c when we run winedbg outside of wineconsole */
447
        /* stop the debuggee, and continue debugger execution, we will be reentered by the
448 449
         * debug events generated by stopping
         */
450
        dbg_interrupt_debuggee();
451 452
        return EXCEPTION_CONTINUE_EXECUTION;
    default:
453
        dbg_printf("\nException %x\n", eptr->ExceptionRecord->ExceptionCode);
454 455 456 457
        break;
    }

    return EXCEPTION_EXECUTE_HANDLER;
458
}
Alexandre Julliard's avatar
Alexandre Julliard committed
459

460 461 462
static HANDLE dbg_parser_input;
static HANDLE dbg_parser_output;

463
int      input_fetch_entire_line(const char* pfx, char** line)
464
{
465
    char*       buffer;
466 467 468
    char        ch;
    DWORD	nread;
    size_t      len, alloc;
469

470 471 472
    /* as of today, console handles can be file handles... so better use file APIs rather than
     * console's
     */
473 474
    WriteFile(dbg_parser_output, pfx, strlen(pfx), &nread, NULL);

475 476
    buffer = HeapAlloc(GetProcessHeap(), 0, alloc = 16);
    assert(buffer != NULL);
477 478 479 480

    len = 0;
    do
    {
481
        if (!ReadFile(dbg_parser_input, &ch, 1, &nread, NULL) || nread == 0)
482 483
        {
            HeapFree(GetProcessHeap(), 0, buffer);
484
            return -1;
485
        }
486

487
        if (len + 2 > alloc)
488
        {
489
            while (len + 2 > alloc) alloc *= 2;
490
            buffer = dbg_heap_realloc(buffer, alloc);
491
        }
492
        buffer[len++] = ch;
493
    }
494
    while (ch != '\n');
495
    buffer[len] = '\0';
496

497
    *line = buffer;
498
    return len;
499 500 501 502 503 504
}

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

505 506
    int len = input_fetch_entire_line(pfx, &line);
    if (len < 0) return 0;
507 508
    /* remove trailing \n and \r */
    while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) len--;
509 510 511 512 513
    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
514 515
}

Alexandre Julliard's avatar
Alexandre Julliard committed
516
/***********************************************************************
517
 *           parser_handle
Alexandre Julliard's avatar
Alexandre Julliard committed
518
 *
519
 * Debugger command line parser
Alexandre Julliard's avatar
Alexandre Julliard committed
520
 */
521
void	parser_handle(HANDLE input)
Alexandre Julliard's avatar
Alexandre Julliard committed
522
{
523
    BOOL 	        ret_ok;
524 525 526
    HANDLE              in_copy  = dbg_parser_input;
    HANDLE              out_copy = dbg_parser_output;

527
    ret_ok = FALSE;
Eric Pouech's avatar
Eric Pouech committed
528

529
    if (input != INVALID_HANDLE_VALUE)
Eric Pouech's avatar
Eric Pouech committed
530
    {
531 532
        dbg_parser_output = INVALID_HANDLE_VALUE;
        dbg_parser_input  = input;
Eric Pouech's avatar
Eric Pouech committed
533 534
    }
    else
535 536 537 538
    {
        dbg_parser_output = GetStdHandle(STD_OUTPUT_HANDLE);
        dbg_parser_input  = GetStdHandle(STD_INPUT_HANDLE);
    }
Eric Pouech's avatar
Eric Pouech committed
539 540 541 542

    do
    {
       __TRY
543
       {
544
	  ret_ok = TRUE;
545
	  dbg_parse();
Eric Pouech's avatar
Eric Pouech committed
546 547 548
       }
       __EXCEPT(wine_dbg_cmd)
       {
549 550 551
	  ret_ok = FALSE;
       }
       __ENDTRY;
552
       lexeme_flush();
553
    } while (!ret_ok);
Eric Pouech's avatar
Eric Pouech committed
554

555 556
    dbg_parser_input  = in_copy;
    dbg_parser_output = out_copy;
Alexandre Julliard's avatar
Alexandre Julliard committed
557 558
}

559
static void parser(const char* filename)
560
{
561
    HANDLE h = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0L, 0);
562 563 564 565 566 567 568
    if (h != INVALID_HANDLE_VALUE)
    {
        parser_handle(h);
        CloseHandle(h);
    }
}

569
static int dbg_error(const char* s)
Alexandre Julliard's avatar
Alexandre Julliard committed
570
{
571 572
    dbg_printf("%s\n", s);
    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
573
}
574 575 576 577 578 579 580 581

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

582 583
    GetTempPathA(sizeof(path), path);
    GetTempFileNameA(path, "WD", 0, file);
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
    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;
}