Reject pointer messages in SendNotifyMessage[AW] and
[wine/testsucceed.git] / tools / specmaker / symbol.c
blob50d9843786e5fcbe086e9734412c8e0612372060
1 /*
2 * Symbol functions
4 * Copyright 2000 Jon Griffiths
5 */
6 #include "specmaker.h"
9 /* Items that are swapped in arguments after the symbol structure
10 * has been populated
12 static const char *swap_after[] =
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
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
35 static const char *wide_strings[] =
37 "WSTR", "WCSTR", NULL
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
44 static const char *wide_chars[] =
46 "WCHAR", NULL
49 /* Items containing these substrings are assumed to be ASCII character
50 * strings, as above
52 static const char *ascii_strings[] =
54 "STR", "CSTR", NULL
58 /* Items containing these substrings are assumed to be ASCII characters,
59 * as above
61 static const char *ascii_chars[] =
63 "CHAR", "char", NULL
66 /* Any type other than the following will produce a FIXME warning with -v
67 * when mapped to a long, to allow fixups
69 static const char *known_longs[] =
71 "char", "CHAR", "float", "int", "INT", "short", "SHORT", "long", "LONG",
72 "WCHAR", "BOOL", "bool", "INT16", "WORD", "DWORD", NULL
76 /*******************************************************************
77 * symbol_clear
79 * Free the memory used by a symbol and initialise it
81 void symbol_clear(parsed_symbol *sym)
83 int i;
85 assert (sym);
86 assert (sym->symbol);
88 free (sym->symbol);
90 if (sym->return_text)
91 free (sym->return_text);
93 if (sym->function_name)
94 free (sym->function_name);
96 for (i = sym->argc - 1; i >= 0; i--)
98 if (sym->arg_text [i])
99 free (sym->arg_text [i]);
100 if (sym->arg_name [i])
101 free (sym->arg_name [i]);
103 memset (sym, 0, sizeof (parsed_symbol));
107 /*******************************************************************
108 * symbol_is_valid_c
110 * Check if a symbol is a valid C identifier
112 int symbol_is_valid_c(const parsed_symbol *sym)
114 char *name;
116 assert (sym);
117 assert (sym->symbol);
119 name = sym->symbol;
121 while (*name)
123 if (!isalnum (*name) && *name != '_')
124 return 0;
125 name++;
127 return 1;
131 /*******************************************************************
132 * symbol_get_call_convention
134 * Return the calling convention of a symbol
136 const char *symbol_get_call_convention(const parsed_symbol *sym)
138 int call = sym->flags ? sym->flags : CALLING_CONVENTION;
140 assert (sym);
141 assert (sym->symbol);
143 if (call & SYM_CDECL)
144 return "cdecl";
145 return "stdcall";
149 /*******************************************************************
150 * symbol_get_spec_type
152 * Get the .spec file text for a symbols argument
154 const char *symbol_get_spec_type (const parsed_symbol *sym, size_t arg)
156 assert (arg < sym->argc);
157 switch (sym->arg_type [arg])
159 case ARG_STRING: return "str";
160 case ARG_WIDE_STRING: return "wstr";
161 case ARG_POINTER: return "ptr";
162 case ARG_DOUBLE: return "double";
163 case ARG_STRUCT:
164 case ARG_FLOAT:
165 case ARG_LONG: return "long";
167 assert (0);
168 return NULL;
172 /*******************************************************************
173 * symbol_get_type
175 * Get the ARG_ constant for a type string
177 int symbol_get_type (const char *string)
179 const char *iter = string;
180 const char **tab;
181 int ptrs = 0;
183 while (*iter && isspace(*iter))
184 iter++;
185 if (*iter == 'P' || *iter == 'H')
186 ptrs++; /* Win32 type pointer */
188 iter = string;
189 while (*iter)
191 if (*iter == '*' || (*iter == 'L' && iter[1] == 'P')
192 || (*iter == '[' && iter[1] == ']'))
193 ptrs++;
194 if (ptrs > 1)
195 return ARG_POINTER;
196 iter++;
199 /* 0 or 1 pointer */
200 tab = wide_strings;
201 while (*tab++)
202 if (strstr (string, tab[-1]))
204 if (ptrs < 2) return ARG_WIDE_STRING;
205 else return ARG_POINTER;
207 tab = wide_chars;
208 while (*tab++)
209 if (strstr (string, tab[-1]))
211 if (!ptrs) return ARG_LONG;
212 else return ARG_WIDE_STRING;
214 tab = ascii_strings;
215 while (*tab++)
216 if (strstr (string, tab[-1]))
218 if (ptrs < 2) return ARG_STRING;
219 else return ARG_POINTER;
221 tab = ascii_chars;
222 while (*tab++)
223 if (strstr (string, tab[-1]))
225 if (!ptrs) return ARG_LONG;
226 else {
227 if (!strstr (string, "unsigned")) /* unsigned char * => ptr */
228 return ARG_STRING;
232 if (ptrs)
233 return ARG_POINTER; /* Pointer to some other type */
235 /* No pointers */
236 if (strstr (string, "double"))
237 return ARG_DOUBLE;
239 if (strstr (string, "void") || strstr (string, "VOID"))
240 return ARG_VOID;
242 if (strstr (string, "struct") || strstr (string, "union"))
243 return ARG_STRUCT; /* Struct by value, ugh */
245 if (VERBOSE)
247 int known = 0;
249 tab = known_longs;
250 while (*tab++)
251 if (strstr (string, tab[-1]))
253 known = 1;
254 break;
256 /* Unknown types passed by value can be 'grep'ed out for fixup later */
257 if (!known)
258 printf ("/* FIXME: By value type: Assumed 'int' */ typedef int %s;\n",
259 string);
261 return ARG_LONG;
265 /*******************************************************************
266 * symbol_clean_string
268 * Make a type string more Wine-friendly. Logically const :-)
270 void symbol_clean_string (const char *string)
272 const char **tab = swap_after;
273 char *str = (char *)string;
275 #define SWAP(i, p, x, y) do { i = p; while ((i = str_replace (i, x, y))); } while(0)
277 while (tab [0])
279 char *p;
280 SWAP (p, str, tab [0], tab [1]);
281 tab += 2;
283 if (str [strlen (str) - 1] == ' ')
284 str [strlen (str) - 1] = '\0'; /* no trailing space */
286 if (*str == ' ')
287 memmove (str, str + 1, strlen (str)); /* No leading spaces */