ntdll: Fix SMT CPU flag reporting.
[wine/zf.git] / tools / winedump / msmangle.c
blobf9fe75b7d5eee8e549e2a030c6155a07812e15f6
1 /*
2 * Demangle VC++ symbols into C function prototypes
4 * Copyright 2000 Jon Griffiths
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.
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.
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
21 #include "config.h"
22 #include "wine/port.h"
24 #include "winedump.h"
26 /* Type for parsing mangled types */
27 typedef struct _compound_type
29 char dest_type;
30 int flags;
31 BOOL have_qualifiers;
32 char *expression;
33 } compound_type;
36 /* Initialise a compound type structure */
37 #define INIT_CT(ct) do { memset (&ct, 0, sizeof (ct)); } while (0)
39 /* free the memory used by a compound structure */
40 #define FREE_CT(ct) free (ct.expression)
42 /* Flags for data types */
43 #define DATA_VTABLE 0x1
45 /* Internal functions */
46 static char *demangle_datatype (char **str, compound_type *ct,
47 parsed_symbol* sym);
49 static char *get_constraints_convention_1 (char **str, compound_type *ct);
51 static char *get_constraints_convention_2 (char **str, compound_type *ct);
53 static char *get_type_string (const char c, const int constraints);
55 static int get_type_constant (const char c, const int constraints);
57 static char *get_pointer_type_string (compound_type *ct,
58 const char *expression);
61 /*******************************************************************
62 * demangle_symbol
64 * Demangle a C++ linker symbol into a C prototype
66 BOOL symbol_demangle (parsed_symbol *sym)
68 compound_type ct;
69 BOOL is_static = FALSE;
70 int is_const = 0;
71 char *function_name = NULL;
72 char *class_name = NULL;
73 char *name;
74 const char *const_status;
75 static unsigned int hash = 0; /* In case of overloaded functions */
76 unsigned int data_flags = 0;
78 assert (globals.do_code);
79 assert (sym && sym->symbol);
81 hash++;
83 /* MS mangled names always begin with '?' */
84 name = sym->symbol;
85 if (*name++ != '?')
86 return FALSE;
88 if (VERBOSE)
89 puts ("Attempting to demangle symbol");
91 /* Then function name or operator code */
92 if (*name == '?')
94 /* C++ operator code (one character, or two if the first is '_') */
95 switch (*++name)
97 case '0': function_name = strdup ("ctor"); break;
98 case '1': function_name = strdup ("dtor"); break;
99 case '2': function_name = strdup ("operator_new"); break;
100 case '3': function_name = strdup ("operator_delete"); break;
101 case '4': function_name = strdup ("operator_equals"); break;
102 case '5': function_name = strdup ("operator_shiftright"); break;
103 case '6': function_name = strdup ("operator_shiftleft"); break;
104 case '7': function_name = strdup ("operator_not"); break;
105 case '8': function_name = strdup ("operator_equalsequals"); break;
106 case '9': function_name = strdup ("operator_notequals"); break;
107 case 'A': function_name = strdup ("operator_array"); break;
108 case 'C': function_name = strdup ("operator_dereference"); break;
109 case 'D': function_name = strdup ("operator_multiply"); break;
110 case 'E': function_name = strdup ("operator_plusplus"); break;
111 case 'F': function_name = strdup ("operator_minusminus"); break;
112 case 'G': function_name = strdup ("operator_minus"); break;
113 case 'H': function_name = strdup ("operator_plus"); break;
114 case 'I': function_name = strdup ("operator_address"); break;
115 case 'J': function_name = strdup ("operator_dereferencememberptr"); break;
116 case 'K': function_name = strdup ("operator_divide"); break;
117 case 'L': function_name = strdup ("operator_modulo"); break;
118 case 'M': function_name = strdup ("operator_lessthan"); break;
119 case 'N': function_name = strdup ("operator_lessthanequal"); break;
120 case 'O': function_name = strdup ("operator_greaterthan"); break;
121 case 'P': function_name = strdup ("operator_greaterthanequal"); break;
122 case 'Q': function_name = strdup ("operator_comma"); break;
123 case 'R': function_name = strdup ("operator_functioncall"); break;
124 case 'S': function_name = strdup ("operator_complement"); break;
125 case 'T': function_name = strdup ("operator_xor"); break;
126 case 'U': function_name = strdup ("operator_logicalor"); break;
127 case 'V': function_name = strdup ("operator_logicaland"); break;
128 case 'W': function_name = strdup ("operator_or"); break;
129 case 'X': function_name = strdup ("operator_multiplyequals"); break;
130 case 'Y': function_name = strdup ("operator_plusequals"); break;
131 case 'Z': function_name = strdup ("operator_minusequals"); break;
132 case '_':
133 switch (*++name)
135 case '0': function_name = strdup ("operator_divideequals"); break;
136 case '1': function_name = strdup ("operator_moduloequals"); break;
137 case '2': function_name = strdup ("operator_shiftrightequals"); break;
138 case '3': function_name = strdup ("operator_shiftleftequals"); break;
139 case '4': function_name = strdup ("operator_andequals"); break;
140 case '5': function_name = strdup ("operator_orequals"); break;
141 case '6': function_name = strdup ("operator_xorequals"); break;
142 case '7': function_name = strdup ("vftable"); data_flags = DATA_VTABLE; break;
143 case '8': function_name = strdup ("vbtable"); data_flags = DATA_VTABLE; break;
144 case '9': function_name = strdup ("vcall"); data_flags = DATA_VTABLE; break;
145 case 'A': function_name = strdup ("typeof"); data_flags = DATA_VTABLE; break;
146 case 'B': function_name = strdup ("local_static_guard"); data_flags = DATA_VTABLE; break;
147 case 'C': function_name = strdup ("string"); data_flags = DATA_VTABLE; break;
148 case 'D': function_name = strdup ("vbase_dtor"); data_flags = DATA_VTABLE; break;
149 case 'E': function_name = strdup ("vector_dtor"); break;
150 case 'G': function_name = strdup ("scalar_dtor"); break;
151 case 'H': function_name = strdup ("vector_ctor_iter"); break;
152 case 'I': function_name = strdup ("vector_dtor_iter"); break;
153 case 'J': function_name = strdup ("vector_vbase_ctor_iter"); break;
154 case 'L': function_name = strdup ("eh_vector_ctor_iter"); break;
155 case 'M': function_name = strdup ("eh_vector_dtor_iter"); break;
156 case 'N': function_name = strdup ("eh_vector_vbase_ctor_iter"); break;
157 case 'O': function_name = strdup ("copy_ctor_closure"); break;
158 case 'S': function_name = strdup ("local_vftable"); data_flags = DATA_VTABLE; break;
159 case 'T': function_name = strdup ("local_vftable_ctor_closure"); break;
160 case 'U': function_name = strdup ("operator_new_vector"); break;
161 case 'V': function_name = strdup ("operator_delete_vector"); break;
162 case 'X': function_name = strdup ("placement_new_closure"); break;
163 case 'Y': function_name = strdup ("placement_delete_closure"); break;
164 default:
165 return FALSE;
167 break;
168 default:
169 /* FIXME: Other operators */
170 return FALSE;
172 name++;
174 else
176 /* Type or function name terminated by '@' */
177 function_name = name;
178 while (*name && *name++ != '@') ;
179 if (!*name)
180 return FALSE;
181 function_name = str_substring (function_name, name - 1);
184 /* Either a class name, or '@' if the symbol is not a class member */
185 if (*name == '@')
187 class_name = strdup ("global"); /* Non member function (or a datatype) */
188 name++;
190 else
192 /* Class the function is associated with, terminated by '@@' */
193 class_name = name;
194 while (*name && *name++ != '@') ;
195 if (*name++ != '@') {
196 free (function_name);
197 return FALSE;
199 class_name = str_substring (class_name, name - 2); /* Allocates a new string */
202 /* Function/Data type and access level */
203 /* FIXME: why 2 possible letters for each option? */
204 switch(*name++)
206 /* Data */
208 case '0' : /* private static */
209 case '1' : /* protected static */
210 case '2' : /* public static */
211 is_static = TRUE;
212 /* Fall through */
213 case '3' : /* non static */
214 case '4' : /* non static */
215 /* Data members need to be implemented: report */
216 INIT_CT (ct);
217 if (!demangle_datatype (&name, &ct, sym))
219 if (VERBOSE)
220 printf ("/*FIXME: %s: unknown data*/\n", sym->symbol);
221 free (function_name);
222 free (class_name);
223 return FALSE;
225 sym->flags |= SYM_DATA;
226 sym->argc = 1;
227 sym->arg_name[0] = str_create (5, OUTPUT_UC_DLL_NAME, "_", class_name,
228 is_static ? "static_" : "_", function_name);
229 sym->arg_text[0] = str_create (3, ct.expression, " ", sym->arg_name[0]);
230 FREE_CT (ct);
231 free (function_name);
232 free (class_name);
233 return TRUE;
235 case '6' : /* compiler generated static */
236 case '7' : /* compiler generated static */
237 if (data_flags & DATA_VTABLE)
239 sym->flags |= SYM_DATA;
240 sym->argc = 1;
241 sym->arg_name[0] = str_create (5, OUTPUT_UC_DLL_NAME, "_", class_name,
242 "_", function_name);
243 sym->arg_text[0] = str_create (2, "void *", sym->arg_name[0]);
245 if (VERBOSE)
246 puts ("Demangled symbol OK [vtable]");
247 free (function_name);
248 free (class_name);
249 return TRUE;
251 free (function_name);
252 free (class_name);
253 return FALSE;
255 /* Functions */
257 case 'E' : /* private virtual */
258 case 'F' : /* private virtual */
259 case 'M' : /* protected virtual */
260 case 'N' : /* protected virtual */
261 case 'U' : /* public virtual */
262 case 'V' : /* public virtual */
263 /* Virtual functions need to be added to the exported vtable: report */
264 if (VERBOSE)
265 printf ("/*FIXME %s: %s::%s is virtual-add to vftable*/\n", sym->symbol,
266 class_name, function_name);
267 /* Fall through */
268 case 'A' : /* private */
269 case 'B' : /* private */
270 case 'I' : /* protected */
271 case 'J' : /* protected */
272 case 'Q' : /* public */
273 case 'R' : /* public */
274 /* Implicit 'this' pointer */
275 sym->arg_text [sym->argc] = str_create (3, "struct ", class_name, " *");
276 sym->arg_type [sym->argc] = ARG_POINTER;
277 sym->arg_flag [sym->argc] = 0;
278 sym->arg_name [sym->argc++] = strdup ("_this");
279 /* New struct definitions can be 'grep'ed out for making a fixup header */
280 if (VERBOSE)
281 printf ("struct %s { void **vtable; /*FIXME: class definition */ };\n", class_name);
282 break;
283 case 'C' : /* private: static */
284 case 'D' : /* private: static */
285 case 'K' : /* protected: static */
286 case 'L' : /* protected: static */
287 case 'S' : /* public: static */
288 case 'T' : /* public: static */
289 is_static = TRUE; /* No implicit this pointer */
290 break;
291 case 'Y' :
292 case 'Z' :
293 break;
294 /* FIXME: G,H / O,P / W,X are private / protected / public thunks */
295 default:
296 free (function_name);
297 free (class_name);
298 return FALSE;
301 /* If there is an implicit this pointer, const status follows */
302 if (sym->argc)
304 switch (*name++)
306 case 'A': break; /* non-const */
307 case 'B': is_const = CT_CONST; break;
308 case 'C': is_const = CT_VOLATILE; break;
309 case 'D': is_const = (CT_CONST | CT_VOLATILE); break;
310 default:
311 free (function_name);
312 free (class_name);
313 return FALSE;
317 /* Next is the calling convention */
318 switch (*name++)
320 case 'A': /* __cdecl */
321 case 'B': /* __cdecl __declspec(dllexport) */
322 if (!sym->argc)
324 sym->flags |= SYM_CDECL;
325 break;
327 /* Else fall through */
328 case 'C': /* __pascal */
329 case 'D': /* __pascal __declspec(dllexport) */
330 case 'E': /* __thiscall */
331 case 'F': /* __thiscall __declspec(dllexport) */
332 case 'G': /* __stdcall */
333 case 'H': /* __stdcall __declspec(dllexport) */
334 case 'I': /* __fastcall */
335 case 'J': /* __fastcall __declspec(dllexport)*/
336 case 'K': /* default (none given) */
337 if (sym->argc)
338 sym->flags |= SYM_THISCALL;
339 else
340 sym->flags |= SYM_STDCALL;
341 break;
342 default:
343 free (function_name);
344 free (class_name);
345 return FALSE;
348 /* Return type, or @ if 'void' */
349 if (*name == '@')
351 sym->return_text = strdup ("void");
352 sym->return_type = ARG_VOID;
353 name++;
355 else
357 INIT_CT (ct);
358 if (!demangle_datatype (&name, &ct, sym)) {
359 free (function_name);
360 free (class_name);
361 return FALSE;
363 sym->return_text = ct.expression;
364 sym->return_type = get_type_constant(ct.dest_type, ct.flags);
365 ct.expression = NULL;
366 FREE_CT (ct);
369 /* Now come the function arguments */
370 while (*name && *name != 'Z')
372 /* Decode each data type and append it to the argument list */
373 if (*name != '@')
375 INIT_CT (ct);
376 if (!demangle_datatype(&name, &ct, sym)) {
377 free (function_name);
378 free (class_name);
379 return FALSE;
382 if (strcmp (ct.expression, "void"))
384 sym->arg_text [sym->argc] = ct.expression;
385 ct.expression = NULL;
386 sym->arg_type [sym->argc] = get_type_constant (ct.dest_type, ct.flags);
387 sym->arg_flag [sym->argc] = ct.flags;
388 sym->arg_name[sym->argc] = str_create_num (1, sym->argc, "arg");
389 sym->argc++;
391 else
392 break; /* 'void' terminates an argument list */
393 FREE_CT (ct);
395 else
396 name++;
399 while (*name == '@')
400 name++;
402 /* Functions are always terminated by 'Z'. If we made it this far and
403 * Don't find it, we have incorrectly identified a data type.
405 if (*name != 'Z') {
406 free (function_name);
407 free (class_name);
408 return FALSE;
411 /* Note: '()' after 'Z' means 'throws', but we don't care here */
413 /* Create the function name. Include a unique number because otherwise
414 * overloaded functions could have the same c signature.
416 switch (is_const)
418 case (CT_CONST | CT_VOLATILE): const_status = "_const_volatile"; break;
419 case CT_CONST: const_status = "_const"; break;
420 case CT_VOLATILE: const_status = "_volatile"; break;
421 default: const_status = "_"; break;
423 sym->function_name = str_create_num (4, hash, class_name, "_",
424 function_name, is_static ? "_static" : const_status);
426 assert (sym->return_text);
427 assert (sym->flags);
428 assert (sym->function_name);
430 free (class_name);
431 free (function_name);
433 if (VERBOSE)
434 puts ("Demangled symbol OK");
436 return TRUE;
440 /*******************************************************************
441 * demangle_datatype
443 * Attempt to demangle a C++ data type, which may be compound.
444 * a compound type is made up of a number of simple types. e.g:
445 * char** = (pointer to (pointer to (char)))
447 * Uses a simple recursive descent algorithm that is broken
448 * and/or incomplete, without a doubt ;-)
450 static char *demangle_datatype (char **str, compound_type *ct,
451 parsed_symbol* sym)
453 char *iter;
455 assert (str && *str);
456 assert (ct);
458 iter = *str;
460 if (!get_constraints_convention_1 (&iter, ct))
461 return NULL;
463 if (*iter == '_')
465 /* MS type: __int8,__int16 etc */
466 ct->flags |= CT_EXTENDED;
467 iter++;
470 switch (*iter)
472 case 'C': case 'D': case 'E': case 'F': case 'G':
473 case 'H': case 'I': case 'J': case 'K': case 'M':
474 case 'N': case 'O': case 'X': case 'Z':
475 /* Simple data types */
476 ct->dest_type = *iter++;
477 if (!get_constraints_convention_2 (&iter, ct))
478 return NULL;
479 ct->expression = get_type_string (ct->dest_type, ct->flags);
480 break;
481 case 'U':
482 case 'V':
483 /* Class/struct/union */
484 ct->dest_type = *iter++;
485 if (*iter == '0' || *iter == '1')
487 /* Referring to class type (implicit 'this') */
488 char *stripped;
489 if (!sym->argc)
490 return NULL;
492 iter++;
493 /* Apply our constraints to the base type (struct xxx *) */
494 stripped = strdup (sym->arg_text [0]);
495 if (!stripped)
496 fatal ("Out of Memory");
498 /* If we're a reference, re-use the pointer already in the type */
499 if (!(ct->flags & CT_BY_REFERENCE))
500 stripped[ strlen (stripped) - 2] = '\0'; /* otherwise, strip it */
502 ct->expression = str_create (2, ct->flags & CT_CONST ? "const " :
503 ct->flags & CT_VOLATILE ? "volatile " : "", stripped);
504 free (stripped);
506 else if (*iter != '@')
508 /* The name of the class/struct, followed by '@@' */
509 char *struct_name = iter;
510 while (*iter && *iter++ != '@') ;
511 if (*iter++ != '@')
512 return NULL;
513 struct_name = str_substring (struct_name, iter - 2);
514 ct->expression = str_create (4, ct->flags & CT_CONST ? "const " :
515 ct->flags & CT_VOLATILE ? "volatile " : "", "struct ",
516 struct_name, ct->flags & CT_BY_REFERENCE ? " *" : "");
517 free (struct_name);
519 break;
520 case 'Q': /* FIXME: Array Just treated as pointer currently */
521 case 'P': /* Pointer */
523 compound_type sub_ct;
524 INIT_CT (sub_ct);
526 ct->dest_type = *iter++;
527 if (!get_constraints_convention_2 (&iter, ct))
528 return NULL;
530 /* FIXME: P6 = Function pointer, others who knows.. */
531 if (isdigit (*iter))
533 if (*iter == '6')
535 int sub_expressions = 0;
536 /* FIXME: there are tons of memory leaks here */
537 /* FIXME: this is still broken in some cases and it has to be
538 * merged with the function prototype parsing above...
540 iter += iter[1] == 'A' ? 2 : 3; /* FIXME */
541 if (!demangle_datatype (&iter, &sub_ct, sym))
542 return NULL;
543 ct->expression = str_create(2, sub_ct.expression, " (*)(");
544 if (*iter != '@')
546 while (*iter != 'Z')
548 FREE_CT (sub_ct);
549 INIT_CT (sub_ct);
550 if (!demangle_datatype (&iter, &sub_ct, sym))
551 return NULL;
552 if (sub_expressions)
553 ct->expression = str_create(3, ct->expression, ", ", sub_ct.expression);
554 else
555 ct->expression = str_create(2, ct->expression, sub_ct.expression);
556 while (*iter == '@') iter++;
557 sub_expressions++;
559 } else while (*iter == '@') iter++;
560 iter++;
561 ct->expression = str_create(2, ct->expression, ")");
563 else
564 return NULL;
566 else
568 /* Recurse to get the pointed-to type */
569 if (!demangle_datatype (&iter, &sub_ct, sym))
570 return NULL;
572 ct->expression = get_pointer_type_string (ct, sub_ct.expression);
575 FREE_CT (sub_ct);
577 break;
578 case '0': case '1': case '2': case '3': case '4':
579 case '5': case '6': case '7': case '8': case '9':
580 /* Referring back to previously parsed type */
581 if (sym->argc >= (size_t)('0' - *iter))
582 return NULL;
583 ct->dest_type = sym->arg_type ['0' - *iter];
584 ct->expression = strdup (sym->arg_text ['0' - *iter]);
585 iter++;
586 break;
587 default :
588 return NULL;
590 if (!ct->expression)
591 return NULL;
593 return *str = iter;
597 /* Constraints:
598 * There are two conventions for specifying data type constants. I
599 * don't know how the compiler chooses between them, but I suspect it
600 * is based on ensuring that linker names are unique.
601 * Convention 1. The data type modifier is given first, followed
602 * by the data type it operates on. '?' means passed by value,
603 * 'A' means passed by reference. Note neither of these characters
604 * is a valid base data type. This is then followed by a character
605 * specifying constness or volatility.
606 * Convention 2. The base data type (which is never '?' or 'A') is
607 * given first. The character modifier is optionally given after
608 * the base type character. If a valid character modifier is present,
609 * then it only applies to the current data type if the character
610 * after that is not 'A' 'B' or 'C' (Because this makes a convention 1
611 * constraint for the next data type).
613 * The conventions are usually mixed within the same symbol.
614 * Since 'C' is both a qualifier and a data type, I suspect that
615 * convention 1 allows specifying e.g. 'volatile signed char*'. In
616 * convention 2 this would be 'CC' which is ambiguous (i.e. Is it two
617 * pointers, or a single pointer + modifier?). In convention 1 it
618 * is encoded as '?CC' which is not ambiguous. This probably
619 * holds true for some other types as well.
622 /*******************************************************************
623 * get_constraints_convention_1
625 * Get type constraint information for a data type
627 static char *get_constraints_convention_1 (char **str, compound_type *ct)
629 char *iter = *str, **retval = str;
631 if (ct->have_qualifiers)
632 return *str; /* Previously got constraints for this type */
634 if (*iter == '?' || *iter == 'A')
636 ct->have_qualifiers = TRUE;
637 ct->flags |= (*iter++ == '?' ? 0 : CT_BY_REFERENCE);
639 switch (*iter++)
641 case 'A' :
642 break; /* non-const, non-volatile */
643 case 'B' :
644 ct->flags |= CT_CONST;
645 break;
646 case 'C' :
647 ct->flags |= CT_VOLATILE;
648 break;
649 default :
650 return NULL;
654 return *retval = iter;
658 /*******************************************************************
659 * get_constraints_convention_2
661 * Get type constraint information for a data type
663 static char *get_constraints_convention_2 (char **str, compound_type *ct)
665 char *iter = *str, **retval = str;
667 /* FIXME: Why do arrays have both convention 1 & 2 constraints? */
668 if (ct->have_qualifiers && ct->dest_type != 'Q')
669 return *str; /* Previously got constraints for this type */
671 ct->have_qualifiers = TRUE; /* Even if none, we've got all we're getting */
673 switch (*iter)
675 case 'A' :
676 if (iter[1] != 'A' && iter[1] != 'B' && iter[1] != 'C')
677 iter++;
678 break;
679 case 'B' :
680 ct->flags |= CT_CONST;
681 iter++;
682 break;
683 case 'C' :
684 /* See note above, if we find 'C' it is _not_ a signed char */
685 ct->flags |= CT_VOLATILE;
686 iter++;
687 break;
690 return *retval = iter;
694 /*******************************************************************
695 * get_type_string
697 * Return a string containing the name of a data type
699 static char *get_type_string (const char c, const int constraints)
701 const char *type_string;
703 if (constraints & CT_EXTENDED)
705 switch (c)
707 case 'D': type_string = "__int8"; break;
708 case 'E': type_string = "unsigned __int8"; break;
709 case 'F': type_string = "__int16"; break;
710 case 'G': type_string = "unsigned __int16"; break;
711 case 'H': type_string = "__int32"; break;
712 case 'I': type_string = "unsigned __int32"; break;
713 case 'J': type_string = "__int64"; break;
714 case 'K': type_string = "unsigned __int64"; break;
715 case 'L': type_string = "__int128"; break;
716 case 'M': type_string = "unsigned __int128"; break;
717 case 'N': type_string = "int"; break; /* bool */
718 case 'W': type_string = "WCHAR"; break; /* wchar_t */
719 default:
720 return NULL;
723 else
725 switch (c)
727 case 'C': /* Signed char, fall through */
728 case 'D': type_string = "char"; break;
729 case 'E': type_string = "unsigned char"; break;
730 case 'F': type_string = "short int"; break;
731 case 'G': type_string = "unsigned short int"; break;
732 case 'H': type_string = "int"; break;
733 case 'I': type_string = "unsigned int"; break;
734 case 'J': type_string = "long"; break;
735 case 'K': type_string = "unsigned long"; break;
736 case 'M': type_string = "float"; break;
737 case 'N': type_string = "double"; break;
738 case 'O': type_string = "long double"; break;
739 /* FIXME: T = union */
740 case 'U':
741 case 'V': type_string = "struct"; break;
742 case 'X': return strdup ("void");
743 case 'Z': return strdup ("...");
744 default:
745 return NULL;
749 return str_create (3, constraints & CT_CONST ? "const " :
750 constraints & CT_VOLATILE ? "volatile " : "", type_string,
751 constraints & CT_BY_REFERENCE ? " *" : "");
755 /*******************************************************************
756 * get_type_constant
758 * Get the ARG_* constant for this data type
760 static int get_type_constant (const char c, const int constraints)
762 /* Any reference type is really a pointer */
763 if (constraints & CT_BY_REFERENCE)
764 return ARG_POINTER;
766 switch (c)
768 case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I':
769 case 'J': case 'K':
770 return ARG_LONG;
771 case 'M':
772 return ARG_FLOAT;
773 case 'N': case 'O':
774 return ARG_DOUBLE;
775 case 'P': case 'Q':
776 return ARG_POINTER;
777 case 'U': case 'V':
778 return ARG_STRUCT;
779 case 'X':
780 return ARG_VOID;
781 case 'Z':
782 default:
783 return -1;
788 /*******************************************************************
789 * get_pointer_type_string
791 * Return a string containing 'pointer to expression'
793 static char *get_pointer_type_string (compound_type *ct,
794 const char *expression)
796 /* FIXME: set a compound flag for bracketing expression if needed */
797 return str_create (3, ct->flags & CT_CONST ? "const " :
798 ct->flags & CT_VOLATILE ? "volatile " : "", expression,
799 ct->flags & CT_BY_REFERENCE ? " **" : " *");