dxdiag: Add code for plain-text information output.
[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 static inline BOOL cmp_symbol(const SYMBOL_INFO* si1, const SYMBOL_INFO* si2)
44 {
45     /* FIXME: !memcmp(si1, si2, sizeof(SYMBOL_INFO) + si1->NameLen)
46      * is wrong because sizeof(SYMBOL_INFO) can be aligned on 4-byte boundary
47      * Note: we also need to zero out the structures before calling 
48      * stack_get_frame, so that un-touched fields by stack_get_frame
49      * get the same value!!
50      */
51     return !memcmp(si1, si2, FIELD_OFFSET(SYMBOL_INFO, Name)) &&
52         !memcmp(si1->Name, si2->Name, si1->NameLen);
53 }
54
55 int display_add(struct expr *exp, int count, char format)
56 {
57     unsigned i;
58     BOOL local_binding = FALSE;
59
60     for (i = 0; i < ndisplays; i++)
61         if (displaypoints[i].exp == NULL)
62             break;
63
64     if (i == maxdisplays)
65     {
66         /* no space left - expand */
67         maxdisplays += DISPTAB_DELTA;
68         displaypoints = dbg_heap_realloc(displaypoints,
69                                          maxdisplays * sizeof(*displaypoints));
70     }
71
72     if (i == ndisplays) ndisplays++;
73
74     displaypoints[i].exp           = expr_clone(exp, &local_binding);
75     displaypoints[i].count         = count;
76     displaypoints[i].format        = format;
77     displaypoints[i].enabled       = TRUE;
78     if (local_binding)
79     {
80         displaypoints[i].func = (SYMBOL_INFO*)displaypoints[i].func_buffer;
81         memset(displaypoints[i].func, 0, sizeof(SYMBOL_INFO));
82         displaypoints[i].func->SizeOfStruct = sizeof(SYMBOL_INFO);
83         displaypoints[i].func->MaxNameLen = sizeof(displaypoints[i].func_buffer) -
84             sizeof(*displaypoints[i].func);
85         if (!stack_get_current_symbol(displaypoints[i].func))
86         {
87             expr_free(displaypoints[i].exp);
88             displaypoints[i].exp = NULL;
89             return FALSE;
90         }
91     }
92     else displaypoints[i].func = NULL;
93
94     return TRUE;
95 }
96
97 int display_info(void)
98 {
99     unsigned            i;
100     char                buffer[sizeof(SYMBOL_INFO) + 256];
101     SYMBOL_INFO*        func;
102     const char*         info;
103
104     func = (SYMBOL_INFO*)buffer;
105     memset(func, 0, sizeof(SYMBOL_INFO));
106     func->SizeOfStruct = sizeof(SYMBOL_INFO);
107     func->MaxNameLen = sizeof(buffer) - sizeof(*func);
108     if (!stack_get_current_symbol(func)) return FALSE;
109
110     for (i = 0; i < ndisplays; i++)
111     {
112         if (displaypoints[i].exp == NULL) continue;
113
114         dbg_printf("%d: ", i + 1);
115         expr_print(displaypoints[i].exp);
116
117         if (displaypoints[i].enabled)
118         {
119             if (displaypoints[i].func && !cmp_symbol(displaypoints[i].func, func))
120                 info = " (out of scope)";
121             else
122                 info = "";
123         }
124         else
125             info = " (disabled)";
126         if (displaypoints[i].func)
127             dbg_printf(" in %s", displaypoints[i].func->Name);
128         dbg_printf("%s\n", info);
129     }
130     return TRUE;
131 }
132
133 static void print_one_display(int i)
134 {
135     struct dbg_lvalue   lvalue;
136
137     if (displaypoints[i].enabled) 
138     {
139         lvalue = expr_eval(displaypoints[i].exp);
140         if (lvalue.type.id == dbg_itype_none)
141         {
142             dbg_printf("Unable to evaluate expression ");
143             expr_print(displaypoints[i].exp);
144             dbg_printf("\nDisabling display %d ...\n", i + 1);
145             displaypoints[i].enabled = FALSE;
146             return;
147         }
148     }
149
150     dbg_printf("%d: ", i + 1);
151     expr_print(displaypoints[i].exp);
152     dbg_printf(" = ");
153     if (!displaypoints[i].enabled)
154         dbg_printf("(disabled)\n");
155     else
156         if (displaypoints[i].format == 'i')
157             memory_examine(&lvalue, displaypoints[i].count, displaypoints[i].format);
158         else
159             print_value(&lvalue, displaypoints[i].format, 0);
160 }
161
162 int display_print(void)
163 {
164     unsigned            i;
165     char                buffer[sizeof(SYMBOL_INFO) + 256];
166     SYMBOL_INFO*        func;
167
168     func = (SYMBOL_INFO*)buffer;
169     memset(func, 0, sizeof(SYMBOL_INFO));
170     func->SizeOfStruct = sizeof(SYMBOL_INFO);
171     func->MaxNameLen = sizeof(buffer) - sizeof(*func);
172     if (!stack_get_current_symbol(func)) return FALSE;
173
174     for (i = 0; i < ndisplays; i++)
175     {
176         if (displaypoints[i].exp == NULL || !displaypoints[i].enabled)
177             continue;
178         if (displaypoints[i].func && !cmp_symbol(displaypoints[i].func, func))
179             continue;
180         print_one_display(i);
181     }
182
183     return TRUE;
184 }
185
186 int display_delete(int displaynum)
187 {
188     if (displaynum > ndisplays || displaynum == 0 || displaynum < -1 ||
189         displaypoints[displaynum - 1].exp == NULL)
190     {
191         dbg_printf("Invalid display number\n");
192         return TRUE;
193     }
194
195     if (displaynum == -1)
196     {
197         unsigned i;
198
199         for (i = 0; i < ndisplays; i++)
200         {
201             if (displaypoints[i].exp != NULL) 
202             {
203                 expr_free(displaypoints[i].exp);
204                 displaypoints[i].exp = NULL;
205             }
206         }
207         maxdisplays = DISPTAB_DELTA;
208         displaypoints = dbg_heap_realloc(displaypoints,
209                                          (maxdisplays = DISPTAB_DELTA) * sizeof(*displaypoints));
210         ndisplays = 0;
211     }
212     else if (displaypoints[--displaynum].exp != NULL) 
213     {
214         expr_free(displaypoints[displaynum].exp);
215         displaypoints[displaynum].exp = NULL;
216         while (displaynum == ndisplays - 1 && displaypoints[displaynum].exp == NULL)
217         {
218             --ndisplays;
219             --displaynum;
220         }
221         if (maxdisplays - ndisplays >= 2 * DISPTAB_DELTA)
222         {
223             /* MARK */
224             maxdisplays = (ndisplays + DISPTAB_DELTA - 1) & ~(DISPTAB_DELTA - 1);
225             displaypoints = dbg_heap_realloc(displaypoints,
226                                              maxdisplays * sizeof(*displaypoints));
227         }
228     }
229     return TRUE;
230 }
231
232 int display_enable(int displaynum, int enable)
233 {
234     char                buffer[sizeof(SYMBOL_INFO) + 256];
235     SYMBOL_INFO*        func;
236
237     func = (SYMBOL_INFO*)buffer;
238     memset(func, 0, sizeof(SYMBOL_INFO));
239     func->SizeOfStruct = sizeof(SYMBOL_INFO);
240     func->MaxNameLen = sizeof(buffer) - sizeof(*func);
241     if (!stack_get_current_symbol(func)) return FALSE;
242
243     --displaynum;
244     if (displaynum >= ndisplays || displaynum < 0 || 
245         displaypoints[displaynum].exp == NULL) 
246     {
247         dbg_printf("Invalid display number\n");
248         return TRUE;
249     }
250
251     displaypoints[displaynum].enabled = enable;
252     if (!displaypoints[displaynum].func || 
253         cmp_symbol(displaypoints[displaynum].func, func))
254     {
255         print_one_display(displaynum);
256     }
257
258     return TRUE;
259 }