Added some missing prototypes.
[wine] / debugger / dbg.y
1 %{
2 /*
3  * Parser for command lines in the Wine debugger
4  *
5  * Copyright 1993 Eric Youngdale
6  * Copyright 1995 Morten Welinder
7  * Copyright 2000 Eric Pouech
8  */
9
10 #include "config.h"
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <signal.h>
16 #include <unistd.h>
17
18 #include "wine/exception.h"
19 #include "debugger.h"
20 #include "expr.h"
21 #include "task.h"
22
23 extern FILE * yyin;
24 int curr_frame = 0;
25
26 static void issue_prompt(void);
27 static void mode_command(int);
28 int yylex(void);
29 int yyerror(char *);
30
31 %}
32
33 %union
34 {
35     DBG_VALUE        value;
36     char *           string;
37     int              integer;
38     struct list_id   listing;
39     struct expr *    expression;
40     struct datatype * type;
41 }
42
43 %token tCONT tPASS tSTEP tLIST tNEXT tQUIT tHELP tBACKTRACE tINFO tWALK tUP tDOWN
44 %token tENABLE tDISABLE tBREAK tWATCH tDELETE tSET tMODE tPRINT tEXAM tABORT
45 %token tCLASS tMAPS tMODULE tSTACK tSEGMENTS tREGS tWND tQUEUE tLOCAL
46 %token tPROCESS tTHREAD tMODREF
47 %token tEOL tSTRING tDEBUGSTR
48 %token tFRAME tSHARE tCOND tDISPLAY tUNDISPLAY tDISASSEMBLE
49 %token tSTEPI tNEXTI tFINISH tSHOW tDIR tWHATIS
50 %token <string> tPATH
51 %token <string> tIDENTIFIER tSTRING tDEBUGSTR tINTVAR
52 %token <integer> tNUM tFORMAT
53 %token tSYMBOLFILE
54
55 %token tCHAR tSHORT tINT tLONG tFLOAT tDOUBLE tUNSIGNED tSIGNED 
56 %token tSTRUCT tUNION tENUM
57
58 /* %left ',' */
59 /* %left '=' OP_OR_EQUAL OP_XOR_EQUAL OP_AND_EQUAL OP_SHL_EQUAL \
60          OP_SHR_EQUAL OP_PLUS_EQUAL OP_MINUS_EQUAL \
61          OP_TIMES_EQUAL OP_DIVIDE_EQUAL OP_MODULO_EQUAL */
62 /* %left OP_COND */ /* ... ? ... : ... */
63 %left OP_LOR
64 %left OP_LAND
65 %left '|'
66 %left '^'
67 %left '&'
68 %left OP_EQ OP_NE
69 %left '<' '>' OP_LE OP_GE
70 %left OP_SHL OP_SHR
71 %left '+' '-'
72 %left '*' '/' '%'
73 %left OP_SIGN '!' '~' OP_DEREF /* OP_INC OP_DEC OP_ADDR */
74 %left '.' '[' OP_DRF
75 %nonassoc ':'
76
77 %type <expression> expr lval lvalue 
78 %type <type> type_cast type_expr
79 %type <value> expr_addr lval_addr
80 %type <integer> expr_value
81 %type <string> pathname
82
83 %type <listing> list_arg
84
85 %%
86
87 input: line                    { issue_prompt(); }
88     | input line               { issue_prompt(); }
89
90 line: command 
91     | tEOL
92     | error tEOL               { yyerrok; }
93
94 command:
95       tQUIT tEOL               { DEBUG_CurrThread->dbg_exec_count = 1; 
96                                  DEBUG_CurrThread->dbg_exec_mode = EXEC_KILL; return 1; }
97     | tHELP tEOL               { DEBUG_Help(); }
98     | tHELP tINFO tEOL         { DEBUG_HelpInfo(); }
99     | tCONT tEOL               { DEBUG_CurrThread->dbg_exec_count = 1; 
100                                  DEBUG_CurrThread->dbg_exec_mode = EXEC_CONT; return 0; }
101     | tPASS tEOL               { DEBUG_CurrThread->dbg_exec_count = 1; 
102                                  DEBUG_CurrThread->dbg_exec_mode = EXEC_PASS; return 0; }
103     | tCONT tNUM tEOL          { DEBUG_CurrThread->dbg_exec_count = $2; 
104                                  DEBUG_CurrThread->dbg_exec_mode = EXEC_CONT; return 0; }
105     | tSTEP tEOL               { DEBUG_CurrThread->dbg_exec_count = 1; 
106                                  DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_INSTR; return 0; }
107     | tNEXT tEOL               { DEBUG_CurrThread->dbg_exec_count = 1; 
108                                  DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_OVER; return 0; }
109     | tSTEP tNUM tEOL          { DEBUG_CurrThread->dbg_exec_count = $2; 
110                                  DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_INSTR; return 0; }
111     | tNEXT tNUM tEOL          { DEBUG_CurrThread->dbg_exec_count = $2; 
112                                  DEBUG_CurrThread->dbg_exec_mode = EXEC_STEP_OVER; return 0; }
113     | tSTEPI tEOL              { DEBUG_CurrThread->dbg_exec_count = 1; 
114                                  DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_INSTR; return 0; }
115     | tNEXTI tEOL              { DEBUG_CurrThread->dbg_exec_count = 1; 
116                                  DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_OVER; return 0; }
117     | tSTEPI tNUM tEOL         { DEBUG_CurrThread->dbg_exec_count = $2; 
118                                  DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_INSTR; return 0; }
119     | tNEXTI tNUM tEOL         { DEBUG_CurrThread->dbg_exec_count = $2; 
120                                  DEBUG_CurrThread->dbg_exec_mode = EXEC_STEPI_OVER; return 0; }
121     | tABORT tEOL              { kill(getpid(), SIGABRT); }
122     | tMODE tNUM tEOL          { mode_command($2); }
123     | tENABLE tNUM tEOL        { DEBUG_EnableBreakpoint( $2, TRUE ); }
124     | tDISABLE tNUM tEOL       { DEBUG_EnableBreakpoint( $2, FALSE ); }
125     | tDELETE tBREAK tNUM tEOL { DEBUG_DelBreakpoint( $3 ); }
126     | tBACKTRACE tEOL          { DEBUG_BackTrace(TRUE); }
127     | tUP tEOL                 { DEBUG_SetFrame( curr_frame + 1 );  }
128     | tUP tNUM tEOL            { DEBUG_SetFrame( curr_frame + $2 ); }
129     | tDOWN tEOL               { DEBUG_SetFrame( curr_frame - 1 );  }
130     | tDOWN tNUM tEOL          { DEBUG_SetFrame( curr_frame - $2 ); }
131     | tFRAME tNUM tEOL         { DEBUG_SetFrame( $2 ); }
132     | tFINISH tEOL             { DEBUG_CurrThread->dbg_exec_count = 0;
133                                  DEBUG_CurrThread->dbg_exec_mode = EXEC_FINISH; return 0; }
134     | tSHOW tDIR tEOL          { DEBUG_ShowDir(); }
135     | tDIR pathname tEOL       { DEBUG_AddPath( $2 ); }
136     | tDIR tEOL                { DEBUG_NukePath(); }
137     | tDISPLAY tEOL            { DEBUG_InfoDisplay(); }
138     | tDISPLAY expr tEOL       { DEBUG_AddDisplay($2, 1, 0); }
139     | tDISPLAY tFORMAT expr tEOL { DEBUG_AddDisplay($3, $2 >> 8, $2 & 0xff); }
140     | tDELETE tDISPLAY tNUM tEOL { DEBUG_DelDisplay( $3 ); }
141     | tDELETE tDISPLAY tEOL    { DEBUG_DelDisplay( -1 ); }
142     | tUNDISPLAY tNUM tEOL     { DEBUG_DelDisplay( $2 ); }
143     | tUNDISPLAY tEOL          { DEBUG_DelDisplay( -1 ); }
144     | tCOND tNUM tEOL          { DEBUG_AddBPCondition($2, NULL); }
145     | tCOND tNUM expr tEOL     { DEBUG_AddBPCondition($2, $3); }
146     | tSYMBOLFILE pathname tEOL{ DEBUG_ReadSymbolTable($2); }
147     | tWHATIS expr_addr tEOL   { DEBUG_PrintType(&$2); DEBUG_FreeExprMem(); }
148     | list_command
149     | disassemble_command
150     | set_command
151     | x_command
152     | print_command
153     | break_command
154     | watch_command
155     | info_command
156     | walk_command
157
158 set_command:
159       tSET lval_addr '=' expr_value tEOL   { DEBUG_WriteMemory( &$2, $4 );
160                                              DEBUG_FreeExprMem(); }
161
162 pathname:
163       tIDENTIFIER              { $$ = $1; }
164     | tPATH                    { $$ = $1; }
165
166 disassemble_command:
167       tDISASSEMBLE tEOL              { DEBUG_Disassemble( NULL, NULL, 10 ); }
168     | tDISASSEMBLE expr_addr tEOL    { DEBUG_Disassemble( & $2, NULL, 10 ); }
169     | tDISASSEMBLE expr_addr ',' expr_addr tEOL { DEBUG_Disassemble( & $2, & $4, 0 ); }
170
171 list_command:
172       tLIST tEOL               { DEBUG_List( NULL, NULL, 10 ); }
173     | tLIST '-' tEOL           { DEBUG_List( NULL, NULL, -10 ); }
174     | tLIST list_arg tEOL      { DEBUG_List( & $2, NULL, 10 ); }
175     | tLIST ',' list_arg tEOL  { DEBUG_List( NULL, & $3, -10 ); }
176     | tLIST list_arg ',' list_arg tEOL { DEBUG_List( & $2, & $4, 0 ); }
177
178 list_arg:
179       tNUM                     { $$.sourcefile = NULL; $$.line = $1; }
180     | pathname ':' tNUM        { $$.sourcefile = $1; $$.line = $3; }
181     | tIDENTIFIER              { DEBUG_GetFuncInfo( & $$, NULL, $1); }
182     | pathname ':' tIDENTIFIER { DEBUG_GetFuncInfo( & $$, $1, $3); }
183     | '*' expr_addr            { DEBUG_FindNearestSymbol( & $2.addr, FALSE, NULL, 
184                                                         0, & $$ ); 
185                                              DEBUG_FreeExprMem(); }
186
187 x_command:
188       tEXAM expr_addr tEOL     { DEBUG_ExamineMemory( &$2, 1, 'x'); 
189                                              DEBUG_FreeExprMem(); }
190     | tEXAM tFORMAT expr_addr tEOL  { DEBUG_ExamineMemory( &$3, $2>>8, $2&0xff ); 
191                                              DEBUG_FreeExprMem(); }
192
193 print_command:
194       tPRINT expr_addr tEOL    { DEBUG_Print( &$2, 1, 0, 0 ); 
195                                              DEBUG_FreeExprMem(); }
196     | tPRINT tFORMAT expr_addr tEOL { DEBUG_Print( &$3, $2 >> 8, $2 & 0xff, 0 ); 
197                                              DEBUG_FreeExprMem(); }
198
199 break_command:
200       tBREAK '*' expr_addr tEOL { DEBUG_AddBreakpoint( &$3, NULL ); 
201                                              DEBUG_FreeExprMem(); }
202     | tBREAK tIDENTIFIER tEOL  { DBG_VALUE value;
203                                  if( DEBUG_GetSymbolValue($2, -1, &value, TRUE) )
204                                    {
205                                      DEBUG_AddBreakpoint( &value, NULL );
206                                    }
207                                  else
208                                    {
209                                      DEBUG_Printf(DBG_CHN_MESG,"Unable to add breakpoint\n");
210                                    }
211                                 }
212     | tBREAK tIDENTIFIER ':' tNUM tEOL  { DBG_VALUE value;
213                                  if( DEBUG_GetSymbolValue($2, $4, &value, TRUE) )
214                                    {
215                                      DEBUG_AddBreakpoint( &value, NULL );
216                                    }
217                                  else
218                                    {
219                                      DEBUG_Printf(DBG_CHN_MESG,"Unable to add breakpoint\n");
220                                    }
221                                }
222     | tBREAK tNUM tEOL         { struct name_hash *nh;
223                                  DBG_VALUE value;
224                                  DEBUG_GetCurrentAddress( &value.addr );
225                                  DEBUG_FindNearestSymbol(&value.addr, TRUE,
226                                                          &nh, 0, NULL);
227                                  if( nh != NULL )
228                                    {
229                                      DEBUG_GetLineNumberAddr(nh, $2, &value.addr, TRUE);
230                                      value.type = NULL;
231                                      value.cookie = DV_TARGET;
232                                      DEBUG_AddBreakpoint( &value, NULL );
233                                    }
234                                  else
235                                    {
236                                      DEBUG_Printf(DBG_CHN_MESG,"Unable to add breakpoint\n");
237                                    }
238                                }
239
240     | tBREAK tEOL              { DBG_VALUE value;
241                                  DEBUG_GetCurrentAddress( &value.addr );
242                                  value.type = NULL;
243                                  value.cookie = DV_TARGET;
244                                  DEBUG_AddBreakpoint( &value, NULL );
245                                }
246
247 watch_command:
248       tWATCH '*' expr_addr tEOL { DEBUG_AddWatchpoint( &$3, 1 ); 
249                                              DEBUG_FreeExprMem(); }
250     | tWATCH tIDENTIFIER tEOL  { DBG_VALUE value;
251                                  if( DEBUG_GetSymbolValue($2, -1, &value, TRUE) )
252                                      DEBUG_AddWatchpoint( &value, 1 );
253                                  else
254                                      DEBUG_Printf(DBG_CHN_MESG,"Unable to add breakpoint\n");
255                                 }
256
257 info_command:
258       tINFO tBREAK tEOL         { DEBUG_InfoBreakpoints(); }
259     | tINFO tCLASS tSTRING tEOL { DEBUG_InfoClass( $3 ); DEBUG_FreeExprMem(); }
260     | tINFO tSHARE tEOL         { DEBUG_InfoShare(); }
261     | tINFO tMODULE expr_value tEOL   { DEBUG_DumpModule( $3 ); DEBUG_FreeExprMem(); }
262     | tINFO tQUEUE expr_value tEOL    { DEBUG_DumpQueue( $3 ); DEBUG_FreeExprMem(); }
263     | tINFO tREGS tEOL          { DEBUG_InfoRegisters(); }
264     | tINFO tSEGMENTS expr_value tEOL { DEBUG_InfoSegments( $3, 1 ); DEBUG_FreeExprMem(); }
265     | tINFO tSEGMENTS tEOL      { DEBUG_InfoSegments( 0, -1 ); }
266     | tINFO tSTACK tEOL         { DEBUG_InfoStack(); }
267     | tINFO tMAPS tEOL          { DEBUG_InfoVirtual(); }
268     | tINFO tWND expr_value tEOL      { DEBUG_InfoWindow( (HWND)$3 ); 
269                                              DEBUG_FreeExprMem(); }
270     | tINFO tLOCAL tEOL         { DEBUG_InfoLocals(); }
271     | tINFO tDISPLAY tEOL       { DEBUG_InfoDisplay(); }
272
273 walk_command:
274       tWALK tCLASS tEOL         { DEBUG_WalkClasses(); }
275     | tWALK tMODULE tEOL        { DEBUG_WalkModules(); }
276     | tWALK tQUEUE tEOL         { DEBUG_WalkQueues(); }
277     | tWALK tWND tEOL           { DEBUG_WalkWindows( 0, 0 ); }
278     | tWALK tWND tNUM tEOL      { DEBUG_WalkWindows( $3, 0 ); }
279     | tWALK tPROCESS tEOL       { DEBUG_WalkProcess(); }
280     | tWALK tTHREAD tEOL        { DEBUG_WalkThreads(); }
281     | tWALK tMODREF expr_value tEOL   { DEBUG_WalkModref( $3 ); }
282
283
284 type_cast: 
285       '(' type_expr ')'         { $$ = $2; }
286
287 type_expr:
288       type_expr '*'             { $$ = DEBUG_FindOrMakePointerType($1); }
289     |  tINT                     { $$ = DEBUG_TypeCast(DT_BASIC, "int"); }
290     | tCHAR                     { $$ = DEBUG_TypeCast(DT_BASIC, "char"); }
291     | tLONG tINT                { $$ = DEBUG_TypeCast(DT_BASIC, "long int"); }
292     | tUNSIGNED tINT            { $$ = DEBUG_TypeCast(DT_BASIC, "unsigned int"); }
293     | tLONG tUNSIGNED tINT      { $$ = DEBUG_TypeCast(DT_BASIC, "long unsigned int"); }
294     | tLONG tLONG tINT          { $$ = DEBUG_TypeCast(DT_BASIC, "long long int"); }
295     | tLONG tLONG tUNSIGNED tINT { $$ = DEBUG_TypeCast(DT_BASIC, "long long unsigned int"); }
296     | tSHORT tINT               { $$ = DEBUG_TypeCast(DT_BASIC, "short int"); }
297     | tSHORT tUNSIGNED tINT     { $$ = DEBUG_TypeCast(DT_BASIC, "short unsigned int"); }
298     | tSIGNED tCHAR             { $$ = DEBUG_TypeCast(DT_BASIC, "signed char"); }
299     | tUNSIGNED tCHAR           { $$ = DEBUG_TypeCast(DT_BASIC, "unsigned char"); }
300     | tFLOAT                    { $$ = DEBUG_TypeCast(DT_BASIC, "float"); }
301     | tDOUBLE                   { $$ = DEBUG_TypeCast(DT_BASIC, "double"); }
302     | tLONG tDOUBLE             { $$ = DEBUG_TypeCast(DT_BASIC, "long double"); }
303     | tSTRUCT tIDENTIFIER       { $$ = DEBUG_TypeCast(DT_STRUCT, $2); }
304     | tUNION tIDENTIFIER        { $$ = DEBUG_TypeCast(DT_STRUCT, $2); }
305     | tENUM tIDENTIFIER         { $$ = DEBUG_TypeCast(DT_ENUM, $2); }
306
307 expr_addr:
308       expr                      { $$ = DEBUG_EvalExpr($1); }
309
310 expr_value:
311       expr                      { DBG_VALUE     value = DEBUG_EvalExpr($1); 
312                                   /* expr_value is typed as an integer */
313                                   $$ = DEBUG_ReadMemory(&value); }
314
315 /*
316  * The expr rule builds an expression tree.  When we are done, we call
317  * EvalExpr to evaluate the value of the expression.  The advantage of
318  * the two-step approach is that it is possible to save expressions for
319  * use in 'display' commands, and in conditional watchpoints.
320  */
321 expr:
322       tNUM                       { $$ = DEBUG_ConstExpr($1); }
323     | tSTRING                    { $$ = DEBUG_StringExpr($1); }
324     | tINTVAR                    { $$ = DEBUG_IntVarExpr($1); }
325     | tIDENTIFIER                { $$ = DEBUG_SymbolExpr($1); }
326     | expr OP_DRF tIDENTIFIER    { $$ = DEBUG_StructPExpr($1, $3); } 
327     | expr '.' tIDENTIFIER       { $$ = DEBUG_StructExpr($1, $3); } 
328     | tIDENTIFIER '(' ')'        { $$ = DEBUG_CallExpr($1, 0); } 
329     | tIDENTIFIER '(' expr ')'   { $$ = DEBUG_CallExpr($1, 1, $3); } 
330     | tIDENTIFIER '(' expr ',' expr ')'  { $$ = DEBUG_CallExpr($1, 2, $3, $5); } 
331     | tIDENTIFIER '(' expr ',' expr ',' expr ')'         { $$ = DEBUG_CallExpr($1, 3, $3, $5, $7); } 
332     | tIDENTIFIER '(' expr ',' expr ',' expr ',' expr ')'        { $$ = DEBUG_CallExpr($1, 4, $3, $5, $7, $9); } 
333     | tIDENTIFIER '(' expr ',' expr ',' expr ',' expr ',' expr ')'       { $$ = DEBUG_CallExpr($1, 5, $3, $5, $7, $9, $11); } 
334     | expr '[' expr ']'          { $$ = DEBUG_BinopExpr(EXP_OP_ARR, $1, $3); } 
335     | expr ':' expr              { $$ = DEBUG_BinopExpr(EXP_OP_SEG, $1, $3); } 
336     | expr OP_LOR expr           { $$ = DEBUG_BinopExpr(EXP_OP_LOR, $1, $3); }
337     | expr OP_LAND expr          { $$ = DEBUG_BinopExpr(EXP_OP_LAND, $1, $3); }
338     | expr '|' expr              { $$ = DEBUG_BinopExpr(EXP_OP_OR, $1, $3); }
339     | expr '&' expr              { $$ = DEBUG_BinopExpr(EXP_OP_AND, $1, $3); }
340     | expr '^' expr              { $$ = DEBUG_BinopExpr(EXP_OP_XOR, $1, $3); }
341     | expr OP_EQ expr            { $$ = DEBUG_BinopExpr(EXP_OP_EQ, $1, $3); }
342     | expr '>' expr              { $$ = DEBUG_BinopExpr(EXP_OP_GT, $1, $3); }
343     | expr '<' expr              { $$ = DEBUG_BinopExpr(EXP_OP_LT, $1, $3); }
344     | expr OP_GE expr            { $$ = DEBUG_BinopExpr(EXP_OP_GE, $1, $3); }
345     | expr OP_LE expr            { $$ = DEBUG_BinopExpr(EXP_OP_LE, $1, $3); }
346     | expr OP_NE expr            { $$ = DEBUG_BinopExpr(EXP_OP_NE, $1, $3); }
347     | expr OP_SHL expr           { $$ = DEBUG_BinopExpr(EXP_OP_SHL, $1, $3); }
348     | expr OP_SHR expr           { $$ = DEBUG_BinopExpr(EXP_OP_SHR, $1, $3); }
349     | expr '+' expr              { $$ = DEBUG_BinopExpr(EXP_OP_ADD, $1, $3); }
350     | expr '-' expr              { $$ = DEBUG_BinopExpr(EXP_OP_SUB, $1, $3); }
351     | expr '*' expr              { $$ = DEBUG_BinopExpr(EXP_OP_MUL, $1, $3); }
352     | expr '/' expr              { $$ = DEBUG_BinopExpr(EXP_OP_DIV, $1, $3); }
353     | expr '%' expr              { $$ = DEBUG_BinopExpr(EXP_OP_REM, $1, $3); }
354     | '-' expr %prec OP_SIGN     { $$ = DEBUG_UnopExpr(EXP_OP_NEG, $2); }
355     | '+' expr %prec OP_SIGN     { $$ = $2; }
356     | '!' expr                   { $$ = DEBUG_UnopExpr(EXP_OP_NOT, $2); }
357     | '~' expr                   { $$ = DEBUG_UnopExpr(EXP_OP_LNOT, $2); }
358     | '(' expr ')'               { $$ = $2; }
359     | '*' expr %prec OP_DEREF    { $$ = DEBUG_UnopExpr(EXP_OP_DEREF, $2); }
360     | '&' expr %prec OP_DEREF    { $$ = DEBUG_UnopExpr(EXP_OP_ADDR, $2); }
361     | type_cast expr %prec OP_DEREF { $$ = DEBUG_TypeCastExpr($1, $2); } 
362         
363 /*
364  * The lvalue rule builds an expression tree.  This is a limited form
365  * of expression that is suitable to be used as an lvalue.
366  */
367 lval_addr:
368     lval                         { $$ = DEBUG_EvalExpr($1); }
369
370 lval:
371       lvalue                     { $$ = $1; }
372     | '*' expr                   { $$ = DEBUG_UnopExpr(EXP_OP_FORCE_DEREF, $2); }
373         
374 lvalue:
375       tNUM                       { $$ = DEBUG_ConstExpr($1); }
376     | tINTVAR                    { $$ = DEBUG_IntVarExpr($1); }
377     | tIDENTIFIER                { $$ = DEBUG_SymbolExpr($1); }
378     | lvalue OP_DRF tIDENTIFIER  { $$ = DEBUG_StructPExpr($1, $3); } 
379     | lvalue '.' tIDENTIFIER     { $$ = DEBUG_StructExpr($1, $3); } 
380     | lvalue '[' expr ']'        { $$ = DEBUG_BinopExpr(EXP_OP_ARR, $1, $3); } 
381         
382 %%
383
384 static void issue_prompt(void)
385 {
386 #ifdef DONT_USE_READLINE
387    DEBUG_Printf(DBG_CHN_MESG, "Wine-dbg>");
388 #endif
389 }
390
391 static void mode_command(int newmode)
392 {
393     if ((newmode == 16) || (newmode == 32)) DEBUG_CurrThread->dbg_mode = newmode;
394     else DEBUG_Printf(DBG_CHN_MESG,"Invalid mode (use 16 or 32)\n");
395 }
396
397 void DEBUG_Exit(DWORD ec)
398 {
399    ExitProcess(ec);
400 }
401
402 static WINE_EXCEPTION_FILTER(wine_dbg_cmd)
403 {
404    DEBUG_Printf(DBG_CHN_MESG, "\nwine_dbg_cmd: ");
405    switch (GetExceptionCode()) {
406    case DEBUG_STATUS_INTERNAL_ERROR:
407       DEBUG_Printf(DBG_CHN_MESG, "WineDbg internal error\n");
408       break;
409    case DEBUG_STATUS_NO_SYMBOL:
410       DEBUG_Printf(DBG_CHN_MESG, "Undefined symbol\n");
411       break;
412    case DEBUG_STATUS_DIV_BY_ZERO:
413       DEBUG_Printf(DBG_CHN_MESG, "Division by zero\n");
414       break;
415    case DEBUG_STATUS_BAD_TYPE:
416       DEBUG_Printf(DBG_CHN_MESG, "No type or type mismatch\n");
417       break;
418    default:
419       DEBUG_Printf(DBG_CHN_MESG, "Exception %lx\n", GetExceptionCode());
420       break;
421    }
422
423    return EXCEPTION_EXECUTE_HANDLER;
424 }
425
426 /***********************************************************************
427  *           DEBUG_Main
428  *
429  * Debugger main loop.
430  */
431 BOOL DEBUG_Main( BOOL is_debug, BOOL force, DWORD code )
432 {
433     int newmode;
434     BOOL ret_ok;
435     char ch;
436
437 #ifdef YYDEBUG
438     yydebug = 0;
439 #endif
440
441     yyin = stdin;
442
443     DEBUG_SuspendExecution();
444
445     if (!is_debug)
446     {
447 #ifdef __i386__
448         if (DEBUG_IsSelectorSystem(DEBUG_context.SegCs))
449             DEBUG_Printf( DBG_CHN_MESG, " in 32-bit code (0x%08lx).\n", DEBUG_context.Eip );
450         else
451             DEBUG_Printf( DBG_CHN_MESG, " in 16-bit code (%04x:%04lx).\n",
452                           (WORD)DEBUG_context.SegCs, DEBUG_context.Eip );
453 #else
454         DEBUG_Printf( DBG_CHN_MESG, " (0x%08lx).\n", GET_IP(&DEBUG_context) );
455 #endif
456     }
457
458     DEBUG_LoadEntryPoints("Loading new modules symbols:\n");
459
460     if (force || !(is_debug && DEBUG_ShouldContinue( code, 
461                                                      DEBUG_CurrThread->dbg_exec_mode, 
462                                                      &DEBUG_CurrThread->dbg_exec_count )))
463     {
464         DBG_ADDR addr;
465         DEBUG_GetCurrentAddress( &addr );
466
467 #ifdef __i386__
468         switch (newmode = DEBUG_GetSelectorType(addr.seg)) {
469         case 16: case 32: break;
470         default: DEBUG_Printf(DBG_CHN_MESG, "Bad CS (%ld)\n", addr.seg); newmode = 32;
471         }
472 #else
473         newmode = 32;
474 #endif
475         if (newmode != DEBUG_CurrThread->dbg_mode)
476             DEBUG_Printf(DBG_CHN_MESG,"In %d bit mode.\n", DEBUG_CurrThread->dbg_mode = newmode);
477
478         DEBUG_DoDisplay();
479
480         if (is_debug || force)
481         {
482           /*
483            * Do a quiet backtrace so that we have an idea of what the situation
484            * is WRT the source files.
485            */
486             DEBUG_BackTrace(FALSE);
487         }
488         else
489         {
490             /* This is a real crash, dump some info */
491             DEBUG_InfoRegisters();
492             DEBUG_InfoStack();
493 #ifdef __i386__
494             if (DEBUG_CurrThread->dbg_mode == 16)
495             {
496                 DEBUG_InfoSegments( DEBUG_context.SegDs >> 3, 1 );
497                 if (DEBUG_context.SegEs != DEBUG_context.SegDs)
498                     DEBUG_InfoSegments( DEBUG_context.SegEs >> 3, 1 );
499             }
500             DEBUG_InfoSegments( DEBUG_context.SegFs >> 3, 1 );
501 #endif
502             DEBUG_BackTrace(TRUE);
503         }
504
505         if (!is_debug ||
506             (DEBUG_CurrThread->dbg_exec_mode == EXEC_STEPI_OVER) ||
507             (DEBUG_CurrThread->dbg_exec_mode == EXEC_STEPI_INSTR))
508         {
509             /* Show where we crashed */
510             curr_frame = 0;
511             DEBUG_PrintAddress( &addr, DEBUG_CurrThread->dbg_mode, TRUE );
512             DEBUG_Printf(DBG_CHN_MESG,":  ");
513             DEBUG_Disasm( &addr, TRUE );
514             DEBUG_Printf( DBG_CHN_MESG, "\n" );
515         }
516
517         ret_ok = 0;
518         do
519         {
520             __TRY 
521             {
522                issue_prompt();
523                if (yyparse()) {
524                   DEBUG_CurrThread->dbg_exec_mode = EXEC_KILL;
525                   ret_ok = TRUE;
526                } else {
527                   flush_symbols();
528
529                   DEBUG_GetCurrentAddress( &addr );
530                   ret_ok = DEBUG_ValidateRegisters() && 
531                      DEBUG_READ_MEM_VERBOSE((void*)DEBUG_ToLinear(&addr), &ch, 1);
532                }
533             } 
534             __EXCEPT(wine_dbg_cmd)
535             {
536                ret_ok = FALSE;
537             }
538             __ENDTRY;
539
540         } while (!ret_ok);
541     }
542
543     DEBUG_CurrThread->dbg_exec_mode = DEBUG_RestartExecution( DEBUG_CurrThread->dbg_exec_mode, DEBUG_CurrThread->dbg_exec_count );
544     /*
545      * This will have gotten absorbed into the breakpoint info
546      * if it was used.  Otherwise it would have been ignored.
547      * In any case, we don't mess with it any more.
548      */
549     if (DEBUG_CurrThread->dbg_exec_mode == EXEC_CONT || DEBUG_CurrThread->dbg_exec_mode == EXEC_PASS)
550         DEBUG_CurrThread->dbg_exec_count = 0;
551     
552     return (DEBUG_CurrThread->dbg_exec_mode == EXEC_PASS) ? DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE;
553 }
554
555 int yyerror(char* s)
556 {
557    DEBUG_Printf(DBG_CHN_MESG,"%s\n", s);
558    return 0;
559 }