Reverse the order for deleting the items in resetcontent to correctly
[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             types_get_info(&type, TI_GET_TYPE, &type_id);
309             if (types_get_info(&type, TI_GET_TYPE, &type_id) && type_id == user->u.typeid)
310             {
311                 user->result = sym->TypeIndex;
312                 ret = FALSE;
313             }
314             break;
315         default: break;
316         }
317     }
318     return ret;
319 }
320
321 /******************************************************************
322  *              types_find_pointer
323  *
324  * Should look up in module based at linear whether (typeid*) exists
325  * Otherwise, we could create it locally
326  */
327 struct dbg_type types_find_pointer(const struct dbg_type* type)
328 {
329     struct type_find_t  f;
330     struct dbg_type     ret;
331
332     f.result = dbg_itype_none;
333     f.tag = SymTagPointerType;
334     f.u.typeid = type->id;
335     SymEnumTypes(dbg_curr_process->handle, type->module, types_cb, &f);
336     ret.module = type->module;
337     ret.id = f.result;
338     return ret;
339 }
340
341 /******************************************************************
342  *              types_find_type
343  *
344  * Should look up in the module based at linear address whether a type
345  * named 'name' and with the correct tag exists
346  */
347 struct dbg_type types_find_type(unsigned long linear, const char* name, enum SymTagEnum tag)
348
349 {
350     struct type_find_t  f;
351     struct dbg_type     ret;
352
353     f.result = dbg_itype_none;
354     f.tag = tag;
355     f.u.name = name;
356     SymEnumTypes(dbg_curr_process->handle, linear, types_cb, &f);
357     ret.module = linear;
358     ret.id = f.result;
359     return ret;
360 }
361
362 /***********************************************************************
363  *           print_value
364  *
365  * Implementation of the 'print' command.
366  */
367 void print_value(const struct dbg_lvalue* lvalue, char format, int level)
368 {
369     struct dbg_lvalue   lvalue_field;
370     int                 i;
371     DWORD               tag;
372     DWORD               count;
373     DWORD               size;
374
375     if (lvalue->type.id == dbg_itype_none)
376     {
377         /* No type, just print the addr value */
378         print_bare_address(&lvalue->addr);
379         goto leave;
380     }
381
382     if (format == 'i' || format == 's' || format == 'w' || format == 'b' || format == 'g')
383     {
384         dbg_printf("Format specifier '%c' is meaningless in 'print' command\n", format);
385         format = '\0';
386     }
387
388     if (!types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag))
389     {
390         WINE_FIXME("---error\n");
391         return;
392     }
393     switch (tag)
394     {
395     case SymTagBaseType:
396     case SymTagEnum:
397     case SymTagPointerType:
398         print_basic(lvalue, 1, format);
399         break;
400     case SymTagUDT:
401         if (types_get_info(&lvalue->type, TI_GET_CHILDRENCOUNT, &count))
402         {
403             char                        buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
404             TI_FINDCHILDREN_PARAMS*     fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
405             WCHAR*                      ptr;
406             char                        tmp[256];
407             long int                    tmpbuf;
408             struct dbg_type             type;
409
410             dbg_printf("{");
411             fcp->Start = 0;
412             while (count)
413             {
414                 fcp->Count = min(count, 256);
415                 if (types_get_info(&lvalue->type, TI_FINDCHILDREN, fcp))
416                 {
417                     for (i = 0; i < min(fcp->Count, count); i++)
418                     {
419                         ptr = NULL;
420                         type.module = lvalue->type.module;
421                         type.id = fcp->ChildId[i];
422                         types_get_info(&type, TI_GET_SYMNAME, &ptr);
423                         if (!ptr) continue;
424                         WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
425                         dbg_printf("%s=", tmp);
426                         HeapFree(GetProcessHeap(), 0, ptr);
427                         lvalue_field = *lvalue;
428                         if (types_get_udt_element_lvalue(&lvalue_field, &type, &tmpbuf))
429                         {
430                             print_value(&lvalue_field, format, level + 1);
431                         }
432                         if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
433                     }
434                 }
435                 count -= min(count, 256);
436                 fcp->Start += 256;
437             }
438             dbg_printf("}");
439         }
440         break;
441     case SymTagArrayType:
442         /*
443          * Loop over all of the entries, printing stuff as we go.
444          */
445         count = 1; size = 1;
446         types_get_info(&lvalue->type, TI_GET_COUNT, &count);
447         types_get_info(&lvalue->type, TI_GET_LENGTH, &size);
448
449         if (size == count)
450         {
451             unsigned    len;
452             char        buffer[256];
453             /*
454              * Special handling for character arrays.
455              */
456             /* FIXME should check basic type here (should be a char!!!!)... */
457             len = min(count, sizeof(buffer));
458             memory_get_string(dbg_curr_process->handle,
459                               memory_to_linear_addr(&lvalue->addr),
460                               lvalue->cookie == DLV_TARGET, TRUE, buffer, len);
461             dbg_printf("\"%s%s\"", buffer, (len < count) ? "..." : "");
462             break;
463         }
464         lvalue_field = *lvalue;
465         types_get_info(&lvalue->type, TI_GET_TYPE, &lvalue_field.type.id);
466         dbg_printf("{");
467         for (i = 0; i < count; i++)
468         {
469             print_value(&lvalue_field, format, level + 1);
470             lvalue_field.addr.Offset += size / count;
471             dbg_printf((i == count - 1) ? "}" : ", ");
472         }
473         break;
474     case SymTagFunctionType:
475         dbg_printf("Function ");
476         print_bare_address(&lvalue->addr);
477         dbg_printf(": ");
478         types_print_type(&lvalue->type, FALSE);
479         break;
480     default:
481         WINE_FIXME("Unknown tag (%lu)\n", tag);
482         RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
483         break;
484     }
485
486 leave:
487
488     if (level == 0) dbg_printf("\n");
489 }
490
491 static BOOL CALLBACK print_types_cb(PSYMBOL_INFO sym, ULONG size, void* ctx)
492 {
493     struct dbg_type     type;
494     type.module = sym->ModBase;
495     type.id = sym->TypeIndex;
496     dbg_printf("Mod: %08lx ID: %08lx \n", type.module, type.id);
497     types_print_type(&type, TRUE);
498     dbg_printf("\n");
499     return TRUE;
500 }
501
502 static BOOL CALLBACK print_types_mod_cb(PSTR mod_name, DWORD base, void* ctx)
503 {
504     return SymEnumTypes(dbg_curr_process->handle, base, print_types_cb, ctx);
505 }
506
507 int print_types(void)
508 {
509     SymEnumerateModules(dbg_curr_process->handle, print_types_mod_cb, NULL);
510     return 0;
511 }
512
513 int types_print_type(const struct dbg_type* type, BOOL details)
514 {
515     WCHAR*              ptr;
516     char                tmp[256];
517     const char*         name;
518     DWORD               tag, udt, count;
519     struct dbg_type     subtype;
520
521     if (type->id == dbg_itype_none || !types_get_info(type, TI_GET_SYMTAG, &tag))
522     {
523         dbg_printf("--invalid--<%lxh>--", type->id);
524         return FALSE;
525     }
526
527     if (types_get_info(type, TI_GET_SYMNAME, &ptr) && ptr)
528     {
529         WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
530         name = tmp;
531         HeapFree(GetProcessHeap(), 0, ptr);
532     }
533     else name = "--none--";
534
535     switch (tag)
536     {
537     case SymTagBaseType:
538         if (details) dbg_printf("Basic<%s>", name); else dbg_printf("%s", name);
539         break;
540     case SymTagPointerType:
541         types_get_info(type, TI_GET_TYPE, &subtype.id);
542         subtype.module = type->module;
543         types_print_type(&subtype, FALSE);
544         dbg_printf("*");
545         break;
546     case SymTagUDT:
547         types_get_info(type, TI_GET_UDTKIND, &udt);
548         switch (udt)
549         {
550         case UdtStruct: dbg_printf("struct %s", name); break;
551         case UdtUnion:  dbg_printf("union %s", name); break;
552         case UdtClass:  dbg_printf("class %s", name); break;
553         default:        WINE_ERR("Unsupported UDT type (%ld) for %s", udt, name); break;
554         }
555         if (details &&
556             types_get_info(type, TI_GET_CHILDRENCOUNT, &count))
557         {
558             char                        buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
559             TI_FINDCHILDREN_PARAMS*     fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
560             WCHAR*                      ptr;
561             char                        tmp[256];
562             int                         i;
563             struct dbg_type             type_elt;
564             dbg_printf(" {");
565
566             fcp->Start = 0;
567             while (count)
568             {
569                 fcp->Count = min(count, 256);
570                 if (types_get_info(type, TI_FINDCHILDREN, fcp))
571                 {
572                     for (i = 0; i < min(fcp->Count, count); i++)
573                     {
574                         ptr = NULL;
575                         type_elt.module = type->module;
576                         type_elt.id = fcp->ChildId[i];
577                         types_get_info(&type_elt, TI_GET_SYMNAME, &ptr);
578                         if (!ptr) continue;
579                         WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL);
580                         HeapFree(GetProcessHeap(), 0, ptr);
581                         dbg_printf("%s", tmp);
582                         if (types_get_info(&type_elt, TI_GET_TYPE, &type_elt.id))
583                         {
584                             dbg_printf(":");
585                             types_print_type(&type_elt, details);
586                         }
587                         if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
588                     }
589                 }
590                 count -= min(count, 256);
591                 fcp->Start += 256;
592             }
593             dbg_printf("}");
594         }
595         break;
596     case SymTagArrayType:
597         types_get_info(type, TI_GET_TYPE, &subtype.id);
598         subtype.module = type->module;
599         types_print_type(&subtype, details);
600         dbg_printf(" %s[]", name);
601         break;
602     case SymTagEnum:
603         dbg_printf("enum %s", name);
604         break;
605     case SymTagFunctionType:
606         types_get_info(type, TI_GET_TYPE, &subtype.id);
607         subtype.module = type->module;
608         types_print_type(&subtype, FALSE);
609         dbg_printf(" (*%s)(", name);
610         if (types_get_info(type, TI_GET_CHILDRENCOUNT, &count))
611         {
612             char                        buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
613             TI_FINDCHILDREN_PARAMS*     fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
614             int                         i;
615
616             fcp->Start = 0;
617             while (count)
618             {
619                 fcp->Count = min(count, 256);
620                 if (types_get_info(type, TI_FINDCHILDREN, fcp))
621                 {
622                     for (i = 0; i < min(fcp->Count, count); i++)
623                     {
624                         subtype.id = fcp->ChildId[i];
625                         types_print_type(&subtype, FALSE);
626                         if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", ");
627                     }
628                 }
629                 count -= min(count, 256);
630                 fcp->Start += 256;
631             }
632         }
633         dbg_printf(")");
634         break;
635     default:
636         WINE_ERR("Unknown type %lu for %s\n", tag, name);
637         break;
638     }
639     
640     return TRUE;
641 }
642
643 BOOL types_get_info(const struct dbg_type* type, IMAGEHLP_SYMBOL_TYPE_INFO ti, void* pInfo)
644 {
645     if (type->id == dbg_itype_none) return FALSE;
646     if (type->module != 0)
647         return SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, ti, pInfo);
648
649     assert(type->id >= dbg_itype_first);
650 /* helper to typecast pInfo to its expected type (_t) */
651 #define X(_t) (*((_t*)pInfo))
652
653     switch (type->id)
654     {
655     case dbg_itype_unsigned_int:
656         switch (ti)
657         {
658         case TI_GET_SYMTAG:     X(DWORD) = SymTagBaseType; break;
659         case TI_GET_LENGTH:     X(DWORD) = 4; break;
660         case TI_GET_BASETYPE:   X(DWORD) = btUInt; break;
661         default: WINE_FIXME("unsupported %u for u-int\n", ti); return FALSE;
662         }
663         break;
664     case dbg_itype_signed_int:
665         switch (ti)
666         {
667         case TI_GET_SYMTAG:     X(DWORD) = SymTagBaseType; break;
668         case TI_GET_LENGTH:     X(DWORD) = 4; break;
669         case TI_GET_BASETYPE:   X(DWORD) = btInt; break;
670         default: WINE_FIXME("unsupported %u for s-int\n", ti); return FALSE;
671         }
672         break;
673     case dbg_itype_unsigned_short_int:
674         switch (ti)
675         {
676         case TI_GET_SYMTAG:     X(DWORD) = SymTagBaseType; break;
677         case TI_GET_LENGTH:     X(DWORD) = 2; break;
678         case TI_GET_BASETYPE:   X(DWORD) = btUInt; break;
679         default: WINE_FIXME("unsupported %u for u-short int\n", ti); return FALSE;
680         }
681         break;
682     case dbg_itype_signed_short_int:
683         switch (ti)
684         {
685         case TI_GET_SYMTAG:     X(DWORD) = SymTagBaseType; break;
686         case TI_GET_LENGTH:     X(DWORD) = 2; break;
687         case TI_GET_BASETYPE:   X(DWORD) = btInt; break;
688         default: WINE_FIXME("unsupported %u for s-short int\n", ti); return FALSE;
689         }
690         break;
691     case dbg_itype_unsigned_char_int:
692         switch (ti)
693         {
694         case TI_GET_SYMTAG:     X(DWORD) = SymTagBaseType; break;
695         case TI_GET_LENGTH:     X(DWORD) = 1; break;
696         case TI_GET_BASETYPE:   X(DWORD) = btUInt; break;
697         default: WINE_FIXME("unsupported %u for u-char int\n", ti); return FALSE;
698         }
699         break;
700     case dbg_itype_signed_char_int:
701         switch (ti)
702         {
703         case TI_GET_SYMTAG:     X(DWORD) = SymTagBaseType; break;
704         case TI_GET_LENGTH:     X(DWORD) = 1; break;
705         case TI_GET_BASETYPE:   X(DWORD) = btInt; break;
706         default: WINE_FIXME("unsupported %u for s-char int\n", ti); return FALSE;
707         }
708         break;
709     case dbg_itype_char:
710         switch (ti)
711         {
712         case TI_GET_SYMTAG:     X(DWORD) = SymTagBaseType; break;
713         case TI_GET_LENGTH:     X(DWORD) = 1; break;
714         case TI_GET_BASETYPE:   X(DWORD) = btChar; break;
715         default: WINE_FIXME("unsupported %u for char int\n", ti); return FALSE;
716         }
717         break;
718     case dbg_itype_astring:
719         switch (ti)
720         {
721         case TI_GET_SYMTAG:     X(DWORD) = SymTagPointerType; break;
722         case TI_GET_LENGTH:     X(DWORD) = 4; break;
723         case TI_GET_TYPE:       X(DWORD) = dbg_itype_char; break;
724         default: WINE_FIXME("unsupported %u for a string\n", ti); return FALSE;
725         }
726         break;
727     default: WINE_FIXME("unsupported type id 0x%lx\n", type->id);
728     }
729
730 #undef X
731     return TRUE;
732 }