/*1* Symbol functions2*3* Copyright 2000 Jon Griffiths4*5* This library is free software; you can redistribute it and/or6* modify it under the terms of the GNU Lesser General Public7* License as published by the Free Software Foundation; either8* version 2.1 of the License, or (at your option) any later version.9*10* This library is distributed in the hope that it will be useful,11* but WITHOUT ANY WARRANTY; without even the implied warranty of12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU13* Lesser General Public License for more details.14*15* You should have received a copy of the GNU Lesser General Public16* License along with this library; if not, write to the Free Software17* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA18*/1920#include "config.h"2122#include "winedump.h"232425/* Items that are swapped in arguments after the symbol structure26* has been populated27*/28static const char * const swap_after[] =29{30"\r", " ", /* Remove whitespace, normalise pointers and brackets */31"\t", " ",32" ", " ",33" * ", " *",34"* *", "**",35"* ", "*",36" ,", ",",37"( ", "(",38" )", ")",39"wchar_t", "WCHAR", /* Help with Unicode compiles */40"wctype_t", "WCHAR",41"wint_t", "WCHAR",42NULL, NULL43};444546/* Items containing these substrings are assumed to be wide character47* strings, unless they contain more that one '*'. A preceding 'LP'48* counts as a '*', so 'LPWCSTR *' is a pointer, not a string49*/50static const char * const wide_strings[] =51{52"WSTR", "WCSTR", NULL53};5455/* Items containing these substrings are assumed to be wide characters,56* unless they contain one '*'. A preceding 'LP' counts as a '*',57* so 'WCHAR *' is string, while 'LPWCHAR *' is a pointer58*/59static const char * const wide_chars[] =60{61"WCHAR", NULL62};6364/* Items containing these substrings are assumed to be ASCII character65* strings, as above66*/67static const char * const ascii_strings[] =68{69"STR", "CSTR", NULL70};717273/* Items containing these substrings are assumed to be ASCII characters,74* as above75*/76static const char * const ascii_chars[] =77{78"CHAR", "char", NULL79};8081/* Any type other than the following will produce a FIXME warning with -v82* when mapped to a long, to allow fixups83*/84static const char * const known_longs[] =85{86"char", "CHAR", "float", "int", "INT", "short", "SHORT", "long", "LONG",87"WCHAR", "BOOL", "bool", "INT16", "WORD", "DWORD", NULL88};8990void symbol_init(parsed_symbol* sym, const char* name)91{92memset(sym, 0, sizeof(parsed_symbol));93sym->symbol = xstrdup(name);94}9596/*******************************************************************97* symbol_clear98*99* Free the memory used by a symbol and initialise it100*/101void symbol_clear(parsed_symbol *sym)102{103int i;104105assert (sym);106assert (sym->symbol);107108free (sym->symbol);109free (sym->return_text);110free (sym->function_name);111112for (i = sym->argc - 1; i >= 0; i--)113{114free (sym->arg_text [i]);115free (sym->arg_name [i]);116}117memset (sym, 0, sizeof (parsed_symbol));118}119120121/*******************************************************************122* symbol_is_valid_c123*124* Check if a symbol is a valid C identifier125*/126BOOL symbol_is_valid_c(const parsed_symbol *sym)127{128char *name;129130assert (sym);131assert (sym->symbol);132133name = sym->symbol;134135while (*name)136{137if (!isalnum (*name) && *name != '_')138return FALSE;139name++;140}141return TRUE;142}143144145/*******************************************************************146* symbol_get_call_convention147*148* Return the calling convention of a symbol149*/150const char *symbol_get_call_convention(const parsed_symbol *sym)151{152int call = sym->flags ? sym->flags : CALLING_CONVENTION;153154assert (sym);155assert (sym->symbol);156157if (call & SYM_CDECL)158return "cdecl";159return "stdcall";160}161162163/*******************************************************************164* symbol_get_spec_type165*166* Get the .spec file text for a symbol's argument167*/168const char *symbol_get_spec_type (const parsed_symbol *sym, size_t arg)169{170assert (arg < sym->argc);171switch (sym->arg_type [arg])172{173case ARG_STRING: return "str";174case ARG_WIDE_STRING: return "wstr";175case ARG_POINTER: return "ptr";176case ARG_DOUBLE: return "double";177case ARG_STRUCT:178case ARG_FLOAT:179case ARG_LONG: return "long";180}181assert (0);182return NULL;183}184185186/*******************************************************************187* symbol_get_type188*189* Get the ARG_ constant for a type string190*/191int symbol_get_type (const char *string)192{193const char *iter = string;194const char * const *tab;195int ptrs = 0;196197while (*iter && isspace(*iter))198iter++;199if (*iter == 'P' || *iter == 'H')200ptrs++; /* Win32 type pointer */201202iter = string;203while (*iter)204{205if (*iter == '*' || (*iter == 'L' && iter[1] == 'P')206|| (*iter == '[' && iter[1] == ']'))207ptrs++;208if (ptrs > 1)209return ARG_POINTER;210iter++;211}212213/* 0 or 1 pointer */214tab = wide_strings;215while (*tab++)216if (strstr (string, tab[-1]))217{218if (ptrs < 2) return ARG_WIDE_STRING;219else return ARG_POINTER;220}221tab = wide_chars;222while (*tab++)223if (strstr (string, tab[-1]))224{225if (!ptrs) return ARG_LONG;226else return ARG_WIDE_STRING;227}228tab = ascii_strings;229while (*tab++)230if (strstr (string, tab[-1]))231{232if (ptrs < 2) return ARG_STRING;233else return ARG_POINTER;234}235tab = ascii_chars;236while (*tab++)237if (strstr (string, tab[-1]))238{239if (!ptrs) return ARG_LONG;240else {241if (!strstr (string, "unsigned")) /* unsigned char * => ptr */242return ARG_STRING;243}244}245246if (ptrs)247return ARG_POINTER; /* Pointer to some other type */248249/* No pointers */250if (strstr (string, "double"))251return ARG_DOUBLE;252253if (strstr (string, "float") || strstr (string, "FLOAT"))254return ARG_FLOAT;255256if (strstr (string, "void") || strstr (string, "VOID"))257return ARG_VOID;258259if (strstr (string, "struct") || strstr (string, "union"))260return ARG_STRUCT; /* Struct by value, ugh */261262if (VERBOSE)263{264BOOL known = FALSE;265266tab = known_longs;267while (*tab++)268if (strstr (string, tab[-1]))269{270known = TRUE;271break;272}273/* Unknown types passed by value can be 'grep'ed out for fixup later */274if (!known)275printf ("/* FIXME: By value type: Assumed 'int' */ typedef int %s;\n",276string);277}278return ARG_LONG;279}280281282/*******************************************************************283* symbol_clean_string284*285* Make a type string more Wine-friendly. Logically const :-)286*/287void symbol_clean_string (char *str)288{289const char * const *tab = swap_after;290291#define SWAP(i, p, x, y) do { i = p; while ((i = str_replace (i, x, y))); } while(0)292293while (tab [0])294{295char *p;296SWAP (p, str, tab [0], tab [1]);297tab += 2;298}299if (str [strlen (str) - 1] == ' ')300str [strlen (str) - 1] = '\0'; /* no trailing space */301302if (*str == ' ')303memmove (str, str + 1, strlen (str)); /* No leading spaces */304}305306307