- implemented support for function debug start/stop and labels (msc.c
  and stabs.c)
- started implementing typedef support
- functions now have a real function signature (only in stabs.c, still
  to be done in msc.c)
- small enhancements to TI_GET_TYPE for functions
- added support for functions' block and local variables in registers
  (msc.c)
- fixed some bugs in StackWalk
- constants are now stored as variants (instead of unsigned ints)
- fixed regular expression management (dbghelp's RE are not the same
  as POSIX ones)

diff --git a/dlls/dbghelp/dbghelp.c b/dlls/dbghelp/dbghelp.c
index ca90828..3ee317b 100644
--- a/dlls/dbghelp/dbghelp.c
+++ b/dlls/dbghelp/dbghelp.c
@@ -29,22 +29,21 @@
 
 /* TODO
  *  - support for symbols' types is still partly missing
- *      + debug start/stop in functions
- *      + parameters in function prototype...
  *      + C++ support
+ *      + funcargtype:s are (partly) wrong: they should be a specific struct (like
+ *        typedef) pointing to the actual type (and not a direct access)
+ *      + we should store the underlying type for an enum in the symt_enum struct
  *  - most options (dbghelp_options) are not used (loading lines, decoration, 
  *    deferring reading of module symbols, public symbols...)
  *  - (un)decoration is not handled (should make winedump's code a (.a) library
  *    and link it to winedump, and potentially to msvcrt and dbghelp (check best
  *    way not to duplicate code in msvcrt & dbghelp)
  *  - msc:
- *      + handle the debug_start & debug_end information block
+ *      + we should add parameters' types to the function's signature
+ *        while processing a function's parameters
  *      + get rid of MSC reading FIXME:s (lots of types are not defined)
  *      + C++ management
  *  - stabs: 
- *      + we should add parameters' types to the function's signature
- *        while processing a function's parameters
- *      + should generate the func debug_{start,end} statements (black magic ?)
  *      + should identify the relay code in Wine and mark it as thunk type
  *      + C++ management
  *  - implement the callback notification mechanism
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h
index ebf5988..d5f3710 100644
--- a/dlls/dbghelp/dbghelp_private.h
+++ b/dlls/dbghelp/dbghelp_private.h
@@ -26,6 +26,7 @@
 #include "winbase.h"
 #include "winver.h"
 #include "dbghelp.h"
+#include "oaidl.h"
 
 #include "cvconst.h"
 
@@ -142,11 +143,7 @@
             unsigned                    position;
             unsigned                    length;
         } bitfield;                             /* used by BitField */
-#if 1   
-        unsigned                value;          /* LocIsConstant */
-#else   
         VARIANT                 value;          /* LocIsConstant */
-#endif
     } u;
 };
 
@@ -159,7 +156,15 @@
     struct symt*                type;           /* points to function_signature */
     unsigned long               size;
     struct vector               vlines;
-    struct vector               vchildren;      /* locals, params, blocks */
+    struct vector               vchildren;      /* locals, params, blocks, start/end, labels */
+};
+
+struct symt_function_point
+{
+    struct symt                 symt;           /* either SymTagFunctionDebugStart, SymTagFunctionDebugEnd, SymTagLabel */
+    struct symt_function*       parent;
+    unsigned long               offset;
+    const char*                 name;           /* for labels */
 };
 
 struct symt_public
@@ -201,6 +206,7 @@
 {
     struct symt                 symt;
     struct symt*                rettype;
+    struct vector               vchildren;
 };
 
 struct symt_pointer
@@ -367,11 +373,21 @@
 extern struct symt_block*
                     symt_open_func_block(struct module* module, 
                                          struct symt_function* func,
-                                         struct symt_block* block, unsigned pc);
+                                         struct symt_block* block, 
+                                         unsigned pc, unsigned len);
 extern struct symt_block*
                     symt_close_func_block(struct module* module, 
                                           struct symt_function* func,
                                           struct symt_block* block, unsigned pc);
+extern struct symt_function_point*
+                    symt_add_function_point(struct module* module, 
+                                            struct symt_function* func,
+                                            enum SymTagEnum point, 
+                                            unsigned offset, const char* name);
+extern BOOL         symt_fill_func_line_info(struct module* module,
+                                             struct symt_function* func, 
+                                             DWORD addr, IMAGEHLP_LINE* line);
+extern BOOL         symt_get_func_line_next(struct module* module, PIMAGEHLP_LINE line);
 
 /* type.c */
 extern void         symt_init_basic(struct module* module);
@@ -394,13 +410,19 @@
                     symt_new_enum(struct module* module, const char* typename);
 extern BOOL         symt_add_enum_element(struct module* module, 
                                           struct symt_enum* enum_type, 
-                                          const char* name, unsigned value);
+                                          const char* name, int value);
 extern struct symt_array*
                     symt_new_array(struct module* module, int min, int max, 
                                    struct symt* base);
 extern struct symt_function_signature*
                     symt_new_function_signature(struct module* module, 
                                                 struct symt* ret_type);
+extern BOOL         symt_add_function_signature_parameter(struct module* module,
+                                                          struct symt_function_signature* sig,
+                                                          struct symt* param);
 extern struct symt_pointer*
                     symt_new_pointer(struct module* module, 
                                      struct symt* ref_type);
+extern struct symt_typedef*
+                    symt_new_typedef(struct module* module, struct symt* ref, 
+                                     const char* name);
diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c
index 1f3b394..e1d719e 100644
--- a/dlls/dbghelp/msc.c
+++ b/dlls/dbghelp/msc.c
@@ -1068,7 +1068,7 @@
     cv_basic_types[T_SHORT]  = &symt_new_basic(module, btInt,   "short int", 2)->symt;
     cv_basic_types[T_LONG]   = &symt_new_basic(module, btInt,   "long int", 4)->symt;
     cv_basic_types[T_QUAD]   = &symt_new_basic(module, btInt,   "long long int", 8)->symt;
-    cv_basic_types[T_UCHAR]  = &symt_new_basic(module, btUInt,  "unsignd char", 1)->symt;
+    cv_basic_types[T_UCHAR]  = &symt_new_basic(module, btUInt,  "unsigned char", 1)->symt;
     cv_basic_types[T_USHORT] = &symt_new_basic(module, btUInt,  "unsigned short", 2)->symt;
     cv_basic_types[T_ULONG]  = &symt_new_basic(module, btUInt,  "unsigned long", 4)->symt;
     cv_basic_types[T_UQUAD]  = &symt_new_basic(module, btUInt,  "unsigned long long", 8)->symt;
@@ -1937,9 +1937,9 @@
 
     struct
     {
-	short int	len;	/* Total length of this entry */
-	short int	id;		/* Always S_BPREL32 */
-	unsigned int	offset;	/* Stack offset relative to BP */
+	short int	len;	        /* Total length of this entry */
+	short int	id;		/* Always S_BPREL */
+	unsigned int	offset;	        /* Stack offset relative to BP */
 	unsigned short	symtype;
 	unsigned char	namelen;
 	unsigned char	name[1];
@@ -1947,13 +1947,101 @@
 
     struct
     {
-	short int	len;	/* Total length of this entry */
-	short int	id;		/* Always S_BPREL32 */
-	unsigned int	offset;	/* Stack offset relative to BP */
+	short int	len;	        /* Total length of this entry */
+	short int	id;		/* Always S_BPREL_32 */
+	unsigned int	offset;	        /* Stack offset relative to EBP */
 	unsigned int	symtype;
 	unsigned char	namelen;
 	unsigned char	name[1];
     } stack32;
+
+    struct
+    {
+	short int	len;	        /* Total length of this entry */
+	short int	id;		/* Always S_REGISTER */
+        unsigned short  type;
+        unsigned short  reg;
+	unsigned char	namelen;
+	unsigned char	name[1];
+        /* don't handle register tracking */
+    } s_register;
+
+    struct
+    {
+	short int	len;	        /* Total length of this entry */
+	short int	id;		/* Always S_REGISTER_32 */
+        unsigned int    type;           /* check whether type & reg are correct */
+        unsigned int    reg;
+	unsigned char	namelen;
+	unsigned char	name[1];
+        /* don't handle register tracking */
+    } s_register32;
+
+    struct
+    {
+        short int       len;
+        short int       id;
+        unsigned int    parent;
+        unsigned int    end;
+        unsigned int    length;
+        unsigned int    offset;
+        unsigned short  segment;
+        unsigned char   namelen;
+        unsigned char   name[1];
+    } block;
+
+    struct
+    {
+        short int       len;
+        short int       id;
+        unsigned int    offset;
+        unsigned short  segment;
+        unsigned char   flags;
+        unsigned char   namelen;
+        unsigned char   name[1];
+    } label;
+
+    struct
+    {
+        short int       len;
+        short int       id;
+        unsigned short  type;
+        unsigned short  arrlen;         /* numeric leaf */
+#if 0
+        unsigned char   namelen;
+        unsigned char   name[1];
+#endif
+    } constant;
+
+    struct
+    {
+        short int       len;
+        short int       id;
+        unsigned        type;
+        unsigned short  arrlen;         /* numeric leaf */
+#if 0
+        unsigned char   namelen;
+        unsigned char   name[1];
+#endif
+    } constant32;
+
+    struct
+    {
+        short int       len;
+        short int       id;
+        unsigned short  type;
+        unsigned char   namelen;
+        unsigned char   name[1];
+    } udt;
+
+    struct
+    {
+        short int       len;
+        short int       id;
+        unsigned        type;
+        unsigned char   namelen;
+        unsigned char   name[1];
+    } udt32;
 };
 
 #define S_COMPILE       0x0001
@@ -1997,7 +2085,6 @@
 #define S_UDT_32        0x1003
 #define S_COBOLUDT_32   0x1004
 #define S_MANYREG_32    0x1005
-
 #define S_BPREL_32      0x1006
 #define S_LDATA_32      0x1007
 #define S_GDATA_32      0x1008
@@ -2081,6 +2168,8 @@
     int                                 i, length;
     char                                symname[PATH_MAX];
     const struct codeview_linetab*      flt;
+    struct symt_block*                  block = NULL;
+    struct symt*                        symt;
 
     /*
      * Loop over the different types of records and whenever we
@@ -2102,13 +2191,9 @@
             memcpy(symname, sym->data.name, sym->data.namelen);
             symname[sym->data.namelen] = '\0';
             flt = codeview_get_linetab(linetab, sym->data.seg, sym->data.offset);
-            /* global data should be the only one of type global var...
-             * the other ones sound different
-             * FIXME
-             */
             symt_new_global_variable(msc_dbg->module, 
                                      flt ? flt->compiland : NULL,
-                                     symname, sym->generic.id == S_GDATA,
+                                     symname, sym->generic.id == S_LDATA,
                                      codeview_get_address(msc_dbg, sym->data.seg, sym->data.offset),
                                      0,
                                      codeview_get_type(sym->data.symtype, FALSE));
@@ -2119,12 +2204,8 @@
             memcpy(symname, sym->data32.name, sym->data32.namelen);
             symname[sym->data32.namelen] = '\0';
             flt = codeview_get_linetab(linetab, sym->data32.seg, sym->data32.offset);
-            /* global data should be the only one of type global var...
-             * the other ones sound different
-             * FIXME
-             */
             symt_new_global_variable(msc_dbg->module, flt ? flt->compiland : NULL,
-                                     symname, sym->generic.id == S_GDATA_32,
+                                     symname, sym->generic.id == S_LDATA_32,
                                      codeview_get_address(msc_dbg, sym->data32.seg, sym->data32.offset),
                                      0,
                                      codeview_get_type(sym->data32.symtype, FALSE));
@@ -2171,8 +2252,6 @@
          */
 	case S_GPROC:
 	case S_LPROC:
- 	    if (curr_func) symt_normalize_function(msc_dbg->module, curr_func);
-
             memcpy(symname, sym->proc.name, sym->proc.namelen);
             symname[sym->proc.namelen] = '\0';
             flt = codeview_get_linetab(linetab, sym->proc.segment, sym->proc.offset);
@@ -2181,15 +2260,13 @@
                                           codeview_get_address(msc_dbg, sym->proc.segment, sym->proc.offset),
                                           sym->proc.proc_len,
                                           codeview_get_type(sym->proc.proctype, FALSE));
-
             codeview_add_func_linenum(msc_dbg->module, curr_func, flt, 
                                       sym->proc.offset, sym->proc.proc_len);
-            /* DEBUG_SetSymbolBPOff(curr_func, sym->proc.debug_start); */
+            symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugStart, sym->proc.debug_start, NULL);
+            symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugEnd, sym->proc.debug_end, NULL);
 	    break;
 	case S_GPROC_32:
 	case S_LPROC_32:
- 	    if (curr_func) symt_normalize_function(msc_dbg->module, curr_func);
-
             memcpy(symname, sym->proc32.name, sym->proc32.namelen);
             symname[sym->proc32.namelen] = '\0';
             flt = codeview_get_linetab(linetab, sym->proc32.segment, sym->proc32.offset);
@@ -2198,10 +2275,10 @@
                                           codeview_get_address(msc_dbg, sym->proc32.segment, sym->proc32.offset),
                                           sym->proc32.proc_len,
                                           codeview_get_type(sym->proc32.proctype, FALSE));
-
             codeview_add_func_linenum(msc_dbg->module, curr_func, flt, 
                                       sym->proc32.offset, sym->proc32.proc_len);
-            /* DEBUG_SetSymbolBPOff(curr_func, sym->proc32.debug_start); */
+            symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugStart, sym->proc32.debug_start, NULL);
+            symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugEnd, sym->proc32.debug_end, NULL);
 	    break;
 
         /*
@@ -2211,17 +2288,116 @@
             memcpy(symname, sym->stack.name, sym->stack.namelen);
             symname[sym->stack.namelen] = '\0';
             symt_add_func_local(msc_dbg->module, curr_func, 0, sym->stack.offset,
-                                NULL, codeview_get_type(sym->stack.symtype, FALSE),
+                                block, codeview_get_type(sym->stack.symtype, FALSE),
                                 symname);
             break;
 	case S_BPREL_32:
             memcpy(symname, sym->stack32.name, sym->stack32.namelen);
             symname[sym->stack32.namelen] = '\0';
             symt_add_func_local(msc_dbg->module, curr_func, 0, sym->stack32.offset,
-                                NULL, codeview_get_type(sym->stack32.symtype, FALSE),
+                                block, codeview_get_type(sym->stack32.symtype, FALSE),
                                 symname);
             break;
 
+        case S_REGISTER:
+            memcpy(symname, sym->s_register.name, sym->s_register.namelen);
+            symname[sym->s_register.namelen] = '\0';
+            symt_add_func_local(msc_dbg->module, curr_func, 0, sym->s_register.reg,
+                                block, codeview_get_type(sym->s_register.type, FALSE),
+                                symname);
+            break;
+
+        case S_REGISTER_32:
+            memcpy(symname, sym->s_register32.name, sym->s_register32.namelen);
+            symname[sym->s_register32.namelen] = '\0';
+            symt_add_func_local(msc_dbg->module, curr_func, 0, sym->s_register32.reg,
+                                block, codeview_get_type(sym->s_register32.type, FALSE),
+                                symname);
+            break;
+
+        case S_BLOCK:
+            block = symt_open_func_block(msc_dbg->module, curr_func, block, 
+                                         codeview_get_address(msc_dbg, sym->block.segment, sym->block.offset),
+                                         sym->block.length);
+            break;
+
+        case S_END:
+            if (block)
+            {
+                block = symt_close_func_block(msc_dbg->module, curr_func, block, 0);
+            }
+            else if (curr_func)
+            {
+                symt_normalize_function(msc_dbg->module, curr_func);
+                curr_func = NULL;
+            }
+            break;
+
+        case S_COMPILE:
+            TRACE("S-Compile %x %.*s\n", ((LPBYTE)sym)[4], ((LPBYTE)sym)[8], (LPBYTE)sym + 9);
+            break;
+
+        case S_OBJNAME:
+            TRACE("S-ObjName %.*s\n", ((LPBYTE)sym)[8], (LPBYTE)sym + 9);
+            break;
+
+        case S_LABEL:
+            memcpy(symname, sym->label.name, sym->label.namelen);
+            symname[sym->label.namelen] = '\0';
+            if (curr_func)
+            {
+                symt_add_function_point(msc_dbg->module, curr_func, SymTagLabel, 
+                                        codeview_get_address(msc_dbg, sym->label.segment, sym->label.offset) - curr_func->addr,
+                                        symname);
+            }
+            else FIXME("No current function for label %s\n", symname);
+            break;
+
+#if 0
+        case S_CONSTANT_32:
+            {
+                int             val, vlen;
+                char*           ptr;
+                const char*     x;
+                struct symt*    se;
+
+                vlen = numeric_leaf(&val, &sym->constant32.arrlen);
+                ptr = (char*)&sym->constant32.arrlen + vlen;
+                se = codeview_get_type(sym->constant32.type, FALSE);
+                if (!se) x = "---";
+                else if (se->tag == SymTagEnum) x = ((struct symt_enum*)se)->name;
+                else x = "###";
+                    
+                FIXME("S-Constant %u %.*s %x (%s)\n", 
+                      val, ptr[0], ptr + 1, sym->constant32.type, x);
+            }
+            break;
+#endif
+
+        case S_UDT:
+            symt = codeview_get_type(sym->udt.type, FALSE);
+            if (symt)
+            {
+                memcpy(symname, sym->udt.name, sym->udt.namelen);
+                symname[sym->udt.namelen] = '\0';
+                symt_new_typedef(msc_dbg->module, symt, symname);
+            }
+            else FIXME("S-Udt %.*s: couldn't find type 0x%x\n", 
+                       sym->udt.namelen, sym->udt.name, sym->udt.type);
+            break;
+
+        case S_UDT_32:
+            symt = codeview_get_type(sym->udt32.type, FALSE);
+            if (symt)
+            {
+                memcpy(symname, sym->udt32.name, sym->udt32.namelen);
+                symname[sym->udt32.namelen] = '\0';
+                symt_new_typedef(msc_dbg->module, symt, symname);
+            }
+            else FIXME("S-Udt %.*s: couldn't find type 0x%x\n", 
+                       sym->udt32.namelen, sym->udt32.name, sym->udt32.type);
+            break;
+
         /*
          * These are special, in that they are always followed by an
          * additional length-prefixed string which is *not* included
diff --git a/dlls/dbghelp/stabs.c b/dlls/dbghelp/stabs.c
index 76c5dda..e08a86c 100644
--- a/dlls/dbghelp/stabs.c
+++ b/dlls/dbghelp/stabs.c
@@ -1112,6 +1112,30 @@
     return found;
 }
 
+/******************************************************************
+ *		stabs_finalize_function
+ *
+ * Ends function creation: mainly:
+ * - cleans up line number information
+ * - tries to set up a debug-start tag (FIXME: heuristic to be enhanced)
+ */
+static void stabs_finalize_function(struct module* module, struct symt_function* func)
+{
+    IMAGEHLP_LINE       il;
+   
+    if (!func) return;
+    symt_normalize_function(module, func);
+    /* To define the debug-start of the function, we use the second line number.
+     * Not 100% bullet proof, but better than nothing
+     */
+    if (symt_fill_func_line_info(module, func, func->addr, &il) &&
+        symt_get_func_line_next(module, &il))
+    {
+        symt_add_function_point(module, func, SymTagFuncDebugStart, 
+                                il.Address - func->addr, NULL);
+    }
+}
+
 SYM_TYPE stabs_parse(struct module* module, const char* addr, 
                      unsigned long load_offset, unsigned int staboff, int stablen,
                      unsigned int strtaboff, int strtablen)
@@ -1267,7 +1291,7 @@
             break;
         case N_LBRAC:
             block = symt_open_func_block(module, curr_func, block,
-                                         stab_ptr->n_value);
+                                         stab_ptr->n_value, 0);
             for (j = 0; j < num_pending_vars; j++)
             {
                 symt_add_func_local(module, curr_func, pending_vars[j].regno, 
@@ -1284,9 +1308,13 @@
             /* These are function parameters. */
             if (curr_func != NULL)
             {
+                struct symt*    param_type = stabs_parse_type(ptr);
                 stab_strcpy(symname, sizeof(symname), ptr);
                 symt_add_func_local(module, curr_func, 0, stab_ptr->n_value, 
-                                    NULL, stabs_parse_type(ptr), symname);
+                                    NULL, param_type, symname);
+                symt_add_function_signature_parameter(module, 
+                                                      (struct symt_function_signature*)curr_func->type, 
+                                                      param_type);
             }
             break;
         case N_RSYM:
@@ -1385,7 +1413,7 @@
             break;
         case N_FUN:
             /* First, clean up the previous function we were working on. */
-            symt_normalize_function(module, curr_func);
+            stabs_finalize_function(module, curr_func);
 
             /*
              * For now, just declare the various functions.  Later
@@ -1402,18 +1430,18 @@
             stab_strcpy(symname, sizeof(symname), ptr);
             if (*symname)
             {
-                struct symt_function_signature*        func_type;
+                struct symt_function_signature* func_type;
                 func_type = symt_new_function_signature(module, 
                                                         stabs_parse_type(ptr));
 #ifdef __ELF__
                 if ((public = lookup_public(module, compiland, symname)))
-                curr_func = symt_new_function(module, compiland, symname, 
-                                              public->address, public->size,
-                                              stabs_parse_type(ptr));
+                    curr_func = symt_new_function(module, compiland, symname, 
+                                                  public->address, public->size,
+                                                  &func_type->symt);
 #else
                 curr_func = symt_new_function(module, compiland, symname, 
                                               load_offset + stab_ptr->n_value, 0,
-                                              stabs_parse_type(ptr));
+                                              &func_type->symt);
 #endif
             }
             else
@@ -1431,7 +1459,7 @@
             {
                 /* Nuke old path. */
                 currpath[0] = '\0';
-                symt_normalize_function(module, curr_func);
+                stabs_finalize_function(module, curr_func);
                 curr_func = NULL;
                 source_idx = -1;
                 incl_stk = -1;
@@ -1456,7 +1484,7 @@
         case N_UNDF:
             strs += strtabinc;
             strtabinc = stab_ptr->n_value;
-            symt_normalize_function(module, curr_func);
+            stabs_finalize_function(module, curr_func);
             curr_func = NULL;
             break;
         case N_OPT:
diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c
index 21d562e..4e78a66 100644
--- a/dlls/dbghelp/symbol.c
+++ b/dlls/dbghelp/symbol.c
@@ -20,6 +20,8 @@
  */
 
 
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
 #include "config.h"
 #include <stdlib.h>
 #include <stdio.h>
@@ -77,6 +79,61 @@
     return cmp_addr(a1, a2);
 }
 
+static inline void re_append(char** mask, unsigned* len, char ch)
+{
+    *mask = HeapReAlloc(GetProcessHeap(), 0, *mask, ++(*len));
+    (*mask)[*len - 2] = ch;
+}
+
+/* transforms a dbghelp's regular expression into a POSIX one
+ * Here are the valid dbghelp reg ex characters:
+ *      *       0 or more characters
+ *      ?       a single character
+ *      []      list
+ *      #       0 or more of preceding char
+ *      +       1 or more of preceding char
+ *      escapes \ on #, ?, [, ], *, +. don't work on -
+ */
+static void compile_regex(const char* str, regex_t* re)
+{
+    char*       mask = HeapAlloc(GetProcessHeap(), 0, 1);
+    unsigned    len = 1;
+    BOOL        in_escape = FALSE;
+
+    re_append(&mask, &len, '^');
+    while (*str)
+    {
+        /* FIXME: this shouldn't be valid on '-' */
+        if (in_escape)
+        {
+            re_append(&mask, &len, '\\');
+            re_append(&mask, &len, *str);
+            in_escape = FALSE;
+        }
+        else switch (*str)
+        {
+        case '\\': in_escape = TRUE; break;
+        case '*':  re_append(&mask, &len, '.'); re_append(&mask, &len, '*'); break;
+        case '?':  re_append(&mask, &len, '.'); break;
+        case '#':  re_append(&mask, &len, '*'); break;
+        /* escape some valid characters in dbghelp reg exp:s */
+        case '$':  re_append(&mask, &len, '\\'); re_append(&mask, &len, '$'); break;
+        /* +, [, ], - are the same in dbghelp & POSIX, use them as any other char */
+        default:   re_append(&mask, &len, *str); break;
+        }
+        str++;
+    }
+    if (in_escape)
+    {
+        re_append(&mask, &len, '\\');
+        re_append(&mask, &len, '\\');
+    }
+    re_append(&mask, &len, '$');
+    mask[len - 1] = '\0';
+    regcomp(re, mask, REG_NOSUB);
+    HeapFree(GetProcessHeap(), 0, mask);
+}
+
 struct symt_compiland* symt_new_compiland(struct module* module, const char* name)
 {
     struct symt_compiland*    sym;
@@ -158,13 +215,15 @@
                                         struct symt_compiland* compiland, 
                                         const char* name,
                                         unsigned long addr, unsigned long size,
-                                        struct symt* type)
+                                        struct symt* sig_type)
 {
     struct symt_function*       sym;
     struct symt**               p;
 
     TRACE_(dbghelp_symtype)("Adding global function %s:%s @%lx-%lx\n", 
                             module->module.ModuleName, name, addr, addr + size - 1);
+
+    assert(!sig_type || sig_type->tag == SymTagFunctionType);
     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
     {
         sym->symt.tag  = SymTagFunction;
@@ -173,7 +232,7 @@
         module->sortlist_valid = FALSE;
         sym->container = &compiland->symt;
         sym->addr      = addr;
-        sym->type      = type;
+        sym->type      = sig_type;
         sym->size      = size;
         sym->addr      = addr;
         vector_init(&sym->vlines,  sizeof(struct line_info), 64);
@@ -244,7 +303,7 @@
     locsym->symt.tag      = SymTagData;
     locsym->hash_elt.name = pool_strdup(&module->pool, name);
     locsym->hash_elt.next = NULL;
-    locsym->kind          = DataIsLocal;
+    locsym->kind          = (offset < 0) ? DataIsParam : DataIsLocal;
     locsym->container     = &block->symt;
     locsym->type          = type;
     if (regno)
@@ -269,7 +328,7 @@
 struct symt_block* symt_open_func_block(struct module* module, 
                                         struct symt_function* func,
                                         struct symt_block* parent_block, 
-                                        unsigned pc)
+                                        unsigned pc, unsigned len)
 {
     struct symt_block*  block;
     struct symt**       p;
@@ -279,9 +338,9 @@
 
     assert(!parent_block || parent_block->symt.tag == SymTagBlock);
     block = pool_alloc(&module->pool, sizeof(*block));
-    block->symt.tag         = SymTagBlock;
-    block->address = func->addr + pc;
-    block->size    = 0;
+    block->symt.tag = SymTagBlock;
+    block->address  = func->addr + pc;
+    block->size     = len;
     block->container = parent_block ? &parent_block->symt : &func->symt;
     vector_init(&block->vchildren, sizeof(struct symt*), 4);
     if (parent_block)
@@ -299,17 +358,37 @@
 {
     assert(func->symt.tag == SymTagFunction);
 
-    block->size = func->addr + pc - block->address;
+    if (pc) block->size = func->addr + pc - block->address;
     return (block->container->tag == SymTagBlock) ? 
         GET_ENTRY(block->container, struct symt_block, symt) : NULL;
 }
 
+struct symt_function_point* symt_add_function_point(struct module* module, 
+                                                    struct symt_function* func,
+                                                    enum SymTagEnum point, 
+                                                    unsigned offset, const char* name)
+{
+    struct symt_function_point* sym;
+    struct symt**               p;
+
+    if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
+    {
+        sym->symt.tag = point;
+        sym->parent   = func;
+        sym->offset   = offset;
+        sym->name     = name ? pool_strdup(&module->pool, name) : NULL;
+        p = vector_add(&func->vchildren, &module->pool);
+        *p = &sym->symt;
+    }
+    return sym;
+}
+
 BOOL symt_normalize_function(struct module* module, struct symt_function* func)
 {
     unsigned            len;
     struct line_info*   dli;
 
-    if (!func) return TRUE;
+    assert(func);
     /* We aren't adding any more locals or line numbers to this function.
      * Free any spare memory that we might have allocated.
      */
@@ -363,7 +442,17 @@
                 break;
             case LocIsConstant:
                 sym_info->Flags |= SYMFLAG_VALUEPRESENT;
-                sym_info->Value = data->u.value;
+                switch (data->u.value.n1.n2.vt)
+                {
+                case VT_I4:  sym_info->Value = (ULONG)data->u.value.n1.n2.n3.lVal; break;
+                case VT_I2:  sym_info->Value = (ULONG)(long)data->u.value.n1.n2.n3.iVal; break;
+                case VT_I1:  sym_info->Value = (ULONG)(long)data->u.value.n1.n2.n3.cVal; break;
+                case VT_UI4: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.ulVal; break;
+                case VT_UI2: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.uiVal; break;
+                case VT_UI1: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.bVal; break;
+                default:        
+                    FIXME("Unsupported variant type (%u)\n", data->u.value.n1.n2.vt);
+                }
                 break;
             default:
                 FIXME("Unhandled loc (%u) in sym data\n", data->location);
@@ -408,7 +497,7 @@
 
     assert(mask);
     assert(mask[0] != '!');
-    regcomp(&preg, mask, REG_NOSUB);
+    compile_regex(mask, &preg);
     hash_table_iter_init(&module->ht_symbols, &hti, NULL);
     while ((ptr = hash_table_iter_up(&hti)))
     {
@@ -550,6 +639,10 @@
                     return FALSE;
             }
             break;
+        case SymTagLabel:
+        case SymTagFuncDebugStart:
+        case SymTagFuncDebugEnd:
+            break;
         default:
             FIXME("Unknown type: %u (%x)\n", lsym->tag, lsym->tag);
             assert(0);
@@ -582,7 +675,7 @@
         BOOL            ret;
         regex_t         preg;
 
-        regcomp(&preg, mask ? mask : ".*", REG_NOSUB);
+        compile_regex(mask ? mask : "*", &preg);
         ret = symt_enum_locals_helper(pcs, module, &preg, EnumSymbolsCallback, 
                                       UserContext, sym_info, 
                                       &((struct symt_function*)sym)->vchildren);
@@ -620,7 +713,7 @@
                 for (module = pcs->lmodules; module; module = module->next)
                 {
                     if (module->module.SymType != SymNone &&
-                        !symt_enum_module(module, ".*", EnumSymbolsCallback, UserContext))
+                        !symt_enum_module(module, "*", EnumSymbolsCallback, UserContext))
                         break;
                 }
                 return TRUE;
@@ -641,9 +734,9 @@
                 FIXME("Strange call mode\n");
                 return FALSE;
             }
-            Mask = ".*";
+            Mask = "*";
         }
-        else if (!Mask) Mask = ".*";
+        else if (!Mask) Mask = "*";
     }
     if ((module = module_get_debug(pcs, module)))
         symt_enum_module(module, Mask, EnumSymbolsCallback, UserContext);
@@ -792,12 +885,12 @@
 }
 
 /******************************************************************
- *		fill_line_info
+ *		sym_fill_func_line_info
  *
  * fills information about a file
  */
-static BOOL fill_line_info(struct module* module, struct symt_function* func, 
-                           DWORD addr, IMAGEHLP_LINE* line)
+BOOL symt_fill_func_line_info(struct module* module, struct symt_function* func, 
+                              DWORD addr, IMAGEHLP_LINE* line)
 {
     struct line_info*   dli = NULL;
     BOOL                found = FALSE;
@@ -872,9 +965,9 @@
     if ((idx = symt_find_nearest(module, dwAddr)) == -1) return FALSE;
 
     if (module->addr_sorttab[idx]->symt.tag != SymTagFunction) return FALSE;
-    if (!fill_line_info(module, 
-                        (struct symt_function*)module->addr_sorttab[idx],
-                        dwAddr, Line)) return FALSE;
+    if (!symt_fill_func_line_info(module, 
+                                  (struct symt_function*)module->addr_sorttab[idx],
+                                  dwAddr, Line)) return FALSE;
     if (pdwDisplacement) *pdwDisplacement = dwAddr - Line->Address;
     return TRUE;
 }
@@ -929,6 +1022,27 @@
     return FALSE;
 }
 
+BOOL symt_get_func_line_next(struct module* module, PIMAGEHLP_LINE line)
+{
+    struct line_info*   li;
+
+    if (line->Key == 0) return FALSE;
+    li = (struct line_info*)line->Key;
+    while (!(li->cookie & DLIT_LAST))
+    {
+        li++;
+        if (!(li->cookie & DLIT_SOURCEFILE))
+        {
+            line->LineNumber = li->line_number;
+            line->Address    = li->u.pc_offset;
+            line->Key        = li;
+            return TRUE;
+        }
+        line->FileName = (char*)source_get(module, li->u.source_file);
+    }
+    return FALSE;
+}
+
 /******************************************************************
  *		SymGetLineNext (DBGHELP.@)
  *
@@ -937,7 +1051,6 @@
 {
     struct process*     pcs = process_find_by_handle(hProcess);
     struct module*      module;
-    struct line_info*   li;
 
     TRACE("(%p %p)\n", hProcess, Line);
 
@@ -946,20 +1059,7 @@
     module = module_find_by_addr(pcs, Line->Address, DMT_UNKNOWN);
     if (!(module = module_get_debug(pcs, module))) return FALSE;
 
-    if (Line->Key == 0) return FALSE;
-    li = (struct line_info*)Line->Key;
-    while (!(li->cookie & DLIT_LAST))
-    {
-        li++;
-        if (!(li->cookie & DLIT_SOURCEFILE))
-        {
-            Line->LineNumber = li->line_number;
-            Line->Address    = li->u.pc_offset;
-            Line->Key        = li;
-            return TRUE;
-        }
-        Line->FileName = (char*)source_get(module, li->u.source_file);
-    }
+    if (symt_get_func_line_next(module, Line)) return TRUE;
     SetLastError(ERROR_NO_MORE_ITEMS); /* FIXME */
     return FALSE;
 }
diff --git a/dlls/dbghelp/type.c b/dlls/dbghelp/type.c
index 79e444e..8089dbc 100644
--- a/dlls/dbghelp/type.c
+++ b/dlls/dbghelp/type.c
@@ -84,6 +84,7 @@
     case SymTagFunction:        return ((struct symt_function*)sym)->hash_elt.name;
     case SymTagPublicSymbol:    return ((struct symt_public*)sym)->hash_elt.name;
     case SymTagBaseType:        return ((struct symt_basic*)sym)->hash_elt.name;
+    case SymTagLabel:           return ((struct symt_function_point*)sym)->name;
     /* hierarchy tree */
     case SymTagEnum:            return ((struct symt_enum*)sym)->name;
     case SymTagTypedef:         return ((struct symt_typedef*)sym)->hash_elt.name;
@@ -252,7 +253,7 @@
 }
 
 BOOL symt_add_enum_element(struct module* module, struct symt_enum* enum_type,
-                           const char* name, unsigned value)
+                           const char* name, int value)
 {
     struct symt_data*   e;
     struct symt**       p;
@@ -269,7 +270,8 @@
     /* CV defines the underlying type for the enumeration */
     e->type = &symt_new_basic(module, btInt, "int", 4)->symt;
     e->location = LocIsConstant;
-    e->u.value = value; /* FIXME: use variant */
+    e->u.value.n1.n2.vt = VT_I4;
+    e->u.value.n1.n2.n3.lVal = value;
 
     p = vector_add(&enum_type->vchildren, &module->pool);
     if (!p) return FALSE; /* FIXME we leak e */
@@ -296,16 +298,31 @@
 struct symt_function_signature* symt_new_function_signature(struct module* module, 
                                                             struct symt* ret_type)
 {
-    struct symt_function_signature* sym;
+    struct symt_function_signature*     sym;
 
     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
     {
         sym->symt.tag = SymTagFunctionType;
         sym->rettype  = ret_type;
+        vector_init(&sym->vchildren, sizeof(struct symt*), 4);
     }
     return sym;
 }
 
+BOOL symt_add_function_signature_parameter(struct module* module,
+                                           struct symt_function_signature* sig_type,
+                                           struct symt* param)
+{
+    struct symt**       p;
+
+    assert(sig_type->symt.tag == SymTagFunctionType);
+    p = vector_add(&sig_type->vchildren, &module->pool);
+    if (!p) return FALSE; /* FIXME we leak e */
+    *p = param;
+
+    return TRUE;
+}
+
 struct symt_pointer* symt_new_pointer(struct module* module, struct symt* ref_type)
 {
     struct symt_pointer*        sym;
@@ -318,6 +335,21 @@
     return sym;
 }
 
+struct symt_typedef* symt_new_typedef(struct module* module, struct symt* ref, 
+                                      const char* name)
+{
+    struct symt_typedef* sym;
+
+    if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
+    {
+        sym->symt.tag = SymTagTypedef;
+        sym->type     = ref;
+        sym->hash_elt.name = pool_strdup(&module->pool, name);
+        hash_table_add(&module->ht_types, &sym->hash_elt);
+    }
+    return sym;
+}
+
 /******************************************************************
  *		SymEnumTypes (DBGHELP.@)
  *
@@ -395,10 +427,13 @@
 
             switch (type->tag)
             {
-            case SymTagUDT:  v = &((struct symt_udt*)type)->vchildren; break;
-            case SymTagEnum: v = &((struct symt_enum*)type)->vchildren; break;
+            case SymTagUDT:          v = &((struct symt_udt*)type)->vchildren; break;
+            case SymTagEnum:         v = &((struct symt_enum*)type)->vchildren; break;
+            case SymTagFunctionType: v = &((struct symt_function_signature*)type)->vchildren; break;
+            case SymTagFunction:     v = &((struct symt_function*)type)->vchildren; break;
             default:
-                FIXME("Unsupported sym-tag %s for find-children\n", symt_get_tag_str(type->tag));
+                FIXME("Unsupported sym-tag %s for find-children\n", 
+                      symt_get_tag_str(type->tag));
                 return FALSE;
             }
             for (i = 0; i < tifp->Count; i++)
@@ -428,25 +463,31 @@
         case SymTagPublicSymbol:
             X(DWORD) = ((struct symt_public*)type)->address;
             break;
+        case SymTagFuncDebugStart:
+        case SymTagFuncDebugEnd:
+        case SymTagLabel:
+            X(DWORD) = ((struct symt_function_point*)type)->parent->addr + 
+                ((struct symt_function_point*)type)->offset;
+            break;
         default:
-            FIXME("Unsupported sym-tag %s for get-address\n", symt_get_tag_str(type->tag));
+            FIXME("Unsupported sym-tag %s for get-address\n", 
+                  symt_get_tag_str(type->tag));
             return FALSE;
         }
         break;
 
-#if 0
-        /* this is wrong, we should return the type of the index, not the
-         * type of the array[0]
-         */
-    case TI_GET_ARRAYINDEXTYPEID:
-        if (type->tag != SymTagArrayType) return FALSE;
-        X(DWORD) = (DWORD)((struct symt_array*)type)->basetype;
-        break;
-#endif
-
     case TI_GET_BASETYPE:
-        if (type->tag != SymTagBaseType) return FALSE;
-        X(DWORD) = ((struct symt_basic*)type)->bt;
+        switch (type->tag)
+        {
+        case SymTagBaseType:
+            X(DWORD) = ((struct symt_basic*)type)->bt;
+            break;
+        case SymTagEnum:
+            X(DWORD) = btInt;
+            break;
+        default:
+            return FALSE;
+        }
         break;
 
     case TI_GET_BITPOSITION:
@@ -464,17 +505,32 @@
         case SymTagEnum:
             X(DWORD) = vector_length(&((struct symt_enum*)type)->vchildren);
             break;
+        case SymTagFunctionType:
+            X(DWORD) = vector_length(&((struct symt_function_signature*)type)->vchildren);
+            break;
+        case SymTagFunction:
+            X(DWORD) = vector_length(&((struct symt_function*)type)->vchildren);
+            break;
+        case SymTagPointerType: /* MS does it that way */
+        case SymTagArrayType: /* MS does it that way */
+            X(DWORD) = 0;
+            break;
         default:
-            FIXME("Unsupported sym-tag %s for get-children-count\n", symt_get_tag_str(type->tag));
+            FIXME("Unsupported sym-tag %s for get-children-count\n", 
+                  symt_get_tag_str(type->tag));
             /* fall through */
+        case SymTagData:
         case SymTagPublicSymbol:
-        case SymTagPointerType:
         case SymTagBaseType:
             return FALSE;
         }
         break;
 
     case TI_GET_COUNT:
+        /* it seems that FunctionType also react to GET_COUNT (same value as
+         * GET_CHILDREN_COUNT ?, except for C++ methods, where it seems to
+         * also include 'this' (GET_CHILDREN_COUNT+1)
+         */
         if (type->tag != SymTagArrayType) return FALSE;
         X(DWORD) = ((struct symt_array*)type)->end - 
             ((struct symt_array*)type)->start;
@@ -501,14 +557,13 @@
             X(DWORD) = ((struct symt_udt*)type)->size;
             break;
         case SymTagEnum:
-            X(DWORD) = sizeof(int);
+            X(DWORD) = sizeof(int); /* FIXME: should be size of base-type of enum !!! */
             break;
         case SymTagData:
             if (((struct symt_data*)type)->location == LocIsBitField)
                 X(DWORD) = ((struct symt_data*)type)->u.bitfield.length;
             else
-                return symt_get_info(((struct symt_data*)type)->type, 
-                                     TI_GET_LENGTH, pInfo);
+                return FALSE;
             break;
         case SymTagArrayType:   
             if (!symt_get_info(((struct symt_array*)type)->basetype, 
@@ -520,8 +575,12 @@
         case SymTagPublicSymbol:
             X(DWORD) = ((struct symt_public*)type)->size;
             break;
+        case SymTagTypedef:
+            return symt_get_info(((struct symt_typedef*)type)->type, TI_GET_LENGTH, pInfo);
+            break;
         default:
-            FIXME("Unsupported sym-tag %s for get-size\n", symt_get_tag_str(type->tag));
+            FIXME("Unsupported sym-tag %s for get-length\n", 
+                  symt_get_tag_str(type->tag));
             return 0;
         }
         break;
@@ -536,7 +595,20 @@
             X(DWORD) = (DWORD)((struct symt_data*)type)->container;
             break;
         default:
-            FIXME("Unsupported sym-tag %s for get-lexical-parent\n", symt_get_tag_str(type->tag));
+            FIXME("Unsupported sym-tag %s for get-lexical-parent\n", 
+                  symt_get_tag_str(type->tag));
+            return FALSE;
+        }
+        break;
+
+    case TI_GET_NESTED:
+        switch (type->tag)
+        {
+        case SymTagUDT:
+        case SymTagEnum:
+            X(DWORD) = 0;
+            break;
+        default:
             return FALSE;
         }
         break;
@@ -545,23 +617,22 @@
         switch (type->tag)
         {
         case SymTagData:
-            switch (((struct symt_data*)type)->location)
+            switch (((struct symt_data*)type)->kind)
             {
-            case LocIsRegRel:
-            case LocIsThisRel:  
+            case DataIsParam:
+            case DataIsLocal:
+            case DataIsMember:
                 X(ULONG) = ((struct symt_data*)type)->u.offset; 
                 break;
-            case LocIsConstant: 
-                X(ULONG) = 0; /* FIXME ???? */
-                break;
             default:
-                FIXME("Unknown location (%u) for get-offset\n", 
-                      ((struct symt_data*)type)->location);
-                break;
+                FIXME("Unknown kind (%u) for get-offset\n", 
+                      ((struct symt_data*)type)->kind);
+                return FALSE;
             }
             break;
         default:
-            FIXME("Unsupported sym-tag %s for get-offset\n", symt_get_tag_str(type->tag));
+            FIXME("Unsupported sym-tag %s for get-offset\n", 
+                  symt_get_tag_str(type->tag));
             return FALSE;
         }
         break;
@@ -582,8 +653,10 @@
         break;
 
     case TI_GET_TYPE:
+    case TI_GET_TYPEID:
         switch (type->tag)
         {
+            /* hierarchical => hierarchical */
         case SymTagArrayType:
             X(DWORD) = (DWORD)((struct symt_array*)type)->basetype;
             break;
@@ -593,34 +666,43 @@
         case SymTagFunctionType:
             X(DWORD) = (DWORD)((struct symt_function_signature*)type)->rettype;
             break;
+        case SymTagTypedef:
+            X(DWORD) = (DWORD)((struct symt_typedef*)type)->type;
+            break;
+            /* lexical => hierarchical */
         case SymTagData:
             X(DWORD) = (DWORD)((struct symt_data*)type)->type; 
             break;
+        case SymTagFunction:
+            X(DWORD) = (DWORD)((struct symt_function*)type)->type;
+            break;
+            /* FIXME: should also work for enums and FunctionArgType */
         default:
-            FIXME("Unsupported sym-tag %s for get-type\n", symt_get_tag_str(type->tag));
+            FIXME("Unsupported sym-tag %s for get-type\n", 
+                  symt_get_tag_str(type->tag));
             return FALSE;
         }
         break;
 
-    case TI_GET_TYPEID:
-        X(DWORD) = (DWORD)type; 
-        break;
-
     case TI_GET_UDTKIND:
         if (type->tag != SymTagUDT) return FALSE;
         X(DWORD) = ((struct symt_udt*)type)->kind;
         break;
 
+    case TI_GET_VALUE:
+        if (type->tag != SymTagData || ((struct symt_data*)type)->kind != DataIsConstant)
+            return FALSE;
+        X(VARIANT) = ((struct symt_data*)type)->u.value;
+        break;
+
 #undef X
 
     case TI_GET_ADDRESSOFFSET:
     case TI_GET_ARRAYINDEXTYPEID:
     case TI_GET_CALLING_CONVENTION:
     case TI_GET_CLASSPARENTID:
-    case TI_GET_NESTED:
     case TI_GET_SYMINDEX:
     case TI_GET_THISADJUST:
-    case TI_GET_VALUE:
     case TI_GET_VIRTUALBASECLASS:
     case TI_GET_VIRTUALBASEPOINTEROFFSET:
     case TI_GET_VIRTUALTABLESHAPEID: