- now storing exception info (if any) in thread structure
[wine] / programs / winedbg / types.c
1 /*
2  * File types.c - datatype handling stuff for internal debugger.
3  *
4  * Copyright (C) 1997, Eric Youngdale.
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * Note: This really doesn't do much at the moment, but it forms the framework
21  * upon which full support for datatype handling will eventually be built.
22  */
23
24 #include "config.h"
25 #include <stdlib.h>
26
27 #include "debugger.h"
28 #include "wine/debug.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
31
32 /******************************************************************
33  *              types_extract_as_integer
34  *
35  * Given a lvalue, try to get an integral (or pointer/address) value
36  * out of it
37  */
38 long int types_extract_as_integer(const struct dbg_lvalue* lvalue)
39 {
40     long int            rtn = 0;
41     DWORD               tag, size, bt;
42
43     if (lvalue->type.id == dbg_itype_none ||
44         !types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag))
45         return 0;
46
47     switch (tag)
48     {
49     case SymTagBaseType:
50         if (!types_get_info(&lvalue->type, TI_GET_LENGTH, &size) ||
51             !types_get_info(&lvalue->type, TI_GET_BASETYPE, &bt))
52         {
53             WINE_ERR("Couldn't get information\n");
54             RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
55         }
56         if (size > sizeof(rtn))
57         {
58             WINE_ERR("Size too large (%lu)\n", size);
59             return 0;
60         }
61         /* FIXME: we have an ugly & non portable thing here !!! */
62         if (!memory_read_value(lvalue, size, &rtn)) return 0;
63
64         /* now let's do some promotions !! */
65         switch (bt)
66         {
67         case btInt:
68             /* propagate sign information */
69             if (((size & 3) != 0) && (rtn >> (size * 8 - 1)) != 0)
70                 rtn |= (-1) << (size * 8);
71             break;
72         case btUInt:
73         case btChar:
74             break;
75         case btFloat:
76             RaiseException(DEBUG_STATUS_NOT_AN_INTEGER, 0, 0, NULL);
77         }
78         break;
79     case SymTagPointerType:
80         if (!memory_read_value(lvalue, sizeof(void*), &rtn)) return 0;
81         break;
82     case SymTagArrayType:
83     case SymTagUDT:
84         assert(lvalue->cookie == DLV_TARGET);
85         if (!memory_read_value(lvalue, sizeof(rtn), &rtn)) return 0;
86         break;
87     case SymTagEnum:
88         assert(lvalue->cookie == DLV_TARGET);
89         if (!memory_read_value(lvalue, sizeof(rtn), &rtn)) return 0;
90         break;
91     default:
92         WINE_FIXME("Unsupported tag %lu\n", tag);
93         rtn = 0;
94         break;
95     }
96
97     return rtn;
98 }
99
100 /******************************************************************
101  *              types_deref
102  *
103  */
104 BOOL types_deref(const struct dbg_lvalue* lvalue, struct dbg_lvalue* result)
105 {
106     DWORD       tag;
107
108     memset(result, 0, sizeof(*result));
109     result->type.id = dbg_itype_none;
110     result->type.module = 0;
111
112     /*
113      * Make sure that this really makes sense.
114      */
115     if (!types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag) ||
116         tag != SymTagPointerType ||
117         !memory_read_value(lvalue, sizeof(result->addr.Offset), &result->addr.Offset) ||
118         !types_get_info(&lvalue->type, TI_GET_TYPE, &result->type.id))
119         return FALSE;
120     result->type.module = lvalue->type.module;
121     result->cookie = DLV_TARGET;
122     /* FIXME: this is currently buggy.
123      * there is no way to tell were the deref:ed value is...
124      * for example:
125      *  x is a pointer to struct s, x being on the stack
126      *          => lvalue is in debuggee, result is in debugger
127      *  x is a pointer to struct s, x being optimized into a reg
128      *          => lvalue is debugger, result is debuggee
129      *  x is a pointer to internal variable x
130      *          => lvalue is debugger, result is debuggee
131      * so we force debuggee address space, because dereferencing pointers to
132      * internal variables is very unlikely. A correct fix would be
133      * rather large.
134      */
135     result->addr.Mode = AddrModeFlat;
136     return TRUE;
137 }
138
139 /******************************************************************
140  *              types_get_udt_element_lvalue
141  *
142  * Implement a structure derefencement
143  */
144 static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue, 
145                                          const struct dbg_type* type, long int* tmpbuf)
146 {
147     DWORD       offset, length, bitoffset;
148     DWORD       bt;
149     unsigned    mask;
150
151     types_get_info(type, TI_GET_TYPE, &lvalue->type.id);
152     lvalue->type.module = type->module;
153     types_get_info(type, TI_GET_OFFSET, &offset);
154
155     if (types_get_info(type, TI_GET_BITPOSITION, &bitoffset))
156     {
157         if (!types_get_info(type, TI_GET_LENGTH, &length) ||
158             length > sizeof(*tmpbuf))
159             return FALSE;
160         /*
161          * Bitfield operation.  We have to extract the field and store
162          * it in a temporary buffer so that we get it all right.
163          */
164         lvalue->addr.Offset += offset;
165         if (!memory_read_value(lvalue, sizeof(*tmpbuf), tmpbuf)) return FALSE;
166         mask = 0xffffffff << length;
167         *tmpbuf >>= bitoffset & 7;
168         *tmpbuf &= ~mask;
169
170         lvalue->cookie      = DLV_HOST;
171         lvalue->addr.Offset = (DWORD)tmpbuf;
172
173         /*
174          * OK, now we have the correct part of the number.
175          * Check to see whether the basic type is signed or not, and if so,
176          * we need to sign extend the number.
177          */
178         if (types_get_info(&lvalue->type, TI_GET_BASETYPE, &bt) && 
179             bt == btInt && (*tmpbuf & (1 << (length - 1))))
180         {
181             *tmpbuf |= mask;
182         }
183         return TRUE;
184     }
185     if (types_get_info(type, TI_GET_OFFSET, &offset))
186     {
187         lvalue->addr.Offset += offset;
188         return TRUE;
189     }
190     return FALSE;
191 }
192
193 /******************************************************************
194  *              types_udt_find_element
195  *
196  */
197 BOOL types_udt_find_element(struct dbg_lvalue* lvalue, const char* name, long int* tmpbuf)
198 {
199     DWORD                       tag, count;
200     char                        buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
201     TI_FINDCHILDREN_PARAMS*     fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
202     WCHAR*                      ptr;
203     char                        tmp[256];
204     int                         i;
205     struct dbg_type             type;
206
207     if (!types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag) ||
208         tag != SymTagUDT)
209         return FALSE;
210
211     if (types_get_info(&lvalue->type, TI_GET_CHILDRENCOUNT, &count))
212     {
213         fcp->Start = 0;
214         while (count)
215         {
216             fcp->Count = min(count, 256);
217             if (types_get_info(&lvalue->type, TI_FINDCHILDREN, fcp))
218             {
219                 type.module = lvalue->type.module;
220                 for (i = 0; i < min(fcp->Count, count); i++)
221                 {
222                     ptr = NULL;
223                     type.id = fcp->ChildId[i];
224                     types_get_info(&type, TI_GET_SYMNAME, &ptr);
225                     if (!ptr) continue;
226                     WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
227                     HeapFree(GetProcessHeap(), 0, ptr);
228                     if (strcmp(tmp, name)) continue;
229
230                     return types_get_udt_element_lvalue(lvalue, &type, tmpbuf);
231                 }
232             }
233             count -= min(count, 256);
234             fcp->Start += 256;
235         }
236     }
237     return FALSE;
238 }
239
240 /******************************************************************
241  *              types_array_index
242  *
243  * Grab an element from an array
244  */
245 BOOL types_array_index(const struct dbg_lvalue* lvalue, int index, 
246                        struct dbg_lvalue* result)
247 {
248     DWORD       tag, length, count;
249
250     if (!types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag))
251         return FALSE;
252     switch (tag)
253     {
254     case SymTagArrayType:
255         types_get_info(&lvalue->type, TI_GET_COUNT, &count);
256         if (index < 0 || index >= count) return FALSE;
257         /* fall through */
258     case SymTagPointerType:
259         /*
260          * Get the base type, so we know how much to index by.
261          */
262         types_get_info(&lvalue->type, TI_GET_TYPE, &result->type.id);
263         result->type.module = lvalue->type.module;
264         types_get_info(&result->type, TI_GET_LENGTH, &length);
265         /* Contents of array must be on same target */
266         result->addr.Mode = lvalue->addr.Mode;
267         memory_read_value(lvalue, sizeof(result->addr.Offset), &result->addr.Offset);
268         result->addr.Offset += index * length;
269         break;
270     default:
271         assert(FALSE);
272     }
273     return TRUE;
274 }
275
276 struct type_find_t
277 {
278     unsigned long       result; /* out: the found type */
279     enum SymTagEnum     tag;    /* in: the tag to look for */
280     union
281     {
282         unsigned long           typeid; /* when tag is SymTagUDT */
283         const char*             name;   /* when tag is SymTagPointerType */
284     } u;
285 };
286
287 static BOOL CALLBACK types_cb(PSYMBOL_INFO sym, ULONG size, void* _user)
288 {
289     struct type_find_t* user = (struct type_find_t*)_user;
290     BOOL                ret = TRUE;
291     struct dbg_type     type;
292     DWORD               type_id;
293
294     if (sym->Tag == user->tag)
295     {
296         switch (user->tag)
297         {
298         case SymTagUDT:
299             if (!strcmp(user->u.name, sym->Name))
300             {
301                 user->result = sym->TypeIndex;
302                 ret = FALSE;
303             }
304             break;
305         case SymTagPointerType:
306             type.module = sym->ModBase;
307             type.id = sym->TypeIndex;
308             if (types_get_info(&type, TI_GET_TYPE, &type_id) && type_id == user->u.typeid)
309             {
310                 user->result = sym->TypeIndex;
311                 ret = FALSE;
312             }
313             break;
314         default: break;
315         }
316     }
317     return ret;
318 }
319
320 /******************************************************************
321  *              types_find_pointer
322  *
323  * Should look up in module based at linear whether (typeid*) exists
324  * Otherwise, we could create it locally
325  */
326 struct dbg_type types_find_pointer(const struct dbg_type* type)
327 {
328     struct type_find_t  f;
329     struct dbg_type     ret;
330
331     f.result = dbg_itype_none;
332     f.tag = SymTagPointerType;
333     f.u.typeid = type->id;
334     SymEnumTypes(dbg_curr_process->handle, type->module, types_cb, &f);
335     ret.module = type->module;
336     ret.id = f.result;
337     return ret;
338 }
339
340 /******************************************************************
341  *              types_find_type
342  *
343  * Should look up in the module based at linear address whether a type
344  * named 'name' and with the correct tag exists
345  */
346 struct dbg_type types_find_type(unsigned long linear, const char* name, enum SymTagEnum tag)
347
348 {
349     struct type_find_t  f;
350     struct dbg_type     ret;
351
352     f.result = dbg_itype_none;
353     f.tag = tag;
354     f.u.name = name;
355     SymEnumTypes(dbg_curr_process->handle, linear, types_cb, &f);
356     ret.module = linear;
357     ret.id = f.result;
358     return ret;
359 }
360
361 /***********************************************************************
362  *           print_value
363  *
364  * Implementation of the 'print' command.
365  */
366 void print_value(const struct dbg_lvalue* lvalue, char format, int level)
367 {
368     struct dbg_lvalue   lvalue_field;
369     int                 i;
370     DWORD               tag;
371     DWORD               count;
372     DWORD               size;
373
374     if (lvalue->type.id == dbg_itype_none)
375     {
376         /* No type, just print the addr value */
377         print_bare_address(&lvalue->addr);
378         goto leave;
379     }
380
381     if (format == 'i' || format == 's' || format == 'w' || format == 'b' || format == 'g')
382     {
383         dbg_printf("Format specifier '%c' is meaningless in 'print' command\n", format);
384         format = '\0';
385     }
386
387     if (!types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag))
388     {
389         WINE_FIXME("---error\n");
390         return;
391     }
392     switch (tag)
393     {
394     case SymTagBaseType:
395     case SymTagEnum:
396     case SymTagPointerType:
397         print_basic(lvalue, 1, format);
398         break;
399     case SymTagUDT:
400         if (types_get_info(&lvalue->type, TI_GET_CHILDRENCOUNT, &count))
401         {
402             char                        buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
403             TI_FINDCHILDREN_PARAMS*     fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
404             WCHAR*                      ptr;
405             char                        tmp[256];
406             long int                    tmpbuf;
407             struct dbg_type             type;
408
409             dbg_printf("{");
410             fcp->Start = 0;
411             while (count)
412             {
413                 fcp->Count = min(count, 256);
414                 if (types_get_info(&lvalue->type, TI_FINDCHILDREN, fcp))
415                 {
416                     for (i = 0; i < min(fcp->Count, count); i++)
417                     {
418                         ptr = NULL;
419                         type.module = lvalue->type.module;
420                         type.id = fcp->ChildId[i];
421                         types_get_info(&type, TI_GET_SYMNAME, &ptr);
422                         if (!ptr) continue;
423                         WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
424                         dbg_printf("%s=", tmp);
425                         HeapFree(GetProcessHeap(), 0, ptr);
426                         lvalue_field = *lvalue;
427                         if (types_get_udt_element_lvalue(&lvalue_field, &type, &tmpbuf))
428                         {
429                             print_value(&lvalue_field, format, level + 1);
430                         }
431                         if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
432                     }
433                 }
434                 count -= min(count, 256);
435                 fcp->Start += 256;
436             }
437             dbg_printf("}");
438         }
439         break;
440     case SymTagArrayType:
441         /*
442          * Loop over all of the entries, printing stuff as we go.
443          */
444         count = 1; size = 1;
445         types_get_info(&lvalue->type, TI_GET_COUNT, &count);
446         types_get_info(&lvalue->type, TI_GET_LENGTH, &size);
447
448         if (size == count)
449         {
450             unsigned    len;
451             char        buffer[256];
452             /*
453              * Special handling for character arrays.
454              */
455             /* FIXME should check basic type here (should be a char!!!!)... */
456             len = min(count, sizeof(buffer));
457             memory_get_string(dbg_curr_process->handle,
458                               memory_to_linear_addr(&lvalue->addr),
459                               lvalue->cookie == DLV_TARGET, TRUE, buffer, len);
460             dbg_printf("\"%s%s\"", buffer, (len < count) ? "..." : "");
461             break;
462         }
463         lvalue_field = *lvalue;
464         types_get_info(&lvalue->type, TI_GET_TYPE, &lvalue_field.type.id);
465         dbg_printf("{");
466         for (i = 0; i < count; i++)
467         {
468             print_value(&lvalue_field, format, level + 1);
469             lvalue_field.addr.Offset += size / count;
470             dbg_printf((i == count - 1) ? "}" : ", ");
471         }
472         break;
473     case SymTagFunctionType:
474         dbg_printf("Function ");
475         print_bare_address(&lvalue->addr);
476         dbg_printf(": ");
477         types_print_type(&lvalue->type, FALSE);
478         break;
479     default:
480         WINE_FIXME("Unknown tag (%lu)\n", tag);
481         RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
482         break;
483     }
484
485 leave:
486
487     if (level == 0) dbg_printf("\n");
488 }
489
490 static BOOL CALLBACK print_types_cb(PSYMBOL_INFO sym, ULONG size, void* ctx)
491 {
492     struct dbg_type     type;
493     type.module = sym->ModBase;
494     type.id = sym->TypeIndex;
495     dbg_printf("Mod: %08lx ID: %08lx \n", type.module, type.id);
496     types_print_type(&type, TRUE);
497     dbg_printf("\n");
498     return TRUE;
499 }
500
501 static BOOL CALLBACK print_types_mod_cb(PSTR mod_name, DWORD base, void* ctx)
502 {
503     return SymEnumTypes(dbg_curr_process->handle, base, print_types_cb, ctx);
504 }
505
506 int print_types(void)
507 {
508     SymEnumerateModules(dbg_curr_process->handle, print_types_mod_cb, NULL);
509     return 0;
510 }
511
512 int types_print_type(const struct dbg_type* type, BOOL details)
513 {
514     WCHAR*              ptr;
515     char                tmp[256];
516     const char*         name;
517     DWORD               tag, udt, count;
518     struct dbg_type     subtype;
519
520     if (type->id == dbg_itype_none || !types_get_info(type, TI_GET_SYMTAG, &tag))
521     {
522         dbg_printf("--invalid--<%lxh>--", type->id);
523         return FALSE;
524     }
525
526     if (types_get_info(type, TI_GET_SYMNAME, &ptr) && ptr)
527     {
528         WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
529         name = tmp;
530         HeapFree(GetProcessHeap(), 0, ptr);
531     }
532     else name = "--none--";
533
534     switch (tag)
535     {
536     case SymTagBaseType:
537         if (details) dbg_printf("Basic<%s>", name); else dbg_printf("%s", name);
538         break;
539     case SymTagPointerType:
540         types_get_info(type, TI_GET_TYPE, &subtype.id);
541         subtype.module = type->module;
542         types_print_type(&subtype, FALSE);
543         dbg_printf("*");
544         break;
545     case SymTagUDT:
546         types_get_info(type, TI_GET_UDTKIND, &udt);
547         switch (udt)
548         {
549         case UdtStruct: dbg_printf("struct %s", name); break;
550         case UdtUnion:  dbg_printf("union %s", name); break;
551         case UdtClass:  dbg_printf("class %s", name); break;
552         default:        WINE_ERR("Unsupported UDT type (%ld) for %s", udt, name); break;
553         }
554         if (details &&
555             types_get_info(type, TI_GET_CHILDRENCOUNT, &count))
556         {
557             char                        buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
558             TI_FINDCHILDREN_PARAMS*     fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
559             WCHAR*                      ptr;
560             char                        tmp[256];
561             int                         i;
562             struct dbg_type             type_elt;
563             dbg_printf(" {");
564
565             fcp->Start = 0;
566             while (count)
567             {
568                 fcp->Count = min(count, 256);
569                 if (types_get_info(type, TI_FINDCHILDREN, fcp))
570                 {
571                     for (i = 0; i < min(fcp->Count, count); i++)
572                     {
573                         ptr = NULL;
574                         type_elt.module = type->module;
575                         type_elt.id = fcp->ChildId[i];
576                         types_get_info(&type_elt, TI_GET_SYMNAME, &ptr);
577                         if (!ptr) continue;
578                         WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
579                         HeapFree(GetProcessHeap(), 0, ptr);
580                         dbg_printf("%s", tmp);
581                         if (types_get_info(&type_elt, TI_GET_TYPE, &type_elt.id))
582                         {
583                             dbg_printf(":");
584                             types_print_type(&type_elt, details);
585                         }
586                         if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
587                     }
588                 }
589                 count -= min(count, 256);
590                 fcp->Start += 256;
591             }
592             dbg_printf("}");
593         }
594         break;
595     case SymTagArrayType:
596         types_get_info(type, TI_GET_TYPE, &subtype.id);
597         subtype.module = type->module;
598         types_print_type(&subtype, details);
599         dbg_printf(" %s[]", name);
600         break;
601     case SymTagEnum:
602         dbg_printf("enum %s", name);
603         break;
604     case SymTagFunctionType:
605         types_get_info(type, TI_GET_TYPE, &subtype.id);
606         subtype.module = type->module;
607         types_print_type(&subtype, FALSE);
608         dbg_printf(" (*%s)(", name);
609         if (types_get_info(type, TI_GET_CHILDRENCOUNT, &count))
610         {
611             char                        buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
612             TI_FINDCHILDREN_PARAMS*     fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
613             int                         i;
614
615             fcp->Start = 0;
616             while (count)
617             {
618                 fcp->Count = min(count, 256);
619                 if (types_get_info(type, TI_FINDCHILDREN, fcp))
620                 {
621                     for (i = 0; i < min(fcp->Count, count); i++)
622                     {
623                         subtype.id = fcp->ChildId[i];
624                         types_print_type(&subtype, FALSE);
625                         if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
626                     }
627                 }
628                 count -= min(count, 256);
629                 fcp->Start += 256;
630             }
631         }
632         dbg_printf(")");
633         break;
634     default:
635         WINE_ERR("Unknown type %lu for %s\n", tag, name);
636         break;
637     }
638     
639     return TRUE;
640 }
641
642 BOOL types_get_info(const struct dbg_type* type, IMAGEHLP_SYMBOL_TYPE_INFO ti, void* pInfo)
643 {
644     if (type->id == dbg_itype_none) return FALSE;
645     if (type->module != 0)
646         return SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, ti, pInfo);
647
648     assert(type->id >= dbg_itype_first);
649 /* helper to typecast pInfo to its expected type (_t) */
650 #define X(_t) (*((_t*)pInfo))
651
652     switch (type->id)
653     {
654     case dbg_itype_unsigned_int:
655         switch (ti)
656         {
657         case TI_GET_SYMTAG:     X(DWORD) = SymTagBaseType; break;
658         case TI_GET_LENGTH:     X(DWORD) = 4; break;
659         case TI_GET_BASETYPE:   X(DWORD) = btUInt; break;
660         default: WINE_FIXME("unsupported %u for u-int\n", ti); return FALSE;
661         }
662         break;
663     case dbg_itype_signed_int:
664         switch (ti)
665         {
666         case TI_GET_SYMTAG:     X(DWORD) = SymTagBaseType; break;
667         case TI_GET_LENGTH:     X(DWORD) = 4; break;
668         case TI_GET_BASETYPE:   X(DWORD) = btInt; break;
669         default: WINE_FIXME("unsupported %u for s-int\n", ti); return FALSE;
670         }
671         break;
672     case dbg_itype_unsigned_short_int:
673         switch (ti)
674         {
675         case TI_GET_SYMTAG:     X(DWORD) = SymTagBaseType; break;
676         case TI_GET_LENGTH:     X(DWORD) = 2; break;
677         case TI_GET_BASETYPE:   X(DWORD) = btUInt; break;
678         default: WINE_FIXME("unsupported %u for u-short int\n", ti); return FALSE;
679         }
680         break;
681     case dbg_itype_signed_short_int:
682         switch (ti)
683         {
684         case TI_GET_SYMTAG:     X(DWORD) = SymTagBaseType; break;
685         case TI_GET_LENGTH:     X(DWORD) = 2; break;
686         case TI_GET_BASETYPE:   X(DWORD) = btInt; break;
687         default: WINE_FIXME("unsupported %u for s-short int\n", ti); return FALSE;
688         }
689         break;
690     case dbg_itype_unsigned_char_int:
691         switch (ti)
692         {
693         case TI_GET_SYMTAG:     X(DWORD) = SymTagBaseType; break;
694         case TI_GET_LENGTH:     X(DWORD) = 1; break;
695         case TI_GET_BASETYPE:   X(DWORD) = btUInt; break;
696         default: WINE_FIXME("unsupported %u for u-char int\n", ti); return FALSE;
697         }
698         break;
699     case dbg_itype_signed_char_int:
700         switch (ti)
701         {
702         case TI_GET_SYMTAG:     X(DWORD) = SymTagBaseType; break;
703         case TI_GET_LENGTH:     X(DWORD) = 1; break;
704         case TI_GET_BASETYPE:   X(DWORD) = btInt; break;
705         default: WINE_FIXME("unsupported %u for s-char int\n", ti); return FALSE;
706         }
707         break;
708     case dbg_itype_char:
709         switch (ti)
710         {
711         case TI_GET_SYMTAG:     X(DWORD) = SymTagBaseType; break;
712         case TI_GET_LENGTH:     X(DWORD) = 1; break;
713         case TI_GET_BASETYPE:   X(DWORD) = btChar; break;
714         default: WINE_FIXME("unsupported %u for char int\n", ti); return FALSE;
715         }
716         break;
717     case dbg_itype_astring:
718         switch (ti)
719         {
720         case TI_GET_SYMTAG:     X(DWORD) = SymTagPointerType; break;
721         case TI_GET_LENGTH:     X(DWORD) = 4; break;
722         case TI_GET_TYPE:       X(DWORD) = dbg_itype_char; break;
723         default: WINE_FIXME("unsupported %u for a string\n", ti); return FALSE;
724         }
725         break;
726     default: WINE_FIXME("unsupported type id 0x%lx\n", type->id);
727     }
728
729 #undef X
730     return TRUE;
731 }