msmangle.c 25 KB

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