symbol.c 7.03 KB
Newer Older
1 2 3 4
/*
 *  Symbol functions
 *
 *  Copyright 2000 Jon Griffiths
5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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 21 22 23

#include "config.h"
#include "wine/port.h"

24
#include "winedump.h"
25 26 27 28 29


/* Items that are swapped in arguments after the symbol structure
 * has been populated
 */
30
static const char * const swap_after[] =
31 32 33 34 35 36 37 38 39 40
{
  "\r", " ", /* Remove whitespace, normalise pointers and brackets */
  "\t", " ",
  "  ", " ",
  " * ", " *",
  "* *", "**",
  "* ", "*",
  " ,", ",",
  "( ", "(",
  " )", ")",
Austin English's avatar
Austin English committed
41
  "wchar_t", "WCHAR", /* Help with Unicode compiles */
42 43 44 45 46 47 48
  "wctype_t", "WCHAR",
  "wint_t", "WCHAR",
  NULL, NULL
};


/* Items containing these substrings are assumed to be wide character
49
 * strings, unless they contain more that one '*'. A preceding 'LP'
50 51
 * counts as a '*', so 'LPWCSTR *' is a pointer, not a string
 */
52
static const char * const wide_strings[] =
53 54 55 56 57
{
  "WSTR", "WCSTR", NULL
};

/* Items containing these substrings are assumed to be wide characters,
58
 * unless they contain one '*'. A preceding 'LP' counts as a '*',
59 60
 * so 'WCHAR *' is string, while 'LPWCHAR *' is a pointer
 */
61
static const char * const wide_chars[] =
62 63 64 65 66 67 68
{
  "WCHAR", NULL
};

/* Items containing these substrings are assumed to be ASCII character
 * strings, as above
 */
69
static const char * const ascii_strings[] =
70 71 72 73 74 75 76 77
{
  "STR", "CSTR", NULL
};


/* Items containing these substrings are assumed to be ASCII characters,
 * as above
 */
78
static const char * const ascii_chars[] =
79 80 81 82 83 84 85
{
  "CHAR", "char", NULL
};

/* Any type other than the following will produce a FIXME warning with -v
 * when mapped to a long, to allow fixups
 */
86
static const char * const known_longs[] =
87 88
{
  "char", "CHAR", "float", "int", "INT", "short", "SHORT", "long", "LONG",
89
  "WCHAR", "BOOL", "bool", "INT16", "WORD", "DWORD", NULL
90 91
};

92 93 94 95 96 97
int symbol_init(parsed_symbol* sym, const char* name)
{
    memset(sym, 0, sizeof(parsed_symbol));
    sym->symbol = strdup(name);
    return 0;
}
98 99 100 101 102 103 104 105 106 107 108 109 110 111

/*******************************************************************
 *         symbol_clear
 *
 * Free the memory used by a symbol and initialise it
 */
void symbol_clear(parsed_symbol *sym)
{
 int i;

 assert (sym);
 assert (sym->symbol);

 free (sym->symbol);
112 113
 free (sym->return_text);
 free (sym->function_name);
114 115 116

 for (i = sym->argc - 1; i >= 0; i--)
 {
117 118
   free (sym->arg_text [i]);
   free (sym->arg_name [i]);
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
 }
 memset (sym, 0, sizeof (parsed_symbol));
}


/*******************************************************************
 *         symbol_is_valid_c
 *
 * Check if a symbol is a valid C identifier
 */
int symbol_is_valid_c(const parsed_symbol *sym)
{
  char *name;

  assert (sym);
  assert (sym->symbol);

  name = sym->symbol;

  while (*name)
  {
    if (!isalnum (*name) && *name != '_')
      return 0;
    name++;
  }
  return 1;
}


/*******************************************************************
149
 *         symbol_get_call_convention
150
 *
151
 * Return the calling convention of a symbol
152
 */
153
const char *symbol_get_call_convention(const parsed_symbol *sym)
154
{
155 156
  int call = sym->flags ? sym->flags : CALLING_CONVENTION;

157 158 159
  assert (sym);
  assert (sym->symbol);

160 161 162
  if (call & SYM_CDECL)
    return "cdecl";
  return "stdcall";
163 164 165 166 167 168
}


/*******************************************************************
 *         symbol_get_spec_type
 *
Austin English's avatar
Austin English committed
169
 * Get the .spec file text for a symbol's argument
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
 */
const char *symbol_get_spec_type (const parsed_symbol *sym, size_t arg)
{
  assert (arg < sym->argc);
  switch (sym->arg_type [arg])
  {
  case ARG_STRING:      return "str";
  case ARG_WIDE_STRING: return "wstr";
  case ARG_POINTER:     return "ptr";
  case ARG_DOUBLE:      return "double";
  case ARG_STRUCT:
  case ARG_FLOAT:
  case ARG_LONG:        return "long";
  }
  assert (0);
  return NULL;
}


/*******************************************************************
 *         symbol_get_type
 *
 * Get the ARG_ constant for a type string
 */
int   symbol_get_type (const char *string)
{
  const char *iter = string;
197
  const char * const *tab;
198 199
  int ptrs = 0;

200 201 202 203 204 205
  while (*iter && isspace(*iter))
    iter++;
  if (*iter == 'P' || *iter == 'H')
    ptrs++; /* Win32 type pointer */

  iter = string;
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
  while (*iter)
  {
    if (*iter == '*' || (*iter == 'L' && iter[1] == 'P')
        || (*iter == '[' && iter[1] == ']'))
      ptrs++;
    if (ptrs > 1)
      return ARG_POINTER;
    iter++;
  }

  /* 0 or 1 pointer */
  tab = wide_strings;
  while (*tab++)
    if (strstr (string, tab[-1]))
    {
221 222
      if (ptrs < 2) return ARG_WIDE_STRING;
      else          return ARG_POINTER;
223 224 225 226 227 228 229 230 231 232 233 234
    }
  tab = wide_chars;
  while (*tab++)
    if (strstr (string, tab[-1]))
    {
      if (!ptrs) return ARG_LONG;
      else       return ARG_WIDE_STRING;
    }
  tab = ascii_strings;
  while (*tab++)
    if (strstr (string, tab[-1]))
    {
235 236
      if (ptrs < 2) return ARG_STRING;
      else          return ARG_POINTER;
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
    }
  tab = ascii_chars;
  while (*tab++)
    if (strstr (string, tab[-1]))
    {
      if (!ptrs) return ARG_LONG;
      else {
        if (!strstr (string, "unsigned")) /* unsigned char * => ptr */
          return ARG_STRING;
      }
    }

  if (ptrs)
    return ARG_POINTER; /* Pointer to some other type */

  /* No pointers */
  if (strstr (string, "double"))
    return ARG_DOUBLE;

256
  if (strstr (string, "float") || strstr (string, "FLOAT"))
257 258
    return ARG_FLOAT;

259
  if (strstr (string, "void") || strstr (string, "VOID"))
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
    return ARG_VOID;

  if (strstr (string, "struct") || strstr (string, "union"))
    return ARG_STRUCT; /* Struct by value, ugh */

  if (VERBOSE)
  {
    int known = 0;

    tab = known_longs;
    while (*tab++)
    if (strstr (string, tab[-1]))
    {
      known = 1;
      break;
    }
    /* Unknown types passed by value can be 'grep'ed out for fixup later */
    if (!known)
      printf ("/* FIXME: By value type: Assumed 'int' */ typedef int %s;\n",
              string);
  }
  return ARG_LONG;
}


/*******************************************************************
 *         symbol_clean_string
 *
 * Make a type string more Wine-friendly. Logically const :-)
 */
290
void  symbol_clean_string (char *str)
291
{
292
  const char * const *tab = swap_after;
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307

#define SWAP(i, p, x, y) do { i = p; while ((i = str_replace (i, x, y))); } while(0)

  while (tab [0])
  {
    char *p;
    SWAP (p, str, tab [0], tab [1]);
    tab += 2;
  }
  if (str [strlen (str) - 1] == ' ')
    str [strlen (str) - 1] = '\0'; /* no trailing space */

  if (*str == ' ')
    memmove (str, str + 1, strlen (str)); /* No leading spaces */
}