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