Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/tools/winedump/symbol.c
4389 views
1
/*
2
* Symbol functions
3
*
4
* Copyright 2000 Jon Griffiths
5
*
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Lesser General Public
8
* License as published by the Free Software Foundation; either
9
* version 2.1 of the License, or (at your option) any later version.
10
*
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with this library; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19
*/
20
21
#include "config.h"
22
23
#include "winedump.h"
24
25
26
/* Items that are swapped in arguments after the symbol structure
27
* has been populated
28
*/
29
static const char * const swap_after[] =
30
{
31
"\r", " ", /* Remove whitespace, normalise pointers and brackets */
32
"\t", " ",
33
" ", " ",
34
" * ", " *",
35
"* *", "**",
36
"* ", "*",
37
" ,", ",",
38
"( ", "(",
39
" )", ")",
40
"wchar_t", "WCHAR", /* Help with Unicode compiles */
41
"wctype_t", "WCHAR",
42
"wint_t", "WCHAR",
43
NULL, NULL
44
};
45
46
47
/* Items containing these substrings are assumed to be wide character
48
* strings, unless they contain more that one '*'. A preceding 'LP'
49
* counts as a '*', so 'LPWCSTR *' is a pointer, not a string
50
*/
51
static const char * const wide_strings[] =
52
{
53
"WSTR", "WCSTR", NULL
54
};
55
56
/* Items containing these substrings are assumed to be wide characters,
57
* unless they contain one '*'. A preceding 'LP' counts as a '*',
58
* so 'WCHAR *' is string, while 'LPWCHAR *' is a pointer
59
*/
60
static const char * const wide_chars[] =
61
{
62
"WCHAR", NULL
63
};
64
65
/* Items containing these substrings are assumed to be ASCII character
66
* strings, as above
67
*/
68
static const char * const ascii_strings[] =
69
{
70
"STR", "CSTR", NULL
71
};
72
73
74
/* Items containing these substrings are assumed to be ASCII characters,
75
* as above
76
*/
77
static const char * const ascii_chars[] =
78
{
79
"CHAR", "char", NULL
80
};
81
82
/* Any type other than the following will produce a FIXME warning with -v
83
* when mapped to a long, to allow fixups
84
*/
85
static const char * const known_longs[] =
86
{
87
"char", "CHAR", "float", "int", "INT", "short", "SHORT", "long", "LONG",
88
"WCHAR", "BOOL", "bool", "INT16", "WORD", "DWORD", NULL
89
};
90
91
void symbol_init(parsed_symbol* sym, const char* name)
92
{
93
memset(sym, 0, sizeof(parsed_symbol));
94
sym->symbol = xstrdup(name);
95
}
96
97
/*******************************************************************
98
* symbol_clear
99
*
100
* Free the memory used by a symbol and initialise it
101
*/
102
void symbol_clear(parsed_symbol *sym)
103
{
104
int i;
105
106
assert (sym);
107
assert (sym->symbol);
108
109
free (sym->symbol);
110
free (sym->return_text);
111
free (sym->function_name);
112
113
for (i = sym->argc - 1; i >= 0; i--)
114
{
115
free (sym->arg_text [i]);
116
free (sym->arg_name [i]);
117
}
118
memset (sym, 0, sizeof (parsed_symbol));
119
}
120
121
122
/*******************************************************************
123
* symbol_is_valid_c
124
*
125
* Check if a symbol is a valid C identifier
126
*/
127
BOOL symbol_is_valid_c(const parsed_symbol *sym)
128
{
129
char *name;
130
131
assert (sym);
132
assert (sym->symbol);
133
134
name = sym->symbol;
135
136
while (*name)
137
{
138
if (!isalnum (*name) && *name != '_')
139
return FALSE;
140
name++;
141
}
142
return TRUE;
143
}
144
145
146
/*******************************************************************
147
* symbol_get_call_convention
148
*
149
* Return the calling convention of a symbol
150
*/
151
const char *symbol_get_call_convention(const parsed_symbol *sym)
152
{
153
int call = sym->flags ? sym->flags : CALLING_CONVENTION;
154
155
assert (sym);
156
assert (sym->symbol);
157
158
if (call & SYM_CDECL)
159
return "cdecl";
160
return "stdcall";
161
}
162
163
164
/*******************************************************************
165
* symbol_get_spec_type
166
*
167
* Get the .spec file text for a symbol's argument
168
*/
169
const char *symbol_get_spec_type (const parsed_symbol *sym, size_t arg)
170
{
171
assert (arg < sym->argc);
172
switch (sym->arg_type [arg])
173
{
174
case ARG_STRING: return "str";
175
case ARG_WIDE_STRING: return "wstr";
176
case ARG_POINTER: return "ptr";
177
case ARG_DOUBLE: return "double";
178
case ARG_STRUCT:
179
case ARG_FLOAT:
180
case ARG_LONG: return "long";
181
}
182
assert (0);
183
return NULL;
184
}
185
186
187
/*******************************************************************
188
* symbol_get_type
189
*
190
* Get the ARG_ constant for a type string
191
*/
192
int symbol_get_type (const char *string)
193
{
194
const char *iter = string;
195
const char * const *tab;
196
int ptrs = 0;
197
198
while (*iter && isspace(*iter))
199
iter++;
200
if (*iter == 'P' || *iter == 'H')
201
ptrs++; /* Win32 type pointer */
202
203
iter = string;
204
while (*iter)
205
{
206
if (*iter == '*' || (*iter == 'L' && iter[1] == 'P')
207
|| (*iter == '[' && iter[1] == ']'))
208
ptrs++;
209
if (ptrs > 1)
210
return ARG_POINTER;
211
iter++;
212
}
213
214
/* 0 or 1 pointer */
215
tab = wide_strings;
216
while (*tab++)
217
if (strstr (string, tab[-1]))
218
{
219
if (ptrs < 2) return ARG_WIDE_STRING;
220
else return ARG_POINTER;
221
}
222
tab = wide_chars;
223
while (*tab++)
224
if (strstr (string, tab[-1]))
225
{
226
if (!ptrs) return ARG_LONG;
227
else return ARG_WIDE_STRING;
228
}
229
tab = ascii_strings;
230
while (*tab++)
231
if (strstr (string, tab[-1]))
232
{
233
if (ptrs < 2) return ARG_STRING;
234
else return ARG_POINTER;
235
}
236
tab = ascii_chars;
237
while (*tab++)
238
if (strstr (string, tab[-1]))
239
{
240
if (!ptrs) return ARG_LONG;
241
else {
242
if (!strstr (string, "unsigned")) /* unsigned char * => ptr */
243
return ARG_STRING;
244
}
245
}
246
247
if (ptrs)
248
return ARG_POINTER; /* Pointer to some other type */
249
250
/* No pointers */
251
if (strstr (string, "double"))
252
return ARG_DOUBLE;
253
254
if (strstr (string, "float") || strstr (string, "FLOAT"))
255
return ARG_FLOAT;
256
257
if (strstr (string, "void") || strstr (string, "VOID"))
258
return ARG_VOID;
259
260
if (strstr (string, "struct") || strstr (string, "union"))
261
return ARG_STRUCT; /* Struct by value, ugh */
262
263
if (VERBOSE)
264
{
265
BOOL known = FALSE;
266
267
tab = known_longs;
268
while (*tab++)
269
if (strstr (string, tab[-1]))
270
{
271
known = TRUE;
272
break;
273
}
274
/* Unknown types passed by value can be 'grep'ed out for fixup later */
275
if (!known)
276
printf ("/* FIXME: By value type: Assumed 'int' */ typedef int %s;\n",
277
string);
278
}
279
return ARG_LONG;
280
}
281
282
283
/*******************************************************************
284
* symbol_clean_string
285
*
286
* Make a type string more Wine-friendly. Logically const :-)
287
*/
288
void symbol_clean_string (char *str)
289
{
290
const char * const *tab = swap_after;
291
292
#define SWAP(i, p, x, y) do { i = p; while ((i = str_replace (i, x, y))); } while(0)
293
294
while (tab [0])
295
{
296
char *p;
297
SWAP (p, str, tab [0], tab [1]);
298
tab += 2;
299
}
300
if (str [strlen (str) - 1] == ' ')
301
str [strlen (str) - 1] = '\0'; /* no trailing space */
302
303
if (*str == ' ')
304
memmove (str, str + 1, strlen (str)); /* No leading spaces */
305
}
306
307