cmd.exe: Fix redirect ordering on a command line.
[wine] / programs / winedbg / display.c
1 /*
2  * File display.c - display handling for Wine internal debugger.
3  *
4  * Copyright (C) 1997, Eric Youngdale.
5  * Copyright (C) 2003, Michal Miroslaw
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "debugger.h"
26
27 /* needs to be power of 2, search for MARK to see why :) */
28 #define DISPTAB_DELTA 8
29
30 struct display
31 {
32     struct expr*        exp;
33     int                 count;
34     char                format;
35     char                enabled;
36     char                func_buffer[sizeof(SYMBOL_INFO) + 256];
37     SYMBOL_INFO*        func;
38 };
39
40 static struct display *displaypoints = NULL;
41 static unsigned int maxdisplays = 0, ndisplays = 0;
42
43 #define OFFSET_OF(_f,_s)        ((unsigned)(&(((_s*)NULL)->_f)))
44
45 static inline BOOL cmp_symbol(const SYMBOL_INFO* si1, const SYMBOL_INFO* si2)
46 {
47     /* FIXME: !memcmp(si1, si2, sizeof(SYMBOL_INFO) + si1->NameLen)
48      * is wrong because sizeof(SYMBOL_INFO) can be aligned on 4-byte boundary
49      * Note: we also need to zero out the structures before calling 
50      * stack_get_frame, so that un-touched fields by stack_get_frame
51      * get the same value!!
52      */
53     return !memcmp(si1, si2, OFFSET_OF(Name, SYMBOL_INFO)) &&
54         !memcmp(si1->Name, si2->Name, si1->NameLen);
55 }
56
57 int display_add(struct expr *exp, int count, char format)
58 {
59     int         i;
60     BOOL local_binding = FALSE;
61
62     for (i = 0; i < ndisplays; i++)
63         if (displaypoints[i].exp == NULL)
64             break;
65
66     if (i == maxdisplays)
67     {
68         /* no space left - expand */
69         maxdisplays += DISPTAB_DELTA;
70         displaypoints = dbg_heap_realloc(displaypoints,
71                                          maxdisplays * sizeof(*displaypoints));
72     }
73
74     if (i == ndisplays) ndisplays++;
75
76     displaypoints[i].exp           = expr_clone(exp, &local_binding);
77     displaypoints[i].count         = count;
78     displaypoints[i].format        = format;
79     displaypoints[i].enabled       = TRUE;
80     if (local_binding)
81     {
82         displaypoints[i].func = (SYMBOL_INFO*)displaypoints[i].func_buffer;
83         memset(displaypoints[i].func, 0, sizeof(SYMBOL_INFO));
84         displaypoints[i].func->SizeOfStruct = sizeof(SYMBOL_INFO);
85         displaypoints[i].func->MaxNameLen = sizeof(displaypoints[i].func_buffer) -
86             sizeof(*displaypoints[i].func);
87         if (!stack_get_current_symbol(displaypoints[i].func))
88         {
89             expr_free(displaypoints[i].exp);
90             displaypoints[i].exp = NULL;
91             return FALSE;
92         }
93     }
94     else displaypoints[i].func = NULL;
95
96     return TRUE;
97 }
98
99 int display_info(void)
100 {
101     int                 i;
102     char                buffer[sizeof(SYMBOL_INFO) + 256];
103     SYMBOL_INFO*        func;
104     const char*         info;
105
106     func = (SYMBOL_INFO*)buffer;
107     memset(func, 0, sizeof(SYMBOL_INFO));
108     func->SizeOfStruct = sizeof(SYMBOL_INFO);
109     func->MaxNameLen = sizeof(buffer) - sizeof(*func);
110     if (!stack_get_current_symbol(func)) return FALSE;
111
112     for (i = 0; i < ndisplays; i++)
113     {
114         if (displaypoints[i].exp == NULL) continue;
115
116         dbg_printf("%d: ", i + 1);
117         expr_print(displaypoints[i].exp);
118
119         if (displaypoints[i].enabled)
120         {
121             if (displaypoints[i].func && !cmp_symbol(displaypoints[i].func, func))
122                 info = " (out of scope)";
123             else
124                 info = "";
125         }
126         else
127             info = " (disabled)";
128         if (displaypoints[i].func)
129             dbg_printf(" in %s", displaypoints[i].func->Name);
130         dbg_printf("%s\n", info);
131     }
132     return TRUE;
133 }
134
135 static void print_one_display(int i)
136 {
137     struct dbg_lvalue   lvalue;
138
139     if (displaypoints[i].enabled) 
140     {
141         lvalue = expr_eval(displaypoints[i].exp);
142         if (lvalue.type.id == dbg_itype_none)
143         {
144             dbg_printf("Unable to evaluate expression ");
145             expr_print(displaypoints[i].exp);
146             dbg_printf("\nDisabling display %d ...\n", i + 1);
147             displaypoints[i].enabled = FALSE;
148             return;
149         }
150     }
151
152     dbg_printf("%d: ", i + 1);
153     expr_print(displaypoints[i].exp);
154     dbg_printf(" = ");
155     if (!displaypoints[i].enabled)
156         dbg_printf("(disabled)\n");
157     else
158         if (displaypoints[i].format == 'i')
159             memory_examine(&lvalue, displaypoints[i].count, displaypoints[i].format);
160         else
161             print_value(&lvalue, displaypoints[i].format, 0);
162 }
163
164 int display_print(void)
165 {
166     int                 i;
167     char                buffer[sizeof(SYMBOL_INFO) + 256];
168     SYMBOL_INFO*        func;
169
170     func = (SYMBOL_INFO*)buffer;
171     memset(func, 0, sizeof(SYMBOL_INFO));
172     func->SizeOfStruct = sizeof(SYMBOL_INFO);
173     func->MaxNameLen = sizeof(buffer) - sizeof(*func);
174     if (!stack_get_current_symbol(func)) return FALSE;
175
176     for (i = 0; i < ndisplays; i++)
177     {
178         if (displaypoints[i].exp == NULL || !displaypoints[i].enabled)
179             continue;
180         if (displaypoints[i].func && !cmp_symbol(displaypoints[i].func, func))
181             continue;
182         print_one_display(i);
183     }
184
185     return TRUE;
186 }
187
188 int display_delete(int displaynum)
189 {
190     int i;
191
192     if (displaynum > ndisplays || displaynum == 0 || displaynum < -1 ||
193         displaypoints[displaynum - 1].exp == NULL)
194     {
195         dbg_printf("Invalid display number\n");
196         return TRUE;
197     }
198
199     if (displaynum == -1)
200     {
201         for (i = 0; i < ndisplays; i++)
202         {
203             if (displaypoints[i].exp != NULL) 
204             {
205                 expr_free(displaypoints[i].exp);
206                 displaypoints[i].exp = NULL;
207             }
208         }
209         maxdisplays = DISPTAB_DELTA;
210         displaypoints = dbg_heap_realloc(displaypoints,
211                                          (maxdisplays = DISPTAB_DELTA) * sizeof(*displaypoints));
212         ndisplays = 0;
213     }
214     else if (displaypoints[--displaynum].exp != NULL) 
215     {
216         expr_free(displaypoints[displaynum].exp);
217         displaypoints[displaynum].exp = NULL;
218         while (displaynum == ndisplays - 1 && displaypoints[displaynum].exp == NULL)
219         {
220             --ndisplays;
221             --displaynum;
222         }
223         if (maxdisplays - ndisplays >= 2 * DISPTAB_DELTA)
224         {
225             /* MARK */
226             maxdisplays = (ndisplays + DISPTAB_DELTA - 1) & ~(DISPTAB_DELTA - 1);
227             displaypoints = dbg_heap_realloc(displaypoints,
228                                              maxdisplays * sizeof(*displaypoints));
229         }
230     }
231     return TRUE;
232 }
233
234 int display_enable(int displaynum, int enable)
235 {
236     char                buffer[sizeof(SYMBOL_INFO) + 256];
237     SYMBOL_INFO*        func;
238
239     func = (SYMBOL_INFO*)buffer;
240     memset(func, 0, sizeof(SYMBOL_INFO));
241     func->SizeOfStruct = sizeof(SYMBOL_INFO);
242     func->MaxNameLen = sizeof(buffer) - sizeof(*func);
243     if (!stack_get_current_symbol(func)) return FALSE;
244
245     --displaynum;
246     if (displaynum >= ndisplays || displaynum < 0 || 
247         displaypoints[displaynum].exp == NULL) 
248     {
249         dbg_printf("Invalid display number\n");
250         return TRUE;
251     }
252
253     displaypoints[displaynum].enabled = enable;
254     if (!displaypoints[displaynum].func || 
255         cmp_symbol(displaypoints[displaynum].func, func))
256     {
257         print_one_display(displaynum);
258     }
259
260     return TRUE;
261 }