Refactor some of the string processing in msiexec.
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "debugger.h"
26 #include "wine/debug.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
29
30 /* needs to be power of 2, search for MARK to see why :) */
31 #define DISPTAB_DELTA 8
32
33 struct display
34 {
35     struct expr*        exp;
36     int                 count;
37     char                format;
38     char                enabled;
39     char                func_buffer[sizeof(SYMBOL_INFO) + 256];
40     SYMBOL_INFO*        func;
41 };
42
43 static struct display *displaypoints = NULL;
44 static unsigned int maxdisplays = 0, ndisplays = 0;
45
46 static inline BOOL cmp_symbol(const SYMBOL_INFO* si1, const SYMBOL_INFO* si2)
47 {
48     if (si1->NameLen != si2->NameLen) return FALSE;
49     return !memcmp(si1, si2, sizeof(SYMBOL_INFO) + si1->NameLen);
50 }
51
52 int display_add(struct expr *exp, int count, char format, int in_frame)
53 {
54     int                 i;
55
56     for (i = 0; i < ndisplays; i++)
57         if (displaypoints[i].exp == NULL)
58             break;
59
60     if (i == maxdisplays)
61     {
62         /* no space left - expand */
63         maxdisplays += DISPTAB_DELTA;
64         displaypoints = dbg_heap_realloc(displaypoints,
65                                          maxdisplays * sizeof(*displaypoints));
66     }
67
68     if (i == ndisplays) ndisplays++;
69
70     displaypoints[i].exp           = expr_clone(exp);
71     displaypoints[i].count         = count;
72     displaypoints[i].format        = format;
73     displaypoints[i].enabled       = TRUE;
74     if (in_frame)
75     {
76         displaypoints[i].func = (SYMBOL_INFO*)displaypoints[i].func_buffer;
77         displaypoints[i].func->SizeOfStruct = sizeof(SYMBOL_INFO);
78         displaypoints[i].func->MaxNameLen = sizeof(displaypoints[i].func_buffer) -
79             sizeof(*displaypoints[i].func);
80         if (!stack_get_frame(displaypoints[i].func, NULL))
81         {
82             expr_free(displaypoints[i].exp);
83             displaypoints[i].exp = NULL;
84             return FALSE;
85         }
86     }
87     else displaypoints[i].func = NULL;
88
89     return TRUE;
90 }
91
92 int display_info(void)
93 {
94     int                 i;
95     char                buffer[sizeof(SYMBOL_INFO) + 256];
96     SYMBOL_INFO*        func;
97     const char*         info;
98
99     func = (SYMBOL_INFO*)buffer;
100     func->SizeOfStruct = sizeof(SYMBOL_INFO);
101     func->MaxNameLen = sizeof(buffer) - sizeof(*func);
102     if (!stack_get_frame(func, NULL)) return FALSE;
103
104     for (i = 0; i < ndisplays; i++)
105     {
106         if (displaypoints[i].exp == NULL) continue;
107
108         if (displaypoints[i].enabled)
109         {
110             if (displaypoints[i].func && !cmp_symbol(displaypoints[i].func, func))
111                 info = " (out of scope)";
112             else
113                 info = "";
114         }
115         else
116             info = " (disabled)";
117         dbg_printf("%d in %s%s: ", 
118                    i + 1, func ? displaypoints[i].func->Name : "", info);
119         expr_print(displaypoints[i].exp);
120         dbg_printf("\n");
121     }
122     return TRUE;
123 }
124
125 static void print_one_display(int i)
126 {
127     struct dbg_lvalue   lvalue;
128
129     if (displaypoints[i].enabled) 
130     {
131         lvalue = expr_eval(displaypoints[i].exp);
132         if (lvalue.typeid == dbg_itype_none)
133         {
134             dbg_printf("Unable to evaluate expression ");
135             expr_print(displaypoints[i].exp);
136             dbg_printf("\nDisabling display %d ...\n", i + 1);
137             displaypoints[i].enabled = FALSE;
138             return;
139         }
140     }
141
142     dbg_printf("%d: ", i + 1);
143     expr_print(displaypoints[i].exp);
144     dbg_printf(" = ");
145     if (!displaypoints[i].enabled)
146         dbg_printf("(disabled)\n");
147     else
148         if (displaypoints[i].format == 'i')
149             memory_examine(&lvalue, displaypoints[i].count, displaypoints[i].format);
150         else
151             print_value(&lvalue, displaypoints[i].format, 0);
152 }
153
154 int display_print(void)
155 {
156     int                 i;
157     char                buffer[sizeof(SYMBOL_INFO) + 256];
158     SYMBOL_INFO*        func;
159
160     func = (SYMBOL_INFO*)buffer;
161     func->SizeOfStruct = sizeof(SYMBOL_INFO);
162     func->MaxNameLen = sizeof(buffer) - sizeof(*func);
163     if (!stack_get_frame(func, NULL)) return FALSE;
164
165     for (i = 0; i < ndisplays; i++)
166     {
167         if (displaypoints[i].exp == NULL || !displaypoints[i].enabled)
168             continue;
169         if (displaypoints[i].func && !cmp_symbol(displaypoints[i].func, func))
170             continue;
171         print_one_display(i);
172     }
173
174     return TRUE;
175 }
176
177 int display_delete(int displaynum)
178 {
179     int i;
180
181     if (displaynum > ndisplays || displaynum == 0 || displaynum < -1 ||
182         displaypoints[displaynum - 1].exp == NULL)
183     {
184         dbg_printf("Invalid display number\n");
185         return TRUE;
186     }
187
188     if (displaynum == -1)
189     {
190         for (i = 0; i < ndisplays; i++)
191         {
192             if (displaypoints[i].exp != NULL) 
193             {
194                 expr_free(displaypoints[i].exp);
195                 displaypoints[i].exp = NULL;
196             }
197         }
198         maxdisplays = DISPTAB_DELTA;
199         displaypoints = dbg_heap_realloc(displaypoints,
200                                          (maxdisplays = DISPTAB_DELTA) * sizeof(*displaypoints));
201         ndisplays = 0;
202     }
203     else if (displaypoints[--displaynum].exp != NULL) 
204     {
205         expr_free(displaypoints[displaynum].exp);
206         displaypoints[displaynum].exp = NULL;
207         while (displaynum == ndisplays - 1 && displaypoints[displaynum].exp == NULL)
208         {
209             --ndisplays;
210             --displaynum;
211         }
212         if (maxdisplays - ndisplays >= 2 * DISPTAB_DELTA)
213         {
214             /* MARK */
215             maxdisplays = (ndisplays + DISPTAB_DELTA - 1) & ~(DISPTAB_DELTA - 1);
216             displaypoints = dbg_heap_realloc(displaypoints,
217                                              maxdisplays * sizeof(*displaypoints));
218         }
219     }
220     return TRUE;
221 }
222
223 int display_enable(int displaynum, int enable)
224 {
225     char                buffer[sizeof(SYMBOL_INFO) + 256];
226     SYMBOL_INFO*        func;
227
228     func = (SYMBOL_INFO*)buffer;
229     func->SizeOfStruct = sizeof(SYMBOL_INFO);
230     func->MaxNameLen = sizeof(buffer) - sizeof(*func);
231     if (!stack_get_frame(func, NULL)) return FALSE;
232
233     --displaynum;
234     if (displaynum >= ndisplays || displaynum < 0 || 
235         displaypoints[displaynum].exp == NULL) 
236     {
237         dbg_printf("Invalid display number\n");
238         return TRUE;
239     }
240
241     displaypoints[displaynum].enabled = enable;
242     if (!displaypoints[displaynum].func || 
243         cmp_symbol(displaypoints[displaynum].func, func))
244     {
245         print_one_display(displaynum);
246     }
247
248     return TRUE;
249 }