widl: beginning of typelib generation

Huw D M Davies h.davies1 at physics.ox.ac.uk
Thu Jan 6 08:46:51 CST 2005


Hi,

This adds preliminarily support for typelib generation to widl.  It's
not enough to generate stdole32.tlb mainly because it doesn't cope
with some of the builtin types, like VARIANT, properly yet.  However
it should be possible to generate simple typelibs (for testing the
typelib marshaller for instance).  I'm going to continue to work on
this so let me know if you're interesting in helping out.

        Huw Davies <huw at codeweavers.com>
        Initial support for typelib generation.
-- 
Huw Davies
huw at codeweavers.com
Index: tools/widl/Makefile.in
===================================================================
RCS file: /home/wine/wine/tools/widl/Makefile.in,v
retrieving revision 1.10
diff -u -p -r1.10 Makefile.in
--- tools/widl/Makefile.in	9 Mar 2004 03:49:39 -0000	1.10
+++ tools/widl/Makefile.in	6 Jan 2005 14:37:34 -0000
@@ -10,11 +10,13 @@ PROGRAMS = widl$(EXEEXT)
 MODULE   = none
 
 C_SRCS = \
+	hash.c \
 	header.c \
 	proxy.c \
 	typelib.c \
 	utils.c \
-	widl.c
+	widl.c \
+	write_msft.c
 
 EXTRA_SRCS = parser.y parser.l
 EXTRA_OBJS = y.tab.o @LEX_OUTPUT_ROOT at .o
Index: tools/widl/header.c
===================================================================
RCS file: /home/wine/wine/tools/widl/header.c,v
retrieving revision 1.31
diff -u -p -r1.31 header.c
--- tools/widl/header.c	18 Oct 2004 19:35:08 -0000	1.31
+++ tools/widl/header.c	6 Jan 2005 14:37:35 -0000
@@ -30,6 +30,7 @@
 #include <ctype.h>
 #include <signal.h>
 
+#include "windef.h"
 #include "widl.h"
 #include "utils.h"
 #include "parser.h"
Index: tools/widl/parser.y
===================================================================
RCS file: /home/wine/wine/tools/widl/parser.y,v
retrieving revision 1.29
diff -u -p -r1.29 parser.y
--- tools/widl/parser.y	5 Jan 2005 17:12:25 -0000	1.29
+++ tools/widl/parser.y	6 Jan 2005 14:37:38 -0000
@@ -31,6 +31,8 @@
 #include <alloca.h>
 #endif
 
+#include "windef.h"
+
 #include "widl.h"
 #include "utils.h"
 #include "parser.h"
@@ -969,6 +971,7 @@ static type_t *make_type(unsigned char t
   t->sign = 0;
   t->defined = FALSE;
   t->written = FALSE;
+  t->typelib_idx = -1;
   INIT_LINK(t);
   return t;
 }
Index: tools/widl/typelib.c
===================================================================
RCS file: /home/wine/wine/tools/widl/typelib.c,v
retrieving revision 1.4
diff -u -p -r1.4 typelib.c
--- tools/widl/typelib.c	5 Jan 2005 17:12:25 -0000	1.4
+++ tools/widl/typelib.c	6 Jan 2005 14:37:39 -0000
@@ -36,60 +36,6 @@
 
 int in_typelib = 0;
 
-/* Copied from wtypes.h. Not included directly because that would create a
- * circular dependency (after all, wtypes.h is generated by widl...) */
-
-enum VARENUM {
-    VT_EMPTY = 0,
-    VT_NULL = 1,
-    VT_I2 = 2,
-    VT_I4 = 3,
-    VT_R4 = 4,
-    VT_R8 = 5,
-    VT_CY = 6,
-    VT_DATE = 7,
-    VT_BSTR = 8,
-    VT_DISPATCH = 9,
-    VT_ERROR = 10,
-    VT_BOOL = 11,
-    VT_VARIANT = 12,
-    VT_UNKNOWN = 13,
-    VT_DECIMAL = 14,
-    VT_I1 = 16,
-    VT_UI1 = 17,
-    VT_UI2 = 18,
-    VT_UI4 = 19,
-    VT_I8 = 20,
-    VT_UI8 = 21,
-    VT_INT = 22,
-    VT_UINT = 23,
-    VT_VOID = 24,
-    VT_HRESULT = 25,
-    VT_PTR = 26,
-    VT_SAFEARRAY = 27,
-    VT_CARRAY = 28,
-    VT_USERDEFINED = 29,
-    VT_LPSTR = 30,
-    VT_LPWSTR = 31,
-    VT_RECORD = 36,
-    VT_FILETIME = 64,
-    VT_BLOB = 65,
-    VT_STREAM = 66,
-    VT_STORAGE = 67,
-    VT_STREAMED_OBJECT = 68,
-    VT_STORED_OBJECT = 69,
-    VT_BLOB_OBJECT = 70,
-    VT_CF = 71,
-    VT_CLSID = 72,
-    VT_BSTR_BLOB = 0xfff,
-    VT_VECTOR = 0x1000,
-    VT_ARRAY = 0x2000,
-    VT_BYREF = 0x4000,
-    VT_RESERVED = 0x8000,
-    VT_ILLEGAL = 0xffff,
-    VT_ILLEGALMASKED = 0xfff,
-    VT_TYPEMASK = 0xfff
-};
 static typelib_t *typelib;
 
 /* List of oleauto types that should be recognized by name.
@@ -195,8 +141,11 @@ unsigned short get_type_vt(type_t *t)
     }
     /* FIXME: should we recurse and add a VT_BYREF? */
     /* Or just return VT_PTR? */
+    if(t->ref) return get_type_vt(t->ref);
     error("get_type_vt: unknown-deref-type: %d\n", t->ref->type);
     break;
+  case RPC_FC_STRUCT:
+    return VT_USERDEFINED;
   default:
     error("get_type_vt: unknown-type: %d\n", t->type);
   }
@@ -231,7 +180,7 @@ void end_typelib(void)
     in_typelib--;
     if (!typelib) return;
 
-/*    create_msft_typelib(typelib);*/
+    create_msft_typelib(typelib);
     return;
 }
 
Index: tools/widl/typelib.h
===================================================================
RCS file: /home/wine/wine/tools/widl/typelib.h,v
retrieving revision 1.2
diff -u -p -r1.2 typelib.h
--- tools/widl/typelib.h	5 Jan 2005 17:12:25 -0000	1.2
+++ tools/widl/typelib.h	6 Jan 2005 14:37:39 -0000
@@ -29,4 +29,61 @@ extern void add_coclass(class_t *cls);
 extern void add_module(type_t *module);
 extern void add_struct(type_t *structure);
 
+/* Copied from wtypes.h. Not included directly because that would create a
+ * circular dependency (after all, wtypes.h is generated by widl...) */
+
+enum VARENUM {
+    VT_EMPTY = 0,
+    VT_NULL = 1,
+    VT_I2 = 2,
+    VT_I4 = 3,
+    VT_R4 = 4,
+    VT_R8 = 5,
+    VT_CY = 6,
+    VT_DATE = 7,
+    VT_BSTR = 8,
+    VT_DISPATCH = 9,
+    VT_ERROR = 10,
+    VT_BOOL = 11,
+    VT_VARIANT = 12,
+    VT_UNKNOWN = 13,
+    VT_DECIMAL = 14,
+    VT_I1 = 16,
+    VT_UI1 = 17,
+    VT_UI2 = 18,
+    VT_UI4 = 19,
+    VT_I8 = 20,
+    VT_UI8 = 21,
+    VT_INT = 22,
+    VT_UINT = 23,
+    VT_VOID = 24,
+    VT_HRESULT = 25,
+    VT_PTR = 26,
+    VT_SAFEARRAY = 27,
+    VT_CARRAY = 28,
+    VT_USERDEFINED = 29,
+    VT_LPSTR = 30,
+    VT_LPWSTR = 31,
+    VT_RECORD = 36,
+    VT_FILETIME = 64,
+    VT_BLOB = 65,
+    VT_STREAM = 66,
+    VT_STORAGE = 67,
+    VT_STREAMED_OBJECT = 68,
+    VT_STORED_OBJECT = 69,
+    VT_BLOB_OBJECT = 70,
+    VT_CF = 71,
+    VT_CLSID = 72,
+    VT_BSTR_BLOB = 0xfff,
+    VT_VECTOR = 0x1000,
+    VT_ARRAY = 0x2000,
+    VT_BYREF = 0x4000,
+    VT_RESERVED = 0x8000,
+    VT_ILLEGAL = 0xffff,
+    VT_ILLEGALMASKED = 0xfff,
+    VT_TYPEMASK = 0xfff
+};
+extern unsigned short get_type_vt(type_t *t);
+
+extern int create_msft_typelib(typelib_t *typelib);
 #endif
Index: tools/widl/widltypes.h
===================================================================
RCS file: /home/wine/wine/tools/widl/widltypes.h,v
retrieving revision 1.19
diff -u -p -r1.19 widltypes.h
--- tools/widl/widltypes.h	5 Jan 2005 17:12:25 -0000	1.19
+++ tools/widl/widltypes.h	6 Jan 2005 14:37:39 -0000
@@ -33,10 +33,6 @@ typedef GUID UUID;
 #define TRUE 1
 #define FALSE 0
 
-#define LOWORD(l) ((unsigned short)(l))
-#define HIWORD(l) ((unsigned short)((unsigned long)(l) >> 16))
-#define MAKELONG(low,high) ((unsigned long)(((unsigned short)(low)) | (((unsigned long)((unsigned short)(high))) << 16)))
-
 typedef struct _attr_t attr_t;
 typedef struct _expr_t expr_t;
 typedef struct _type_t type_t;
@@ -177,7 +173,7 @@ struct _type_t {
   var_t *fields;
   int ignore, is_const, sign;
   int defined, written;
-
+  int typelib_idx;
   /* parser-internal */
   DECL_LINK(type_t)
 };
--- /dev/null	2004-02-23 21:02:56.000000000 +0000
+++ tools/widl/write_msft.c	2005-01-06 14:37:20.157031689 +0000
@@ -0,0 +1,1604 @@
+/*
+ *      Typelib v2 (MSFT) generation
+ *
+ *	Copyright 2004  Alastair Bridgewater
+ *                2004, 2005 Huw Davies
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * --------------------------------------------------------------------------------------
+ *  Known problems:
+ *
+ *    Badly incomplete.
+ *
+ *    Only works on little-endian systems.
+ *
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+
+#include "winerror.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winnls.h"
+
+#include "wine/unicode.h"
+
+#include "widltypes.h"
+#include "typelib.h"
+#include "typelib_struct.h"
+#include "utils.h"
+#include "hash.h"
+
+enum MSFT_segment_index {
+    MSFT_SEG_TYPEINFO = 0,  /* type information */
+    MSFT_SEG_IMPORTINFO,    /* import information */
+    MSFT_SEG_IMPORTFILES,   /* import filenames */
+    MSFT_SEG_REFERENCES,    /* references (?) */
+    MSFT_SEG_GUIDHASH,      /* hash table for guids? */
+    MSFT_SEG_GUID,          /* guid storage */
+    MSFT_SEG_NAMEHASH,      /* hash table for names */
+    MSFT_SEG_NAME,          /* name storage */
+    MSFT_SEG_STRING,        /* string storage */
+    MSFT_SEG_TYPEDESC,      /* type descriptions */
+    MSFT_SEG_ARRAYDESC,     /* array descriptions */
+    MSFT_SEG_CUSTDATA,      /* custom data */
+    MSFT_SEG_CUSTDATAGUID,  /* custom data guids */
+    MSFT_SEG_UNKNOWN,       /* ??? */
+    MSFT_SEG_UNKNOWN2,      /* ??? */
+    MSFT_SEG_MAX            /* total number of segments */
+};
+
+typedef struct tagMSFT_ImpFile {
+    int guid;
+    LCID lcid;
+    int version;
+    char filename[0]; /* preceeded by two bytes of encoded (length << 2) + flags in the low two bits. */
+} MSFT_ImpFile;
+
+typedef struct _msft_typelib_t
+{
+    typelib_t *typelib;
+    MSFT_Header typelib_header;
+    MSFT_pSeg typelib_segdir[MSFT_SEG_MAX];
+    char *typelib_segment_data[MSFT_SEG_MAX];
+    int typelib_segment_block_length[MSFT_SEG_MAX];
+
+    INT typelib_typeinfo_offsets[0x200]; /* Hope that's enough. */
+
+    INT *typelib_namehash_segment;
+    INT *typelib_guidhash_segment;
+
+    struct _msft_typeinfo_t *typeinfos;
+    struct _msft_typeinfo_t *last_typeinfo;
+} msft_typelib_t;
+
+typedef struct _msft_typeinfo_t
+{
+    msft_typelib_t *typelib;
+    MSFT_TypeInfoBase *typeinfo;
+
+    INT *typedata;
+    int typedata_allocated;
+    int typedata_length;
+
+    int indices[42];
+    int names[42];
+    int offsets[42];
+
+    int datawidth;
+
+    struct _msft_typeinfo_t *next_typeinfo;
+} msft_typeinfo_t;
+
+
+
+/*================== Internal functions ===================================*/
+
+/****************************************************************************
+ *	ctl2_init_header
+ *
+ *  Initializes the type library header of a new typelib.
+ */
+static void ctl2_init_header(
+	msft_typelib_t *typelib) /* [I] The typelib to initialize. */
+{
+    typelib->typelib_header.magic1 = 0x5446534d;
+    typelib->typelib_header.magic2 = 0x00010002;
+    typelib->typelib_header.posguid = -1;
+    typelib->typelib_header.lcid = 0x0409; /* or do we use the current one? */
+    typelib->typelib_header.lcid2 = 0x0;
+    typelib->typelib_header.varflags = 0x40;
+    typelib->typelib_header.version = 0;
+    typelib->typelib_header.flags = 0;
+    typelib->typelib_header.nrtypeinfos = 0;
+    typelib->typelib_header.helpstring = -1;
+    typelib->typelib_header.helpstringcontext = 0;
+    typelib->typelib_header.helpcontext = 0;
+    typelib->typelib_header.nametablecount = 0;
+    typelib->typelib_header.nametablechars = 0;
+    typelib->typelib_header.NameOffset = -1;
+    typelib->typelib_header.helpfile = -1;
+    typelib->typelib_header.CustomDataOffset = -1;
+    typelib->typelib_header.res44 = 0x20;
+    typelib->typelib_header.res48 = 0x80;
+    typelib->typelib_header.dispatchpos = -1;
+    typelib->typelib_header.res50 = 0;
+}
+
+/****************************************************************************
+ *	ctl2_init_segdir
+ *
+ *  Initializes the segment directory of a new typelib.
+ */
+static void ctl2_init_segdir(
+	msft_typelib_t *typelib) /* [I] The typelib to initialize. */
+{
+    int i;
+    MSFT_pSeg *segdir;
+
+    segdir = &typelib->typelib_segdir[MSFT_SEG_TYPEINFO];
+
+    for (i = 0; i < 15; i++) {
+	segdir[i].offset = -1;
+	segdir[i].length = 0;
+	segdir[i].res08 = -1;
+	segdir[i].res0c = 0x0f;
+    }
+}
+
+/****************************************************************************
+ *	ctl2_hash_guid
+ *
+ *  Generates a hash key from a GUID.
+ *
+ * RETURNS
+ *
+ *  The hash key for the GUID.
+ */
+static int ctl2_hash_guid(
+	REFGUID guid)                /* [I] The guid to find. */
+{
+    int hash;
+    int i;
+
+    hash = 0;
+    for (i = 0; i < 8; i ++) {
+	hash ^= ((const short *)guid)[i];
+    }
+
+    return (hash & 0xf) | ((hash & 0x10) & (0 - !!(hash & 0xe0)));
+}
+
+/****************************************************************************
+ *	ctl2_find_guid
+ *
+ *  Locates a guid in a type library.
+ *
+ * RETURNS
+ *
+ *  The offset into the GUID segment of the guid, or -1 if not found.
+ */
+static int ctl2_find_guid(
+	msft_typelib_t *typelib,   /* [I] The typelib to operate against. */
+	int hash_key,              /* [I] The hash key for the guid. */
+	REFGUID guid)              /* [I] The guid to find. */
+{
+    int offset;
+    MSFT_GuidEntry *guidentry;
+
+    offset = typelib->typelib_guidhash_segment[hash_key];
+    while (offset != -1) {
+	guidentry = (MSFT_GuidEntry *)&typelib->typelib_segment_data[MSFT_SEG_GUID][offset];
+
+	if (!memcmp(guidentry, guid, sizeof(GUID))) return offset;
+
+	offset = guidentry->next_hash;
+    }
+
+    return offset;
+}
+
+/****************************************************************************
+ *	ctl2_find_name
+ *
+ *  Locates a name in a type library.
+ *
+ * RETURNS
+ *
+ *  The offset into the NAME segment of the name, or -1 if not found.
+ *
+ * NOTES
+ *
+ *  The name must be encoded as with ctl2_encode_name().
+ */
+static int ctl2_find_name(
+	msft_typelib_t *typelib,   /* [I] The typelib to operate against. */
+	char *name)                /* [I] The encoded name to find. */
+{
+    int offset;
+    int *namestruct;
+
+    offset = typelib->typelib_namehash_segment[name[2] & 0x7f];
+    while (offset != -1) {
+	namestruct = (int *)&typelib->typelib_segment_data[MSFT_SEG_NAME][offset];
+
+	if (!((namestruct[2] ^ *((int *)name)) & 0xffff00ff)) {
+	    /* hash codes and lengths match, final test */
+	    if (!strncasecmp(name+4, (void *)(namestruct+3), name[0])) break;
+	}
+
+	/* move to next item in hash bucket */
+	offset = namestruct[1];
+    }
+
+    return offset;
+}
+
+/****************************************************************************
+ *	ctl2_encode_name
+ *
+ *  Encodes a name string to a form suitable for storing into a type library
+ *  or comparing to a name stored in a type library.
+ *
+ * RETURNS
+ *
+ *  The length of the encoded name, including padding and length+hash fields.
+ *
+ * NOTES
+ *
+ *  Will throw an exception if name or result are NULL. Is not multithread
+ *  safe in the slightest.
+ */
+static int ctl2_encode_name(
+	msft_typelib_t *typelib,   /* [I] The typelib to operate against (used for LCID only). */
+	const char *name,          /* [I] The name string to encode. */
+	char **result)             /* [O] A pointer to a pointer to receive the encoded name. */
+{
+    int length;
+    static char converted_name[0x104];
+    int offset;
+    int value;
+
+    length = strlen(name);
+    memcpy(converted_name + 4, name, length);
+    converted_name[0] = length & 0xff;
+
+    converted_name[length + 4] = 0;
+
+    converted_name[1] = 0x00;
+
+    value = lhash_val_of_name_sys(typelib->typelib_header.varflags & 0x0f, typelib->typelib_header.lcid, converted_name + 4);
+
+    converted_name[2] = value;
+    converted_name[3] = value >> 8;
+
+    for (offset = (4 - length) & 3; offset; offset--) converted_name[length + offset + 3] = 0x57;
+
+    *result = converted_name;
+
+    return (length + 7) & ~3;
+}
+
+/****************************************************************************
+ *	ctl2_encode_string
+ *
+ *  Encodes a string to a form suitable for storing into a type library or
+ *  comparing to a string stored in a type library.
+ *
+ * RETURNS
+ *
+ *  The length of the encoded string, including padding and length fields.
+ *
+ * NOTES
+ *
+ *  Will throw an exception if string or result are NULL. Is not multithread
+ *  safe in the slightest.
+ */
+static int ctl2_encode_string(
+	msft_typelib_t *typelib,   /* [I] The typelib to operate against (not used?). */
+	const char *string,        /* [I] The string to encode. */
+	char **result)             /* [O] A pointer to a pointer to receive the encoded string. */
+{
+    int length;
+    static char converted_string[0x104];
+    int offset;
+
+    length = strlen(string);
+    memcpy(converted_string + 2, string, length);
+    converted_string[0] = length & 0xff;
+    converted_string[1] = (length >> 8) & 0xff;
+
+    for (offset = (4 - (length + 2)) & 3; offset; offset--) converted_string[length + offset + 1] = 0x57;
+
+    *result = converted_string;
+
+    return (length + 5) & ~3;
+}
+
+/****************************************************************************
+ *	ctl2_alloc_segment
+ *
+ *  Allocates memory from a segment in a type library.
+ *
+ * RETURNS
+ *
+ *  Success: The offset within the segment of the new data area.
+ *  Failure: -1 (this is invariably an out of memory condition).
+ *
+ * BUGS
+ *
+ *  Does not (yet) handle the case where the allocated segment memory needs to grow.
+ */
+static int ctl2_alloc_segment(
+	msft_typelib_t *typelib,         /* [I] The type library in which to allocate. */
+	enum MSFT_segment_index segment, /* [I] The segment in which to allocate. */
+	int size,                        /* [I] The amount to allocate. */
+	int block_size)                  /* [I] Initial allocation block size, or 0 for default. */
+{
+    int offset;
+
+    if(!typelib->typelib_segment_data[segment]) {
+	if (!block_size) block_size = 0x2000;
+
+	typelib->typelib_segment_block_length[segment] = block_size;
+	typelib->typelib_segment_data[segment] = xmalloc(block_size);
+	if (!typelib->typelib_segment_data[segment]) return -1;
+	memset(typelib->typelib_segment_data[segment], 0x57, block_size);
+    }
+
+    while ((typelib->typelib_segdir[segment].length + size) > typelib->typelib_segment_block_length[segment]) {
+	char *block;
+
+	block_size = typelib->typelib_segment_block_length[segment];
+	block = realloc(typelib->typelib_segment_data[segment], block_size << 1);
+	if (!block) return -1;
+
+	if (segment == MSFT_SEG_TYPEINFO) {
+	    /* TypeInfos have a direct pointer to their memory space, so we have to fix them up. */
+	    msft_typeinfo_t *typeinfo;
+
+	    for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
+		typeinfo->typeinfo = (void *)&block[((char *)typeinfo->typeinfo) - typelib->typelib_segment_data[segment]];
+	    }
+	}
+
+	memset(block + block_size, 0x57, block_size);
+	typelib->typelib_segment_block_length[segment] = block_size << 1;
+	typelib->typelib_segment_data[segment] = block;
+    }
+
+    offset = typelib->typelib_segdir[segment].length;
+    typelib->typelib_segdir[segment].length += size;
+
+    return offset;
+}
+
+/****************************************************************************
+ *	ctl2_alloc_typeinfo
+ *
+ *  Allocates and initializes a typeinfo structure in a type library.
+ *
+ * RETURNS
+ *
+ *  Success: The offset of the new typeinfo.
+ *  Failure: -1 (this is invariably an out of memory condition).
+ */
+static int ctl2_alloc_typeinfo(
+	msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
+	int nameoffset)            /* [I] The offset of the name for this typeinfo. */
+{
+    int offset;
+    MSFT_TypeInfoBase *typeinfo;
+
+    offset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEINFO, sizeof(MSFT_TypeInfoBase), 0);
+    if (offset == -1) return -1;
+
+    typelib->typelib_typeinfo_offsets[typelib->typelib_header.nrtypeinfos++] = offset;
+
+    typeinfo = (void *)(typelib->typelib_segment_data[MSFT_SEG_TYPEINFO] + offset);
+
+    typeinfo->typekind = (typelib->typelib_header.nrtypeinfos - 1) << 16;
+    typeinfo->memoffset = -1; /* should be EOF if no elements */
+    typeinfo->res2 = 0;
+    typeinfo->res3 = -1;
+    typeinfo->res4 = 3;
+    typeinfo->res5 = 0;
+    typeinfo->cElement = 0;
+    typeinfo->res7 = 0;
+    typeinfo->res8 = 0;
+    typeinfo->res9 = 0;
+    typeinfo->resA = 0;
+    typeinfo->posguid = -1;
+    typeinfo->flags = 0;
+    typeinfo->NameOffset = nameoffset;
+    typeinfo->version = 0;
+    typeinfo->docstringoffs = -1;
+    typeinfo->helpstringcontext = 0;
+    typeinfo->helpcontext = 0;
+    typeinfo->oCustData = -1;
+    typeinfo->cbSizeVft = 0;
+    typeinfo->cImplTypes = 0;
+    typeinfo->size = 0;
+    typeinfo->datatype1 = -1;
+    typeinfo->datatype2 = 0;
+    typeinfo->res18 = 0;
+    typeinfo->res19 = -1;
+
+    return offset;
+}
+
+/****************************************************************************
+ *	ctl2_alloc_guid
+ *
+ *  Allocates and initializes a GUID structure in a type library. Also updates
+ *  the GUID hash table as needed.
+ *
+ * RETURNS
+ *
+ *  Success: The offset of the new GUID.
+ *  Failure: -1 (this is invariably an out of memory condition).
+ */
+static int ctl2_alloc_guid(
+	msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
+	MSFT_GuidEntry *guid)      /* [I] The GUID to store. */
+{
+    int offset;
+    MSFT_GuidEntry *guid_space;
+    int hash_key;
+
+    hash_key = ctl2_hash_guid(&guid->guid);
+
+    offset = ctl2_find_guid(typelib, hash_key, &guid->guid);
+    if (offset != -1) return offset;
+
+    offset = ctl2_alloc_segment(typelib, MSFT_SEG_GUID, sizeof(MSFT_GuidEntry), 0);
+    if (offset == -1) return -1;
+
+    guid_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_GUID] + offset);
+    *guid_space = *guid;
+
+    guid_space->next_hash = typelib->typelib_guidhash_segment[hash_key];
+    typelib->typelib_guidhash_segment[hash_key] = offset;
+
+    return offset;
+}
+
+/****************************************************************************
+ *	ctl2_alloc_name
+ *
+ *  Allocates and initializes a name within a type library. Also updates the
+ *  name hash table as needed.
+ *
+ * RETURNS
+ *
+ *  Success: The offset within the segment of the new name.
+ *  Failure: -1 (this is invariably an out of memory condition).
+ */
+static int ctl2_alloc_name(
+	msft_typelib_t *typelib,  /* [I] The type library to allocate in. */
+	const char *name)         /* [I] The name to store. */
+{
+    int length;
+    int offset;
+    MSFT_NameIntro *name_space;
+    char *encoded_name;
+
+    length = ctl2_encode_name(typelib, name, &encoded_name);
+
+    offset = ctl2_find_name(typelib, encoded_name);
+    if (offset != -1) return offset;
+
+    offset = ctl2_alloc_segment(typelib, MSFT_SEG_NAME, length + 8, 0);
+    if (offset == -1) return -1;
+
+    name_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_NAME] + offset);
+    name_space->hreftype = -1;
+    name_space->next_hash = -1;
+    memcpy(&name_space->namelen, encoded_name, length);
+
+    if (typelib->typelib_namehash_segment[encoded_name[2] & 0x7f] != -1)
+	name_space->next_hash = typelib->typelib_namehash_segment[encoded_name[2] & 0x7f];
+
+    typelib->typelib_namehash_segment[encoded_name[2] & 0x7f] = offset;
+
+    typelib->typelib_header.nametablecount += 1;
+    typelib->typelib_header.nametablechars += *encoded_name;
+
+    return offset;
+}
+
+/****************************************************************************
+ *	ctl2_alloc_string
+ *
+ *  Allocates and initializes a string in a type library.
+ *
+ * RETURNS
+ *
+ *  Success: The offset within the segment of the new string.
+ *  Failure: -1 (this is invariably an out of memory condition).
+ */
+static int ctl2_alloc_string(
+	msft_typelib_t *typelib,  /* [I] The type library to allocate in. */
+	const char *string)       /* [I] The string to store. */
+{
+    int length;
+    int offset;
+    char *string_space;
+    char *encoded_string;
+
+    length = ctl2_encode_string(typelib, string, &encoded_string);
+
+    for (offset = 0; offset < typelib->typelib_segdir[MSFT_SEG_STRING].length;
+	 offset += ((((typelib->typelib_segment_data[MSFT_SEG_STRING][offset + 1] << 8) & 0xff)
+	     | (typelib->typelib_segment_data[MSFT_SEG_STRING][offset + 0] & 0xff)) + 5) & ~3) {
+	if (!memcmp(encoded_string, typelib->typelib_segment_data[MSFT_SEG_STRING] + offset, length)) return offset;
+    }
+
+    offset = ctl2_alloc_segment(typelib, MSFT_SEG_STRING, length, 0);
+    if (offset == -1) return -1;
+
+    string_space = typelib->typelib_segment_data[MSFT_SEG_STRING] + offset;
+    memcpy(string_space, encoded_string, length);
+
+    return offset;
+}
+
+/****************************************************************************
+ *	ctl2_alloc_importinfo
+ *
+ *  Allocates and initializes an import information structure in a type library.
+ *
+ * RETURNS
+ *
+ *  Success: The offset of the new importinfo.
+ *  Failure: -1 (this is invariably an out of memory condition).
+ */
+static int ctl2_alloc_importinfo(
+        msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
+	MSFT_ImpInfo *impinfo)     /* [I] The import information to store. */
+{
+    int offset;
+    MSFT_ImpInfo *impinfo_space;
+
+    for (offset = 0;
+	 offset < typelib->typelib_segdir[MSFT_SEG_IMPORTINFO].length;
+	 offset += sizeof(MSFT_ImpInfo)) {
+	if (!memcmp(&(typelib->typelib_segment_data[MSFT_SEG_IMPORTINFO][offset]),
+		    impinfo, sizeof(MSFT_ImpInfo))) {
+	    return offset;
+	}
+    }
+
+    offset = ctl2_alloc_segment(typelib, MSFT_SEG_IMPORTINFO, sizeof(MSFT_ImpInfo), 0);
+    if (offset == -1) return -1;
+
+    impinfo_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_IMPORTINFO] + offset);
+    *impinfo_space = *impinfo;
+
+    return offset;
+}
+
+/****************************************************************************
+ *	ctl2_alloc_importfile
+ *
+ *  Allocates and initializes an import file definition in a type library.
+ *
+ * RETURNS
+ *
+ *  Success: The offset of the new importinfo.
+ *  Failure: -1 (this is invariably an out of memory condition).
+ */
+static int ctl2_alloc_importfile(
+	msft_typelib_t *typelib,   /* [I] The type library to allocate in. */
+	int guidoffset,            /* [I] The offset to the GUID for the imported library. */
+	int major_version,         /* [I] The major version number of the imported library. */
+	int minor_version,         /* [I] The minor version number of the imported library. */
+	const char *filename)      /* [I] The filename of the imported library. */
+{
+    int length;
+    int offset;
+    MSFT_ImpFile *importfile;
+    char *encoded_string;
+
+    length = ctl2_encode_string(typelib, filename, &encoded_string);
+
+    encoded_string[0] <<= 2;
+    encoded_string[0] |= 1;
+
+    for (offset = 0; offset < typelib->typelib_segdir[MSFT_SEG_IMPORTFILES].length;
+	 offset += ((((typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xd] << 8) & 0xff)
+	     | (typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xc] & 0xff)) >> 2) + 0xc) {
+	if (!memcmp(encoded_string, typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES] + offset + 0xc, length)) return offset;
+    }
+
+    offset = ctl2_alloc_segment(typelib, MSFT_SEG_IMPORTFILES, length + 0xc, 0);
+    if (offset == -1) return -1;
+
+    importfile = (MSFT_ImpFile *)&typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset];
+    importfile->guid = guidoffset;
+    importfile->lcid = typelib->typelib_header.lcid2;
+    importfile->version = major_version | (minor_version << 16);
+    memcpy(&importfile->filename, encoded_string, length);
+
+    return offset;
+}
+
+
+/****************************************************************************
+ *	ctl2_encode_typedesc
+ *
+ *  Encodes a type description, storing information in the TYPEDESC and ARRAYDESC
+ *  segments as needed.
+ *
+ * RETURNS
+ *
+ *  Success: 0.
+ *  Failure: -1.
+ */
+static int ctl2_encode_type(
+	msft_typelib_t *typelib,   /* [I] The type library in which to encode the TYPEDESC. */
+	type_t *type,              /* [I] The type description to encode. */
+        int ptr_level,             /* [I] ptr level */
+        expr_t *array,             /* [I] arrary description */
+	int *encoded_type,         /* [O] The encoded type description. */
+	int *width,                /* [O] The width of the type, or NULL. */
+	int *alignment,            /* [O] The alignment of the type, or NULL. */
+	int *decoded_size)         /* [O] The total size of the unencoded TYPEDESCs, including nested descs. */
+{
+    int default_type;
+    int scratch;
+    int typeoffset;
+    int arrayoffset;
+    int *typedata;
+    int *arraydata;
+    int target_type;
+    int child_size;
+    unsigned short vt = get_type_vt(type);
+
+    chat("encode_type vt %d ptr_level %d\n", vt, ptr_level);
+
+    default_type = 0x80000000 | (vt << 16) | vt;
+    if (!width) width = &scratch;
+    if (!alignment) alignment = &scratch;
+    if (!decoded_size) decoded_size = &scratch;
+
+    *decoded_size = 0;
+
+    if(ptr_level--) {
+
+	ctl2_encode_type(typelib, type, ptr_level, array, &target_type, NULL, NULL, &child_size);
+
+	for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
+	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+	    if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break;
+	}
+
+	if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
+	    int mix_field;
+	    
+	    if (target_type & 0x80000000) {
+		mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF;
+	    } else {
+		typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
+		mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
+	    }
+
+	    typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
+	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+
+	    typedata[0] = (mix_field << 16) | VT_PTR;
+	    typedata[1] = target_type;
+	}
+
+	*encoded_type = typeoffset;
+
+	*width = 4;
+	*alignment = 4;
+	*decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size;
+        return 0;
+    }
+
+    if(array) {
+        expr_t *dim = array;
+        int num_dims = 1, elements = 1;
+
+        while(NEXT_LINK(dim)) {
+            dim = NEXT_LINK(dim);
+            num_dims++;
+        }
+        chat("array with %d dimensions\n", num_dims);
+	ctl2_encode_type(typelib, type, 0, NULL, &target_type, width, alignment, NULL);
+	arrayoffset = ctl2_alloc_segment(typelib, MSFT_SEG_ARRAYDESC, (2 + 2 * num_dims) * sizeof(long), 0);
+	arraydata = (void *)&typelib->typelib_segment_data[MSFT_SEG_ARRAYDESC][arrayoffset];
+
+	arraydata[0] = target_type;
+        arraydata[1] = num_dims;
+        arraydata[1] |= ((num_dims * 2 * sizeof(long)) << 16);
+
+        arraydata += 2;
+        while(dim) {
+            arraydata[0] = dim->cval;
+            arraydata[1] = 0;
+            arraydata += 2;
+            elements *= dim->cval;
+            dim = PREV_LINK(dim);
+        }
+
+	typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
+	typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+
+	typedata[0] = (0x7ffe << 16) | VT_CARRAY;
+	typedata[1] = arrayoffset;
+
+	*encoded_type = typeoffset;
+	*width = *width * elements;
+	*decoded_size = 20 /*sizeof(ARRAYDESC)*/ + (num_dims - 1) * 8 /*sizeof(SAFEARRAYBOUND)*/;
+        return 0;
+    }
+
+    switch (vt) {
+    case VT_I1:
+    case VT_UI1:
+	*encoded_type = default_type;
+	*width = 1;
+	*alignment = 1;
+	break;
+
+    case VT_INT:
+	*encoded_type = 0x80000000 | (VT_I4 << 16) | VT_INT;
+	if ((typelib->typelib_header.varflags & 0x0f) == SYS_WIN16) {
+	    *width = 2;
+	    *alignment = 2;
+	} else {
+	    *width = 4;
+	    *alignment = 4;
+	}
+	break;
+
+    case VT_UINT:
+	*encoded_type = 0x80000000 | (VT_UI4 << 16) | VT_UINT;
+	if ((typelib->typelib_header.varflags & 0x0f) == SYS_WIN16) {
+	    *width = 2;
+	    *alignment = 2;
+	} else {
+	    *width = 4;
+	    *alignment = 4;
+	}
+	break;
+
+    case VT_UI2:
+    case VT_I2:
+    case VT_BOOL:
+	*encoded_type = default_type;
+	*width = 2;
+	*alignment = 2;
+	break;
+
+    case VT_I4:
+    case VT_UI4:
+    case VT_R4:
+    case VT_ERROR:
+    case VT_BSTR:
+    case VT_HRESULT:
+	*encoded_type = default_type;
+	*width = 4;
+	*alignment = 4;
+	break;
+
+    case VT_CY:
+	*encoded_type = default_type;
+	*width = 8;
+	*alignment = 4; /* guess? */
+	break;
+
+    case VT_VOID:
+	*encoded_type = 0x80000000 | (VT_EMPTY << 16) | vt;
+	*width = 0;
+	*alignment = 1;
+	break;
+
+#if 0
+
+
+    case VT_SAFEARRAY:
+	/* FIXME: Make with the error checking. */
+	FIXME("SAFEARRAY vartype, may not work correctly.\n");
+
+	ctl2_encode_typedesc(typelib, tdesc->u.lptdesc, &target_type, NULL, NULL, &child_size);
+
+	for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
+	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+	    if (((typedata[0] & 0xffff) == VT_SAFEARRAY) && (typedata[1] == target_type)) break;
+	}
+
+	if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
+	    int mix_field;
+	    
+	    if (target_type & 0x80000000) {
+		mix_field = ((target_type >> 16) & VT_TYPEMASK) | VT_ARRAY;
+	    } else {
+		typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
+		mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
+	    }
+
+	    typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
+	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+
+	    typedata[0] = (mix_field << 16) | VT_SAFEARRAY;
+	    typedata[1] = target_type;
+	}
+
+	*encoded_tdesc = typeoffset;
+
+	*width = 4;
+	*alignment = 4;
+	*decoded_size = sizeof(TYPEDESC) + child_size;
+	break;
+
+
+#endif
+
+    case VT_USERDEFINED:
+      {
+        int typeinfo_offset;
+	chat("USERDEFINED.\n");
+        chat("type %p name = %s idx %d\n", type, type->name, type->typelib_idx);
+
+        if(type->typelib_idx == -1)
+            error("trying to ref not added type\n");
+
+        typeinfo_offset = typelib->typelib_typeinfo_offsets[type->typelib_idx];
+	for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
+	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+	    if ((typedata[0] == ((0x7fff << 16) | VT_USERDEFINED)) && (typedata[1] == typeinfo_offset)) break;
+	}
+
+	if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
+	    typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0);
+	    typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
+
+	    typedata[0] = (0x7fff << 16) | VT_USERDEFINED;
+	    typedata[1] = typeinfo_offset;
+	}
+
+	*encoded_type = typeoffset;
+	*width = 0;
+	*alignment = 1;
+	break;
+      }
+
+    default:
+	error("Unrecognized type %d.\n", vt);
+	*encoded_type = default_type;
+	*width = 0;
+	*alignment = 1;
+	break;
+    }
+
+    return 0;
+}
+
+/****************************************************************************
+ *	ctl2_find_nth_reference
+ *
+ *  Finds a reference by index into the linked list of reference records.
+ *
+ * RETURNS
+ *
+ *  Success: Offset of the desired reference record.
+ *  Failure: -1.
+ */
+static int ctl2_find_nth_reference(
+	msft_typelib_t *typelib,   /* [I] The type library in which to search. */
+	int offset,                /* [I] The starting offset of the reference list. */
+	int index)                 /* [I] The index of the reference to find. */
+{
+    MSFT_RefRecord *ref;
+
+    for (; index && (offset != -1); index--) {
+	ref = (MSFT_RefRecord *)&typelib->typelib_segment_data[MSFT_SEG_REFERENCES][offset];
+	offset = ref->onext;
+    }
+
+    return offset;
+}
+
+
+static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, func_t *func)
+{
+    int offset;
+    int *typedata;
+    int i, index = func->idx, id;
+    int decoded_size;
+    int num_params = 0;
+    var_t *arg, *last_arg = NULL;
+    char *namedata;
+    attr_t *attr;
+    unsigned int funcflags = 0, callconv = 4;
+
+    id = ((0x6000 | typeinfo->typeinfo->cImplTypes) << 16) | index;
+
+    chat("(%p,%d)\n", typeinfo, index);
+    
+    if (!typeinfo->typedata) {
+	typeinfo->typedata = xmalloc(0x2000);
+	typeinfo->typedata[0] = 0;
+    }
+
+    for(arg = func->args; arg; arg = NEXT_LINK(arg)) {
+        last_arg = arg;
+        num_params++;
+    }
+
+    chat("num of params %d\n", num_params);
+
+    for(attr = func->def->attrs; attr; attr = NEXT_LINK(attr)) {
+        switch(attr->type) {
+        case ATTR_ID:
+          {
+            expr_t *expr = attr->u.pval; 
+            id = expr->u.lval;
+            break;
+          }
+        case ATTR_OUT:
+            break;
+
+        default:
+            warning("ignoring attr %d\n", attr->type);
+            break;
+        }
+    }
+    /* allocate type data space for us */
+    offset = typeinfo->typedata[0];
+    typeinfo->typedata[0] += 0x18 + (num_params * 12);
+    typedata = typeinfo->typedata + (offset >> 2) + 1;
+
+    /* fill out the basic type information */
+    typedata[0] = (0x18 + (num_params * 12)) | (index << 16);
+    ctl2_encode_type(typeinfo->typelib, func->def->type, func->def->ptr_level, func->def->array, &typedata[1], NULL, NULL, &decoded_size);
+    typedata[2] = funcflags;
+    typedata[3] = ((52 /*sizeof(FUNCDESC)*/ + decoded_size) << 16) | typeinfo->typeinfo->cbSizeVft;
+    typedata[4] = (index << 16) | (callconv << 8) | 9;
+    typedata[5] = num_params;
+
+    /* NOTE: High word of typedata[3] is total size of FUNCDESC + size of all ELEMDESCs for params + TYPEDESCs for pointer params and return types. */
+    /* That is, total memory allocation required to reconstitute the FUNCDESC in its entirety. */
+    typedata[3] += (16 /*sizeof(ELEMDESC)*/ * num_params) << 16;
+
+    for (arg = last_arg, i = 0; arg; arg = PREV_LINK(arg), i++) {
+        attr_t *attr;
+        int paramflags = 0;
+
+        for(attr = arg->attrs; attr; attr = NEXT_LINK(attr)) {
+            switch(attr->type) {
+            case ATTR_IN:
+                paramflags |= 0x01; /* PARAMFLAG_FIN */
+                break;
+            case ATTR_OUT:
+                paramflags |= 0x02; /* PARAMFLAG_FOUT */
+                break;
+            case ATTR_RETVAL:
+                paramflags |= 0x08; /* PARAMFLAG_FRETVAL */
+                break;
+            default:
+                chat("unhandled param attr %d\n", attr->type);
+                break;
+            }
+        }
+	ctl2_encode_type(typeinfo->typelib, arg->type, arg->ptr_level, arg->array, &typedata[6+(i*3)], NULL, NULL, &decoded_size);
+	typedata[7+(i*3)] = -1;
+	typedata[8+(i*3)] = paramflags;
+	typedata[3] += decoded_size << 16;
+
+#if 0
+	/* FIXME: Doesn't work. Doesn't even come up with usable VTs for varDefaultValue. */
+	if (pFuncDesc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) {
+	    ctl2_alloc_custdata(This->typelib, &pFuncDesc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
+	}
+#endif
+    }
+
+    /* update the index data */
+    typeinfo->indices[index] = id; 
+    typeinfo->names[index] = -1;
+    typeinfo->offsets[index] = offset;
+
+    /* ??? */
+    if (!typeinfo->typeinfo->res2) typeinfo->typeinfo->res2 = 0x20;
+    typeinfo->typeinfo->res2 <<= 1;
+
+    /* ??? */
+    if (typeinfo->typeinfo->res3 == -1) typeinfo->typeinfo->res3 = 0;
+    typeinfo->typeinfo->res3 += 0x38;
+
+    /* ??? */
+    if (index < 2) typeinfo->typeinfo->res2 += num_params << 4;
+    typeinfo->typeinfo->res3 += num_params << 4;
+
+    /* adjust size of VTBL */
+    typeinfo->typeinfo->cbSizeVft += 4;
+
+    /* Increment the number of function elements */
+    typeinfo->typeinfo->cElement += 1;
+
+
+    offset = ctl2_alloc_name(typeinfo->typelib, func->def->name);
+    chat("name offset = %d index %d\n", offset, index);
+    typeinfo->names[index] = offset;
+
+    namedata = typeinfo->typelib->typelib_segment_data[MSFT_SEG_NAME] + offset;
+    namedata[9] &= ~0x10;
+    if (*((INT *)namedata) == -1) {
+	*((INT *)namedata) = typeinfo->typelib->typelib_typeinfo_offsets[typeinfo->typeinfo->typekind >> 16];
+    }
+
+    for (arg = last_arg, i = 0; arg; arg = PREV_LINK(arg), i++) {
+	/* FIXME: Almost certainly easy to break */
+	int *paramdata = &typeinfo->typedata[typeinfo->offsets[index] >> 2];
+        
+	offset = ctl2_alloc_name(typeinfo->typelib, arg->name);
+	paramdata[(i * 3) + 8] = offset;
+        chat("param %d name %s offset %d\n", i, arg->name, offset);
+    }
+    return S_OK;
+}
+
+
+static void set_alignment(
+        msft_typeinfo_t* typeinfo,
+        WORD cbAlignment)
+{
+
+    if (!cbAlignment) return;
+    if (cbAlignment > 16) return;
+
+    typeinfo->typeinfo->typekind &= ~0xffc0;
+    typeinfo->typeinfo->typekind |= cbAlignment << 6;
+
+    /* FIXME: There's probably some way to simplify this. */
+    switch (typeinfo->typeinfo->typekind & 15) {
+    case TKIND_ALIAS:
+    default:
+	break;
+
+    case TKIND_ENUM:
+    case TKIND_INTERFACE:
+    case TKIND_DISPATCH:
+    case TKIND_COCLASS:
+	if (cbAlignment > 4) cbAlignment = 4;
+	break;
+
+    case TKIND_RECORD:
+    case TKIND_MODULE:
+    case TKIND_UNION:
+	cbAlignment = 1;
+	break;
+    }
+
+    typeinfo->typeinfo->typekind |= cbAlignment << 11;
+
+    return;
+}
+
+static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var)
+{
+    int offset;
+    INT *typedata;
+    int var_datawidth;
+    int var_alignment;
+    int var_type_size;
+    int alignment;
+    int varflags = 0;
+    attr_t *attr;
+    char *namedata;
+
+    chat("add_var_desc(%d,%s) array %p\n", index, var->name, var->array);
+
+    if ((typeinfo->typeinfo->cElement >> 16) != index) {
+	error("Out-of-order element.\n");
+	return TYPE_E_ELEMENTNOTFOUND;
+    }
+
+
+    for(attr = var->attrs; attr; attr = NEXT_LINK(attr)) {
+        switch(attr->type) {
+        default:
+            warning("AddVarDesc: unhandled attr type %d\n", attr->type);
+            break;
+        }
+    }
+
+    if (!typeinfo->typedata) {
+	typeinfo->typedata = xmalloc(0x2000);
+	typeinfo->typedata[0] = 0;
+    }
+
+    /* allocate type data space for us */
+    offset = typeinfo->typedata[0];
+    typeinfo->typedata[0] += 0x14;
+    typedata = typeinfo->typedata + (offset >> 2) + 1;
+
+    /* fill out the basic type information */
+    typedata[0] = 0x14 | (index << 16);
+    typedata[2] = varflags;
+    typedata[3] = (36 /*sizeof(VARDESC)*/ << 16) | 0;
+
+    /* update the index data */
+    typeinfo->indices[index] = 0x40000000 + index;
+    typeinfo->names[index] = -1;
+    typeinfo->offsets[index] = offset;
+
+    /* figure out type widths and whatnot */
+    ctl2_encode_type(typeinfo->typelib, var->type, var->ptr_level, var->array,
+                     &typedata[1], &var_datawidth, &var_alignment,
+                     &var_type_size);
+
+    /* pad out starting position to data width */
+    typeinfo->datawidth += var_alignment - 1;
+    typeinfo->datawidth &= ~(var_alignment - 1);
+    typedata[4] = typeinfo->datawidth;
+    
+    /* add the new variable to the total data width */
+    typeinfo->datawidth += var_datawidth;
+
+    /* add type description size to total required allocation */
+    typedata[3] += var_type_size << 16;
+
+    /* fix type alignment */
+    alignment = (typeinfo->typeinfo->typekind >> 11) & 0x1f;
+    if (alignment < var_alignment) {
+	alignment = var_alignment;
+	typeinfo->typeinfo->typekind &= ~0xf800;
+	typeinfo->typeinfo->typekind |= alignment << 11;
+    }
+
+    /* ??? */
+    if (!typeinfo->typeinfo->res2) typeinfo->typeinfo->res2 = 0x1a;
+    if ((index == 0) || (index == 1) || (index == 2) || (index == 4) || (index == 9)) {
+	typeinfo->typeinfo->res2 <<= 1;
+    }
+
+    /* ??? */
+    if (typeinfo->typeinfo->res3 == -1) typeinfo->typeinfo->res3 = 0;
+    typeinfo->typeinfo->res3 += 0x2c;
+
+    /* increment the number of variable elements */
+    typeinfo->typeinfo->cElement += 0x10000;
+
+    /* pad data width to alignment */
+    typeinfo->typeinfo->size = (typeinfo->datawidth + (alignment - 1)) & ~(alignment - 1);
+
+    offset = ctl2_alloc_name(typeinfo->typelib, var->name);
+    if (offset == -1) return E_OUTOFMEMORY;
+
+    namedata = typeinfo->typelib->typelib_segment_data[MSFT_SEG_NAME] + offset;
+    if (*((INT *)namedata) == -1) {
+	*((INT *)namedata) = typeinfo->typelib->typelib_typeinfo_offsets[typeinfo->typeinfo->typekind >> 16];
+	namedata[9] |= 0x10;
+    }
+    if ((typeinfo->typeinfo->typekind & 15) == TKIND_ENUM) {
+	namedata[9] |= 0x20;
+    }
+    typeinfo->names[index] = offset;
+
+    return S_OK;
+}
+
+
+static msft_typeinfo_t *create_msft_typeinfo(msft_typelib_t *typelib, typelib_entry_t *entry, int idx)
+{
+    msft_typeinfo_t *msft_typeinfo;
+    int nameoffset;
+    int typeinfo_offset;
+    MSFT_TypeInfoBase *typeinfo;
+    char *name;
+    MSFT_GuidEntry guidentry;
+    attr_t *attr;
+
+    switch(entry->kind) {
+    case TKIND_INTERFACE:
+        name = entry->u.interface->name;
+        attr = entry->u.interface->attrs;
+        entry->u.interface->typelib_idx = idx;
+        break;
+    case TKIND_MODULE:
+        name = entry->u.module->name;
+        attr = entry->u.module->attrs;
+        break;
+    case TKIND_COCLASS:
+        name = entry->u.class->name;
+        attr = entry->u.class->attrs;
+        break;
+    case TKIND_RECORD:
+        name = entry->u.structure->name;
+        attr = entry->u.structure->attrs;
+        entry->u.structure->typelib_idx = idx;
+        chat("type = %p\n", entry->u.structure);
+        break;
+    default:
+        error("create_msft_typeinfo: unhandled type %d\n", entry->kind);
+        return NULL;
+    }
+
+
+    chat("Constructing msft_typeinfo for name %s kind %d\n", name, entry->kind);
+
+    msft_typeinfo = xmalloc(sizeof(*msft_typeinfo));
+
+    msft_typeinfo->typelib = typelib;
+
+    nameoffset = ctl2_alloc_name(typelib, name);
+    typeinfo_offset = ctl2_alloc_typeinfo(typelib, nameoffset);
+    typeinfo = (MSFT_TypeInfoBase *)&typelib->typelib_segment_data[MSFT_SEG_TYPEINFO][typeinfo_offset];
+
+    typelib->typelib_segment_data[MSFT_SEG_NAME][nameoffset + 9] = 0x38;
+    *((int *)&typelib->typelib_segment_data[MSFT_SEG_NAME][nameoffset]) = typeinfo_offset;
+
+    msft_typeinfo->typeinfo = typeinfo;
+
+    typeinfo->typekind |= entry->kind | 0x20;
+    set_alignment(msft_typeinfo, 4);
+
+    switch (entry->kind) {
+    case TKIND_ENUM:
+    case TKIND_INTERFACE:
+    case TKIND_DISPATCH:
+    case TKIND_COCLASS:
+	typeinfo->size = 4;
+	break;
+
+    case TKIND_RECORD:
+    case TKIND_UNION:
+	typeinfo->size = 0;
+	break;
+
+    case TKIND_MODULE:
+	typeinfo->size = 2;
+	break;
+
+    case TKIND_ALIAS:
+	typeinfo->size = -0x75;
+	break;
+
+    default:
+	error("%s unrecognized typekind %d\n", name, entry->kind);
+	typeinfo->size = 0xdeadbeef;
+	break;
+    }
+
+
+    for( ; attr; attr = NEXT_LINK(attr)) {
+        if(attr->type == ATTR_UUID) {
+            guidentry.guid = *(GUID*)attr->u.pval;
+            guidentry.hreftype = typelib->typelib_typeinfo_offsets[typeinfo->typekind >> 16];
+            guidentry.next_hash = -1;
+            typeinfo->posguid = ctl2_alloc_guid(typelib, &guidentry);
+#if 0
+            if (IsEqualIID(guid, &IID_IDispatch)) {
+                typelib->typelib_header.dispatchpos = typelib->typelib_typeinfo_offsets[typeinfo->typekind >> 16];
+            }
+#endif
+        }
+    }
+
+    if (typelib->last_typeinfo) typelib->last_typeinfo->next_typeinfo = msft_typeinfo;
+    typelib->last_typeinfo = msft_typeinfo;
+    if (!typelib->typeinfos) typelib->typeinfos = msft_typeinfo;
+
+
+    return msft_typeinfo;
+}
+
+
+static void set_name(msft_typelib_t *typelib)
+{
+    int offset;
+
+    offset = ctl2_alloc_name(typelib, typelib->typelib->name);
+    if (offset == -1) return;
+    typelib->typelib_header.NameOffset = offset;
+    return;
+}
+
+static void set_version(msft_typelib_t *typelib)
+{
+    long version = MAKELONG(0,0);
+    attr_t *attr;
+
+    for(attr = typelib->typelib->attrs; attr; attr = NEXT_LINK(attr)) {
+        if(attr->type == ATTR_VERSION) {
+            version = attr->u.ival;
+        }
+    }
+    typelib->typelib_header.version = version;
+    return;
+}
+
+static void set_guid(msft_typelib_t *typelib)
+{
+    MSFT_GuidEntry guidentry;
+    int offset;
+    attr_t *attr;
+    GUID guid = {0,0,0,{0,0,0,0,0,0}};
+
+    guidentry.guid = guid;
+    guidentry.hreftype = -2;
+    guidentry.next_hash = -1;
+
+    for(attr = typelib->typelib->attrs; attr; attr = NEXT_LINK(attr)) {
+        if(attr->type == ATTR_UUID) {
+            guidentry.guid = *(GUID*)(attr->u.pval);
+        }
+    }
+
+    offset = ctl2_alloc_guid(typelib, &guidentry);
+    
+    if (offset == -1) return;
+
+    typelib->typelib_header.posguid = offset;
+
+    return;
+}
+
+static void set_doc_string(msft_typelib_t *typelib)
+{
+    attr_t *attr;
+    int offset;
+
+    for(attr = typelib->typelib->attrs; attr; attr = NEXT_LINK(attr)) {
+        if(attr->type == ATTR_HELPSTRING) {
+            offset = ctl2_alloc_string(typelib, attr->u.pval);
+            if (offset == -1) return;
+            typelib->typelib_header.helpstring = offset;
+        }
+    }
+    return;
+}
+
+static void set_help_file_name(msft_typelib_t *typelib)
+{
+    int offset;
+    offset = ctl2_alloc_string(typelib, "help file name");
+    if (offset == -1) return;
+    typelib->typelib_header.helpfile = offset;
+    typelib->typelib_header.varflags |= 0x10;
+    return;
+}
+
+static void set_lcid(msft_typelib_t *typelib)
+{
+    typelib->typelib_header.lcid2 = 0x0;
+    return;
+}
+
+static void set_lib_flags(msft_typelib_t *typelib)
+{
+    typelib->typelib_header.flags = 0;
+    return;
+}
+
+static int ctl2_write_chunk(int fd, void *segment, int length)
+{
+    if (write(fd, segment, length) != length) {
+        close(fd);
+        return 0;
+    }
+    return -1;
+}
+
+static int ctl2_write_segment(msft_typelib_t *typelib, int fd, int segment)
+{
+    if (write(fd, typelib->typelib_segment_data[segment], typelib->typelib_segdir[segment].length)
+        != typelib->typelib_segdir[segment].length) {
+	close(fd);
+	return 0;
+    }
+
+    return -1;
+}
+
+static void ctl2_finalize_typeinfos(msft_typelib_t *typelib, int filesize)
+{
+    msft_typeinfo_t *typeinfo;
+
+    for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
+	typeinfo->typeinfo->memoffset = filesize;
+	if (typeinfo->typedata) {
+	    /*LayOut(typeinfo);*/
+	    filesize += typeinfo->typedata[0] + ((typeinfo->typeinfo->cElement >> 16) * 12) + ((typeinfo->typeinfo->cElement & 0xffff) * 12) + 4;
+	}
+    }
+}
+
+static int ctl2_finalize_segment(msft_typelib_t *typelib, int filepos, int segment)
+{
+    if (typelib->typelib_segdir[segment].length) {
+	typelib->typelib_segdir[segment].offset = filepos;
+    } else {
+	typelib->typelib_segdir[segment].offset = -1;
+    }
+
+    return typelib->typelib_segdir[segment].length;
+}
+
+
+static void ctl2_write_typeinfos(msft_typelib_t *typelib, int fd)
+{
+    msft_typeinfo_t *typeinfo;
+
+    for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
+	if (!typeinfo->typedata) continue;
+
+	ctl2_write_chunk(fd, typeinfo->typedata, typeinfo->typedata[0] + 4);
+	ctl2_write_chunk(fd, typeinfo->indices, ((typeinfo->typeinfo->cElement & 0xffff) + (typeinfo->typeinfo->cElement >> 16)) * 4);
+        chat("writing name chunk len %d %08lx\n", ((typeinfo->typeinfo->cElement & 0xffff) + (typeinfo->typeinfo->cElement >> 16)) * 4, *(DWORD*)typeinfo->names);
+	ctl2_write_chunk(fd, typeinfo->names, ((typeinfo->typeinfo->cElement & 0xffff) + (typeinfo->typeinfo->cElement >> 16)) * 4);
+	ctl2_write_chunk(fd, typeinfo->offsets, ((typeinfo->typeinfo->cElement & 0xffff) + (typeinfo->typeinfo->cElement >> 16)) * 4);
+    }
+}
+
+static int save_all_changes(msft_typelib_t *typelib)
+{
+    int retval;
+    int filepos;
+    int fd;
+
+    chat("save_all_changes(%p)\n", typelib);
+
+    retval = TYPE_E_IOERROR;
+
+    fd = creat(typelib->typelib->filename, 0666);
+    if (fd == -1) return retval;
+
+    filepos = sizeof(MSFT_Header) + sizeof(MSFT_SegDir);
+    filepos += typelib->typelib_header.nrtypeinfos * 4;
+
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_TYPEINFO);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_GUIDHASH);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_GUID);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_IMPORTINFO);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_IMPORTFILES);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_REFERENCES);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_NAMEHASH);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_NAME);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_STRING);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_TYPEDESC);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_ARRAYDESC);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_CUSTDATA);
+    filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_CUSTDATAGUID);
+
+    ctl2_finalize_typeinfos(typelib, filepos);
+
+    if (!ctl2_write_chunk(fd, &typelib->typelib_header, sizeof(typelib->typelib_header))) return retval;
+    if (!ctl2_write_chunk(fd, typelib->typelib_typeinfo_offsets, typelib->typelib_header.nrtypeinfos * 4)) return retval;
+    if (!ctl2_write_chunk(fd, &typelib->typelib_segdir, sizeof(typelib->typelib_segdir))) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_TYPEINFO    )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_GUIDHASH    )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_GUID        )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_IMPORTINFO  )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_IMPORTFILES )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_REFERENCES  )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_NAMEHASH    )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_NAME        )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_STRING      )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_TYPEDESC    )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_ARRAYDESC   )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_CUSTDATA    )) return retval;
+    if (!ctl2_write_segment(typelib, fd, MSFT_SEG_CUSTDATAGUID)) return retval;
+
+    ctl2_write_typeinfos(typelib, fd);
+
+    if (close(fd) == -1) return retval;
+
+    retval = S_OK;
+    return retval;
+}
+
+
+
+
+int create_msft_typelib(typelib_t *typelib)
+{
+    msft_typelib_t *msft;
+    int failed = 0, typelib_idx;
+    typelib_entry_t *entry;
+
+    msft = malloc(sizeof(*msft));
+    if (!msft) return 0;
+    memset(msft, 0, sizeof(*msft));
+    msft->typelib = typelib;
+
+    ctl2_init_header(msft);
+    ctl2_init_segdir(msft);
+
+    msft->typelib_header.varflags |= SYS_WIN32;
+
+    /*
+     * The following two calls return an offset or -1 if out of memory. We
+     * specifically need an offset of 0, however, so...
+     */
+    if (ctl2_alloc_segment(msft, MSFT_SEG_GUIDHASH, 0x80, 0x80)) { failed = 1; }
+    if (ctl2_alloc_segment(msft, MSFT_SEG_NAMEHASH, 0x200, 0x200)) { failed = 1; }
+
+    if(failed) return 0;
+
+    msft->typelib_guidhash_segment = (int *)msft->typelib_segment_data[MSFT_SEG_GUIDHASH];
+    msft->typelib_namehash_segment = (int *)msft->typelib_segment_data[MSFT_SEG_NAMEHASH];
+
+    memset(msft->typelib_guidhash_segment, 0xff, 0x80);
+    memset(msft->typelib_namehash_segment, 0xff, 0x200);
+
+    set_lib_flags(msft);
+    set_lcid(msft);
+/*    set_help_file_name(msft);*/
+    set_doc_string(msft);
+    set_guid(msft);
+    set_version(msft);
+    set_name(msft);
+
+    typelib_idx = 0;
+    for(entry = typelib->entry; NEXT_LINK(entry); entry = NEXT_LINK(entry))
+        ;
+    for( ; entry; entry = PREV_LINK(entry)) {
+        msft_typeinfo_t *msft_typeinfo = create_msft_typeinfo(msft, entry, typelib_idx);
+        switch(entry->kind) {
+        case TKIND_INTERFACE:
+          {
+            int idx = 0;
+            func_t *cur = entry->u.interface->funcs;
+            while(NEXT_LINK(cur)) cur = NEXT_LINK(cur);
+            while(cur) {
+                if(cur->idx == -1) cur->idx = idx;
+                else if(cur->idx != idx) error("method index mismatch\n");
+                add_func_desc(msft_typeinfo, cur);
+                idx++;
+                cur = PREV_LINK(cur);
+            }
+            break;
+          }
+        case TKIND_RECORD:
+          {
+            int idx = 0;
+            var_t *cur = entry->u.structure->fields;
+            while(NEXT_LINK(cur)) cur = NEXT_LINK(cur);
+            while(cur) {
+                add_var_desc(msft_typeinfo, idx, cur);
+                idx++;
+                cur = PREV_LINK(cur);
+            }
+            break;
+          }
+                
+        default:
+            error("create_msft_typelib: unhandled type %d\n", entry->kind);
+            break;
+        }
+        typelib_idx++;
+    }
+    save_all_changes(msft);
+    return 1;
+}
+
--- /dev/null	2004-02-23 21:02:56.000000000 +0000
+++ tools/widl/typelib_struct.h	2005-01-06 14:37:19.239246216 +0000
@@ -0,0 +1,591 @@
+/*
+ * typelib_struct.h  internal wine data structures
+ * used to decode typelib's
+ *
+ * Copyright 1999 Rein KLazes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _WIDL_TYPELIB_STRUCT_H
+#define _WIDL_TYPELIB_STRUCT_H
+
+#define HELPDLLFLAG (0x0100)
+#define DO_NOT_SEEK (-1)
+
+#define MSFT_HREFTYPE_INTHISFILE(href) (!((href) & 3))
+#define MSFT_HREFTYPE_INDEX(href) ((href) /sizeof(MSFT_TypeInfoBase))
+
+/*-------------------------FILE STRUCTURES-----------------------------------*/
+
+/* There are two known file formats, those created with ICreateTypeLib
+ * have the signature "SLTG" as their first four bytes, while those created
+ * with ICreateTypeLib2 have "MSFT".
+ */
+
+/*****************************************************
+ *                MSFT typelibs
+ *
+ * These are TypeLibs created with ICreateTypeLib2
+ *
+ */
+
+/*
+ * structure of the typelib type2 header
+ * it is at the beginning of a type lib file
+ *
+ */
+typedef struct tagMSFT_Header {
+/*0x00*/INT magic1;       /* 0x5446534D "MSFT" */
+        INT   magic2;       /* 0x00010002 version nr? */
+        INT   posguid;      /* position of libid in guid table  */
+                            /* (should be,  else -1) */
+        INT   lcid;         /* locale id */
+/*0x10*/INT   lcid2;
+        INT   varflags;     /* (largely) unknown flags ,seems to be always 41 */
+                            /* becomes 0x51 with a helpfile defined */
+                            /* if help dll defined it's 0x151 */
+                            /* update : the lower nibble is syskind */
+        INT   version;      /* set with SetVersion() */
+        INT   flags;        /* set with SetFlags() */
+/*0x20*/INT   nrtypeinfos;  /* number of typeinfo's (till so far) */
+        INT   helpstring;   /* position of help string in stringtable */
+        INT   helpstringcontext;
+        INT   helpcontext;
+/*0x30*/INT   nametablecount;   /* number of names in name table */
+        INT   nametablechars;   /* nr of characters in name table */
+        INT   NameOffset;       /* offset of name in name table */
+        INT   helpfile;         /* position of helpfile in stringtable */
+/*0x40*/INT   CustomDataOffset; /* if -1 no custom data, else it is offset */
+                                /* in customer data/guid offset table */
+        INT   res44;            /* unknown always: 0x20 (guid hash size?) */
+        INT   res48;            /* unknown always: 0x80 (name hash size?) */
+        INT   dispatchpos;      /* HREFTYPE to IDispatch, or -1 if no IDispatch */
+/*0x50*/INT   res50;            /* is zero becomes one when an interface is derived */
+} MSFT_Header;
+
+/* segments in the type lib file have a structure like this: */
+typedef struct tagMSFT_pSeg {
+        INT   offset;       /* absolute offset in file */
+        INT   length;       /* length of segment */
+        INT   res08;        /* unknown always -1 */
+        INT   res0c;        /* unknown always 0x0f in the header */
+                            /* 0x03 in the typeinfo_data */
+} MSFT_pSeg;
+
+/* layout of the main segment directory */
+typedef struct tagMSFT_SegDir {
+/*1*/MSFT_pSeg pTypeInfoTab; /* each type info get an entry of 0x64 bytes */
+                             /* (25 ints) */
+/*2*/MSFT_pSeg pImpInfo;     /* table with info for imported types */
+/*3*/MSFT_pSeg pImpFiles;    /* import libaries */
+/*4*/MSFT_pSeg pRefTab;      /* References table */
+/*5*/MSFT_pSeg pLibtab;      /* always exists, alway same size (0x80) */
+                             /* hash table w offsets to guid????? */
+/*6*/MSFT_pSeg pGuidTab;     /* all guids are stored here together with  */
+                             /* offset in some table???? */
+/*7*/MSFT_pSeg res07;        /* always created, alway same size (0x200) */
+                             /* purpose largely unknown */
+/*8*/MSFT_pSeg pNametab;     /* name tables */
+/*9*/MSFT_pSeg pStringtab;   /* string table */
+/*A*/MSFT_pSeg pTypdescTab;  /* table with type descriptors */
+/*B*/MSFT_pSeg pArrayDescriptions;
+/*C*/MSFT_pSeg pCustData;    /* data table, used for custom data and default */
+                             /* parameter values */
+/*D*/MSFT_pSeg pCDGuids;     /* table with offsets for the guids and into */
+                             /* the customer data table */
+/*E*/MSFT_pSeg res0e;        /* unknown */
+/*F*/MSFT_pSeg res0f;        /* unknown  */
+} MSFT_SegDir;
+
+
+/* base type info data */
+typedef struct tagMSFT_TypeInfoBase {
+/*000*/ INT   typekind;             /*  it is the TKIND_xxx */
+                                    /* some byte alignment stuf */
+        INT     memoffset;          /* points past the file, if no elements */
+        INT     res2;               /* zero if no element, N*0x40 */
+        INT     res3;               /* -1 if no lement, (N-1)*0x38 */
+/*010*/ INT     res4;               /* always? 3 */
+        INT     res5;               /* always? zero */
+        INT     cElement;           /* counts elements, HI=cVars, LO=cFuncs */
+        INT     res7;               /* always? zero */
+/*020*/ INT     res8;               /* always? zero */
+        INT     res9;               /* always? zero */
+        INT     resA;               /* always? zero */
+        INT     posguid;            /* position in guid table */
+/*030*/ INT     flags;              /* Typeflags */
+        INT     NameOffset;         /* offset in name table */
+        INT     version;            /* element version */
+        INT     docstringoffs;      /* offset of docstring in string tab */
+/*040*/ INT     helpstringcontext;  /*  */
+        INT     helpcontext;    /* */
+        INT     oCustData;          /* offset in customer data table */
+#ifdef WORDS_BIGENDIAN
+        INT16   cbSizeVft;      /* virtual table size, not including inherits */
+        INT16   cImplTypes;     /* nr of implemented interfaces */
+#else
+        INT16   cImplTypes;     /* nr of implemented interfaces */
+        INT16   cbSizeVft;      /* virtual table size, not including inherits */
+#endif
+/*050*/ INT     size;           /* size in bytes, at least for structures */
+        /* FIXME: name of this field */
+        INT     datatype1;      /* position in type description table */
+                                /* or in base intefaces */
+                                /* if coclass: offset in reftable */
+                                /* if interface: reference to inherited if */
+        INT     datatype2;      /* if 0x8000, entry above is valid */
+                                /* actually dunno */
+                                /* else it is zero? */
+        INT     res18;          /* always? 0 */
+/*060*/ INT     res19;          /* always? -1 */
+    } MSFT_TypeInfoBase;
+
+/* layout of an entry with information on imported types */
+typedef struct tagMSFT_ImpInfo {
+    INT     res0;           /* unknown */
+    INT     oImpFile;       /* offset inthe Import File table */
+    INT     oGuid;          /* offset in Guid table */
+    } MSFT_ImpInfo;
+
+/* function description data */
+typedef struct {
+/*  INT   recsize;       record size including some xtra stuff */
+    INT   DataType;     /* data type of the memeber, eg return of function */
+    INT   Flags;        /* something to do with attribute flags (LOWORD) */
+#ifdef WORDS_BIGENDIAN
+    INT16 funcdescsize; /* size of reconstituted FUNCDESC and related structs */
+    INT16 VtableOffset; /* offset in vtable */
+#else
+    INT16 VtableOffset; /* offset in vtable */
+    INT16 funcdescsize; /* size of reconstituted FUNCDESC and related structs */
+#endif
+    INT   FKCCIC;       /* bit string with the following  */
+                        /* meaning (bit 0 is the msb): */
+                        /* bit 2 indicates that oEntry is numeric */
+                        /* bit 3 that parameter has default values */
+                        /* calling convention (bits 4-7 ) */
+                        /* bit 8 indicates that custom data is present */
+                        /* Invokation kind (bits 9-12 ) */
+                        /* function kind (eg virtual), bits 13-15  */
+#ifdef WORDS_BIGENDIAN
+    INT16 nroargs;      /* nr of optional arguments */
+    INT16 nrargs;       /* number of arguments (including optional ????) */
+#else
+    INT16 nrargs;       /* number of arguments (including optional ????) */
+    INT16 nroargs;      /* nr of optional arguments */
+#endif
+    /* optional attribute fields, the number of them is variable */
+    INT   OptAttr[1];
+/*
+0*  INT   helpcontext;
+1*  INT   oHelpString;
+2*  INT   oEntry;       // either offset in string table or numeric as it is //
+3*  INT   res9;         // unknown (-1) //
+4*  INT   resA;         // unknown (-1) //
+5*  INT   HelpStringContext;
+    // these are controlled by a bit set in the FKCCIC field  //
+6*  INT   oCustData;        // custom data for function //
+7*  INT   oArgCustData[1];  // custom data per argument //
+*/
+} MSFT_FuncRecord;
+
+/* after this may follow an array with default value pointers if the
+ * appropriate bit in the FKCCIC field has been set:
+ * INT   oDefautlValue[nrargs];
+ */
+
+    /* Parameter info one per argument*/
+typedef struct {
+        INT   DataType;
+        INT   oName;
+        INT   Flags;
+    } MSFT_ParameterInfo;
+
+/* Variable description data */
+typedef struct {
+/*  INT   recsize;      // record size including some xtra stuff */
+    INT   DataType;     /* data type of the variable */
+    INT   Flags;        /* VarFlags (LOWORD) */
+#ifdef WORDS_BIGENDIAN
+    INT16 vardescsize;  /* size of reconstituted VARDESC and related structs */
+    INT16 VarKind;      /* VarKind */
+#else
+    INT16 VarKind;      /* VarKind */
+    INT16 vardescsize;  /* size of reconstituted VARDESC and related structs */
+#endif
+    INT   OffsValue;    /* value of the variable or the offset  */
+                        /* in the data structure */
+    /* optional attribute fields, the number of them is variable */
+    /* controlled by record length */
+    INT   HelpContext;
+    INT   oHelpString;
+    INT   res9;         /* unknown (-1) */
+    INT   oCustData;        /* custom data for variable */
+    INT   HelpStringContext;
+
+} MSFT_VarRecord;
+
+/* Structure of the reference data  */
+typedef struct {
+    INT   reftype;  /* either offset in type info table, then it's */
+                    /* a multiple of 64 */
+                    /* or offset in the external reference table */
+                    /* with an offset of 1 */
+    INT   flags;
+    INT   oCustData;    /* custom data */
+    INT   onext;    /* next offset, -1 if last */
+} MSFT_RefRecord;
+
+/* this is how a guid is stored */
+typedef struct {
+    GUID guid;
+    INT   hreftype;     /* -2 for the typelib guid, typeinfo offset
+			   for typeinfo guid, low two bits are 01 if
+			   this is an imported typeinfo, low two bits
+			   are 10 if this is an imported typelib (used
+			   by imported typeinfos) */
+    INT   next_hash;    /* offset to next guid in the hash bucket */
+} MSFT_GuidEntry;
+/* some data preceding entries in the name table */
+typedef struct {
+    INT   hreftype;     /* is -1 if name is for neither a typeinfo,
+			   a variable, or a function (that is, name
+			   is for a typelib or a function parameter).
+			   otherwise is the offset of the first
+			   typeinfo that this name refers to (either
+			   to the typeinfo itself or to a member of
+			   the typeinfo */
+    INT   next_hash;    /* offset to next name in the hash bucket */
+    INT   namelen;      /* only lower 8 bits are valid,
+			   lower-middle 8 bits are unknown (flags?),
+			   upper 16 bits are hash code */
+} MSFT_NameIntro;
+/* the custom data table directory has enties like this */
+typedef struct {
+    INT   GuidOffset;
+    INT   DataOffset;
+    INT   next;     /* next offset in the table, -1 if it's the last */
+} MSFT_CDGuid;
+
+
+/***********************************************************
+ *
+ *                SLTG typelibs.
+ *
+ * These are created with ICreateTypeLib
+ *
+ */
+
+#include "pshpack1.h"
+
+typedef struct {
+/*00*/	DWORD SLTG_magic;	/* 0x47544c53  == "SLTG" */
+/*04*/	WORD nrOfFileBlks;	/* no of SLTG_BlkEntry's + 1 */
+/*06*/  WORD res06;		/* ?? always 9 */
+/*08*/  WORD res08;             /* some kind of len/offset ?? */
+/*0a*/	WORD first_blk;		/* 1 based index into blk entries that
+				   corresponds to first block in file */
+/*0c*/	DWORD res0c;		/* always 0x000204ff */
+/*10*/  DWORD res10;		/* always 0x00000000 */
+/*14*/	DWORD res14;		/* always 0x000000c0 */
+/*18*/	DWORD res18;		/* always 0x46000000 */
+/*1c*/	DWORD res1c;		/* always 0x00000044 */
+/*20*/	DWORD res20;		/* always 0xffff0000 */
+} SLTG_Header;
+
+/* This gets followed by a list of block entries */
+typedef struct {
+/*00*/  DWORD len;
+/*04*/	WORD index_string; /* offs from start of SLTG_Magic to index string */
+/*06*/  WORD next;
+} SLTG_BlkEntry;
+
+/* The order of the blocks in the file is given by starting at Block
+   entry firt_blk and stepping through using the next pointer */
+
+/* These then get followed by this magic */
+typedef struct {
+/*00*/ BYTE res00;		/* always 0x01 */
+/*01*/ CHAR CompObj_magic[8];	/* always "CompObj" */
+/*09*/ CHAR dir_magic[4];	/* always "dir" */
+} SLTG_Magic;
+
+#define SLTG_COMPOBJ_MAGIC "CompObj"
+#define SLTG_DIR_MAGIC "dir"
+
+/* Next we have SLTG_Header.nrOfFileBlks - 2 of Index strings.  These
+are presumably unique to within the file and look something like
+"AAAAAAAAAA" with the first character incremented from 'A' to ensure
+uniqueness.  I guess successive chars increment when we need to wrap
+the first one. */
+
+typedef struct {
+/*00*/ CHAR string[11];
+} SLTG_Index;
+
+
+/* This is followed by SLTG_pad9 */
+typedef struct {
+/*00*/ CHAR pad[9];	/* 9 '\0's */
+} SLTG_Pad9;
+
+
+/* Now we have the noOfFileBlks - 1 worth of blocks. The length of
+each block is given by its entry in SLTG_BlkEntry. */
+
+/* type SLTG_NAME in rather like a BSTR except that the length in
+bytes is given by the first WORD and the string contains 8bit chars */
+
+typedef WORD SLTG_Name;
+
+/* The main library block looks like this.  This one seems to come last */
+
+typedef struct {
+/*00*/	WORD magic;		/* 0x51cc */
+/*02*/  WORD res02;		/* 0x0003, 0x0004 */
+/*04*/  WORD name;              /* offset to name in name table */
+/*06*/  SLTG_Name res06;	/* maybe this is just WORD == 0xffff */
+	SLTG_Name helpstring;
+	SLTG_Name helpfile;
+	DWORD helpcontext;
+	WORD syskind;		/* == 1 for win32, 0 for win16 */
+	WORD lcid;		/* == 0x409, 0x809 etc */
+	DWORD res12;		/* == 0 */
+ 	WORD libflags;		/* LIBFLAG_* */
+	WORD maj_vers;
+	WORD min_vers;
+	GUID uuid;
+} SLTG_LibBlk;
+
+#define SLTG_LIBBLK_MAGIC 0x51cc
+
+/* we then get 0x40 bytes worth of 0xffff or small numbers followed by
+   nrOfFileBlks - 2 of these */
+typedef struct {
+	WORD small_no;
+	SLTG_Name index_name; /* This refers to a name in the directory */
+	SLTG_Name other_name; /* Another one of these weird names */
+	WORD res1a;	      /* 0xffff */
+	WORD name_offs;	      /* offset to name in name table */
+	WORD more_bytes;      /* if this is non-zero we get this many
+				 bytes before the next element, which seem
+				 to reference the docstring of the type ? */
+	WORD res20;	      /* 0xffff */
+	DWORD helpcontext;
+	WORD res26;	      /* 0xffff */
+        GUID uuid;
+} SLTG_OtherTypeInfo;
+
+/* Next we get WORD 0x0003 followed by a DWORD which if we add to
+0x216 gives the offset to the name table from the start of the LibBlk
+struct */
+
+typedef struct {
+/*00*/	WORD magic;		/* 0x0501 */
+/*02*/	DWORD href_table;	/* if not 0xffffffff, then byte offset from
+				   beginning of struct to href table */
+/*06*/	DWORD res06;		/* 0xffffffff */
+/*0a*/	DWORD elem_table;	/* offset to members */
+/*0e*/	DWORD res0e;		/* 0xffffffff */
+/*12*/	WORD major_version;	/* major version number */
+/*14*/  WORD minor_version;	/* minor version number */
+/*16*/	DWORD res16;	/* 0xfffe0000 */
+/*1a*/	BYTE typeflags1;/* 0x02 | top 5 bits hold l5sbs of TYPEFLAGS */
+/*1b*/	BYTE typeflags2;/* TYPEFLAGS >> 5 */
+/*1c*/	BYTE typeflags3;/* 0x02*/
+/*1d*/	BYTE typekind;	/* 0x03 == TKIND_INTERFACE etc. */
+/*1e*/  DWORD res1e;	/* 0x00000000 or 0xffffffff */
+} SLTG_TypeInfoHeader;
+
+#define SLTG_TIHEADER_MAGIC 0x0501
+
+typedef struct {
+/*00*/  WORD cFuncs;
+/*02*/  WORD cVars;
+/*04*/  WORD cImplTypes;
+/*06*/  WORD res06;
+/*08*/  WORD res08;
+/*0a*/  WORD res0a;
+/*0c*/  WORD res0c;
+/*0e*/  WORD res0e;
+/*10*/  WORD res10;
+/*12*/  WORD res12;
+/*14*/  WORD tdescalias_vt; /* for TKIND_ALIAS */
+/*16*/  WORD res16;
+/*18*/  WORD res18;
+/*1a*/  WORD res1a;
+/*1c*/  WORD res1c;
+/*1e*/  WORD res1e;
+/*20*/  WORD cbSizeInstance;
+/*22*/  WORD cbAlignment;
+/*24*/  WORD res24;
+/*26*/  WORD res26;
+/*28*/  WORD cbSizeVft;
+/*2a*/  WORD res2a;
+/*2c*/  WORD res2c;
+/*2e*/  WORD res2e;
+/*30*/  WORD res30;
+/*32*/  WORD res32;
+/*34*/  WORD res34;
+} SLTG_TypeInfoTail;
+
+typedef struct {
+/*00*/ WORD res00; /* 0x0001 sometimes 0x0003 ?? */
+/*02*/ WORD res02; /* 0xffff */
+/*04*/ BYTE res04; /* 0x01 */
+/*05*/ DWORD cbExtra; /* No of bytes that follow */
+} SLTG_MemberHeader;
+
+typedef struct {
+/*00*/	WORD magic;	/* 0x120a */
+/*02*/	WORD next;	/* offset in bytes to next block from start of block
+                           group, 0xffff if last item */
+/*04*/	WORD name;	/* offset to name within name table */
+/*06*/	WORD value;	/* offset to value from start of block group */
+/*08*/	WORD res08;	/* 0x56 */
+/*0a*/	DWORD memid;	/* memid */
+/*0e*/  WORD helpcontext;/* 0xfffe == no context, 0x0001 == stored in EnumInfo struct, else offset
+			    to value from start of block group */
+/*10*/	WORD helpstring;/* offset from start of block group to string offset */
+} SLTG_EnumItem;
+
+#define SLTG_ENUMITEM_MAGIC 0x120a
+
+typedef struct {
+/*00*/	WORD vt;	/* vartype, 0xffff marks end. */
+/*02*/	WORD res02;	/* ?, 0xffff marks end */
+} SLTG_AliasItem;
+
+#define SLTG_ALIASITEM_MAGIC 0x001d
+
+
+typedef struct {
+	BYTE magic;	/* 0x4c or 0x6c */
+	BYTE inv;	/* high nibble is INVOKE_KIND, low nibble = 2 */
+	WORD next;	/* byte offset from beginning of group to next fn */
+	WORD name;	/* Offset within name table to name */
+	DWORD dispid;	/* dispid */
+	WORD helpcontext; /* helpcontext (again 1 is special) */
+	WORD helpstring;/* helpstring offset to offset */
+	WORD arg_off;	/* offset to args from start of block */
+	BYTE nacc;	/* lowest 3bits are CALLCONV, rest are no of args */
+        BYTE retnextopt;/* if 0x80 bit set ret type follows else next WORD
+			   is offset to ret type. No of optional args is
+			   middle 6 bits */
+	WORD rettype;	/* return type VT_?? or offset to ret type */
+	WORD vtblpos;	/* position in vtbl? */
+	WORD funcflags; /* present if magic == 0x6c */
+/* Param list starts, repeat next two as required */
+#if 0
+	WORD  name;	/* offset to 2nd letter of name */
+	WORD+ type;	/* VT_ of param */
+#endif
+} SLTG_Function;
+
+#define SLTG_FUNCTION_MAGIC 0x4c
+#define SLTG_FUNCTION_WITH_FLAGS_MAGIC 0x6c
+
+typedef struct {
+/*00*/	BYTE magic;		/* 0xdf */
+/*01*/  BYTE res01;		/* 0x00 */
+/*02*/	DWORD res02;		/* 0xffffffff */
+/*06*/	DWORD res06;		/* 0xffffffff */
+/*0a*/	DWORD res0a;		/* 0xffffffff */
+/*0e*/	DWORD res0e;		/* 0xffffffff */
+/*12*/	DWORD res12;		/* 0xffffffff */
+/*16*/	DWORD res16;		/* 0xffffffff */
+/*1a*/	DWORD res1a;		/* 0xffffffff */
+/*1e*/	DWORD res1e;		/* 0xffffffff */
+/*22*/	DWORD res22;		/* 0xffffffff */
+/*26*/	DWORD res26;		/* 0xffffffff */
+/*2a*/	DWORD res2a;		/* 0xffffffff */
+/*2e*/	DWORD res2e;		/* 0xffffffff */
+/*32*/	DWORD res32;		/* 0xffffffff */
+/*36*/	DWORD res36;		/* 0xffffffff */
+/*3a*/	DWORD res3a;		/* 0xffffffff */
+/*3e*/	DWORD res3e;		/* 0xffffffff */
+/*42*/	WORD  res42;		/* 0xffff */
+/*44*/	DWORD number;		/* this is 8 times the number of refs */
+/*48*/	/* Now we have number bytes (8 for each ref) of SLTG_UnknownRefInfo */
+
+/*50*/	WORD res50;		/* 0xffff */
+/*52*/	BYTE res52;		/* 0x01 */
+/*53*/	DWORD res53;		/* 0x00000000 */
+/*57*/  SLTG_Name names[1];
+  /*    Now we have number/8 SLTG_Names (first WORD is no of bytes in the ascii
+   *    string).  Strings look like "*\Rxxxx*#n".  If xxxx == ffff then the
+   *    ref refers to the nth type listed in this library (0 based).  Else
+   *    the xxxx (which maybe fewer than 4 digits) is the offset into the name
+   *    table to a string "*\G{<guid>}#1.0#0#C:\WINNT\System32\stdole32.tlb#"
+   *    The guid is the typelib guid; the ref again refers to the nth type of
+   *    the imported typelib.
+   */
+
+/*xx*/ BYTE resxx;		/* 0xdf */
+
+} SLTG_RefInfo;
+
+#define SLTG_REF_MAGIC 0xdf
+
+typedef struct {
+	WORD res00;	/* 0x0001 */
+	BYTE res02;	/* 0x02 */
+	BYTE res03;	/* 0x40 if internal ref, 0x00 if external ? */
+	WORD res04;	/* 0xffff */
+	WORD res06;	/* 0x0000, 0x0013 or 0xffff ?? */
+} SLTG_UnknownRefInfo;
+
+typedef struct {
+  WORD res00; /* 0x004a */
+  WORD next;  /* byte offs to next interface */
+  WORD res04; /* 0xffff */
+  BYTE impltypeflags; /* IMPLTYPEFLAG_* */
+  BYTE res07; /* 0x80 */
+  WORD res08; /* 0x0012, 0x0028 ?? */
+  WORD ref;   /* number in ref table ? */
+  WORD res0c; /* 0x4000 */
+  WORD res0e; /* 0xfffe */
+  WORD res10; /* 0xffff */
+  WORD res12; /* 0x001d */
+  WORD pos_in_table; /* 0x0, 0x4, ? */
+} SLTG_ImplInfo;
+
+#define SLTG_IMPL_MAGIC 0x004a
+
+typedef struct {
+  BYTE magic; /* 0x0a */
+  BYTE typepos;
+  WORD next;
+  WORD name;
+  WORD byte_offs; /* pos in struct */
+  WORD type; /* if typepos == 0x02 this is the type, else offset to type */
+  DWORD memid;
+  WORD helpcontext; /* ?? */
+  WORD helpstring; /* ?? */
+} SLTG_RecordItem;
+
+#define SLTG_RECORD_MAGIC 0x0a
+
+
+/* CARRAYs look like this
+WORD type == VT_CARRAY
+WORD offset from start of block to SAFEARRAY
+WORD typeofarray
+*/
+
+#include "poppack.h"
+
+/*---------------------------END--------------------------------------------*/
+#endif
--- /dev/null	2004-02-23 21:02:56.000000000 +0000
+++ tools/widl/hash.c	2005-01-06 14:37:20.156031923 +0000
@@ -0,0 +1,621 @@
+/*
+ * Oleaut32 hash functions
+ *
+ * Copyright 1999 Corel Corporation
+ * Copyright 2001-2003 Jon Griffiths
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winnls.h"
+
+#include "hash.h"
+
+static const unsigned char Lookup_16[128 * 3] = {
+ /* Common */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x00, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+
+ /* Windows */
+ 0x7F, 0x7F, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x7F, 0x89, 0x53, 0x8B, 0x8C,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x96, 0x98, 0x99,
+ 0x53, 0x9B, 0x8C, 0x7F, 0x7F, 0x55, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x96, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41,
+ 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49,
+ 0x49, 0x49, 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0xD7, 0x4F, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0xDE, 0xDF, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x43,
+ 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x44, 0x4E, 0x4F, 0x4F, 0x4F,
+ 0x4F, 0x4F, 0xF7, 0x4F, 0x55, 0x55, 0x55, 0x55, 0x55, 0xDE, 0x55,
+
+ /* Mac */
+ 0x41, 0x41, 0x43, 0x45, 0x4E, 0x4F, 0x55, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
+ 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x4E, 0x4F, 0x4F, 0x4F,
+ 0x4F, 0x4F, 0x55, 0x55, 0x55, 0x55, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0x41, 0x4F, 0xB0, 0xB1, 0xB2, 0xB3,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0x41, 0x4F, 0xBD, 0x41, 0x4F, 0xC0,
+ 0xC1, 0xC2, 0xC3, 0x46, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0x41, 0x41, 0x4F,
+ 0xCE, 0xCE, 0xD0, 0xD0, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0x55, 0x55, 0xDA,
+ 0xDB, 0xDC, 0xDD, 0x3F, 0x3F, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0x41, 0x45, 0x41,
+ 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x4F, 0x4F, 0x3F, 0x4F, 0x55, 0x55, 0x55,
+ 0x49, 0x7F, 0xF7, 0x7F, 0xF9, 0xFA, 0xFB, 0x3F, 0xFD, 0xFE, 0x7F
+};
+
+static const unsigned char Lookup_32[128 * 3] = {
+ /* Common */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x00, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+
+ /* Windows */
+ 0x7F, 0x7F, 0x82, 0x7F, 0x84, 0x85, 0x86, 0x87, 0x7F, 0x89, 0x53, 0x8B, 0x53,
+ 0x54, 0x5A, 0x5A, 0x7F, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x96, 0x7F, 0x99,
+ 0x53, 0x9B, 0x53, 0x54, 0x5A, 0x5A, 0xA0, 0x7F, 0xA2, 0x4C, 0xA4, 0x41, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0x53, 0xAB, 0xAC, 0x96, 0xAE, 0x5A, 0xB0, 0xB1, 0xB2, 0x4C,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x41, 0x53, 0xBB, 0x4C, 0xBD, 0x4C, 0x5A, 0x52,
+ 0x41, 0x41, 0x41, 0x41, 0x4C, 0x43, 0x43, 0x43, 0x45, 0x45, 0x45, 0x45, 0x49,
+ 0x49, 0x44, 0xD0, 0x4E, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0xD7, 0x52, 0x55, 0x55,
+ 0x55, 0x55, 0x59, 0x54, 0xDF, 0x52, 0x41, 0x41, 0x41, 0x41, 0x4C, 0x43, 0x43,
+ 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x44, 0xD0, 0x4E, 0x4E, 0x4F, 0x4F,
+ 0x4F, 0x4F, 0xF7, 0x52, 0x55, 0x55, 0x55, 0x55, 0x59, 0x54, 0xFF,
+
+ /* Mac */
+ 0x41, 0x41, 0x41, 0x45, 0x41, 0x4F, 0x55, 0x41, 0x41, 0x43, 0x41, 0x43, 0x43,
+ 0x43, 0x45, 0x5A, 0x5A, 0x44, 0x49, 0x44, 0x45, 0x45, 0x45, 0x4F, 0x45, 0x4F,
+ 0x4F, 0x4F, 0x55, 0x45, 0x45, 0x55, 0xA0, 0xA1, 0x45, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0xAA, 0x45, 0xAC, 0xAD, 0x47, 0x49, 0x49, 0x49, 0xB2, 0xB3,
+ 0x49, 0x4B, 0xB6, 0xB7, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4E, 0x4E,
+ 0x4E, 0xC2, 0xC3, 0x4E, 0x4E, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0x4E, 0x4F, 0x4F,
+ 0x4F, 0x4F, 0xD0, 0xD0, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0x4F, 0x52, 0x52,
+ 0x52, 0xDC, 0xDD, 0x52, 0x52, 0x52, 0x53, 0xE2, 0xE3, 0x53, 0x53, 0x53, 0x41,
+ 0x54, 0x54, 0x49, 0x5A, 0x5A, 0x55, 0x4F, 0x4F, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x59, 0x59, 0x4B, 0x5A, 0x4C, 0x4C, 0x47, 0xFF
+};
+
+static const unsigned char Lookup_48[128 * 3] = {
+ /* Common */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x00, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+
+ /* Windows */
+ 0x7F, 0x7F, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x7F, 0x89, 0x53, 0x8B, 0x8C,
+ 0x7F, 0x7F, 0x7F, 0x7F, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x96, 0x98, 0x99,
+ 0x53, 0x9B, 0x8C, 0x7F, 0x7F, 0x59, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x96, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41,
+ 0x41, 0x41, 0x41, 0x41, 0x41, 0xC6, 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49,
+ 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0xD7, 0x4F, 0x55, 0x55,
+ 0x55, 0x55, 0x59, 0xDE, 0xDF, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0xC6, 0x43,
+ 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0x4F, 0x4F,
+ 0x4F, 0x4F, 0xF7, 0x4F, 0x55, 0x55, 0x55, 0x55, 0x59, 0xDE, 0x59,
+
+ /* Mac */
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C,
+ 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+ 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAB, 0xAD, 0xAE, 0xAE, 0xB0, 0xB1, 0xB2, 0xB3,
+ 0xA7, 0xB5, 0xB6, 0xB7, 0xB8, 0xB8, 0xBA, 0xBA, 0xBC, 0xBC, 0xBE, 0xBE, 0xB7,
+ 0xC1, 0xC2, 0xC3, 0x46, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCB, 0xCD,
+ 0xCD, 0xC1, 0xD0, 0xD0, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD8, 0xDA,
+ 0xDA, 0xDC, 0xDD, 0xDD, 0x9F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94,
+ 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F
+};
+
+static const unsigned char Lookup_64[128 * 3] = {
+ /* Common */
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x00, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+
+/* Windows */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x96, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41,
+ 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49,
+ 0x49, 0x49, 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0xD7, 0x4F, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0xDE, 0xDF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ /* Mac */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x96, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41,
+ 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49,
+ 0x49, 0x49, 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0xD7, 0x4F, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0xDE, 0xDF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const unsigned char Lookup_80[128 * 3] = {
+ /* Common */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x00, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+
+/* Windows */
+ 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
+
+ /* Mac */
+ 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
+};
+
+static const unsigned char Lookup_112[128 * 3] = {
+ /* Common */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x00, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+
+/* Windows */
+ 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
+
+ /* Mac */
+ 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
+};
+
+static const unsigned char Lookup_128[128 * 3] = {
+ /* Common */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x00,
+
+/* Windows */
+ 0x00, 0x00, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x00, 0x89, 0x00, 0x8B, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x2D, 0x2D, 0x00, 0x99,
+ 0x00, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x09, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0x00, 0xAB, 0xAC, 0x2D, 0xAE, 0x2D, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xBA,
+ 0xA2, 0xC2, 0xC3, 0xC4, 0xB8, 0xC6, 0xB9, 0xC8, 0xBA, 0xCA, 0xCB, 0xCC, 0xCD,
+ 0xCE, 0xBC, 0xD0, 0xD1, 0x00, 0xD3, 0xD4, 0xBE, 0xD6, 0xD7, 0xD8, 0xBF, 0xBA,
+ 0xBE, 0xA2, 0xB8, 0xB9, 0xBA, 0xBE, 0xA2, 0xC2, 0xC3, 0xC4, 0xB8, 0xC6, 0xB9,
+ 0xC8, 0xBA, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xBC, 0xD0, 0xD1, 0xD3, 0xD3, 0xD4,
+ 0xBE, 0xD6, 0xD7, 0xD8, 0xBF, 0xBA, 0xBE, 0xBC, 0xBE, 0xBF, 0x00,
+
+ /* Mac */
+ 0x41, 0x31, 0x32, 0x45, 0x33, 0x4F, 0x55, 0x87, 0x41, 0x41, 0x41, 0x00, 0x8C,
+ 0x43, 0x45, 0x45, 0x45, 0x45, 0x92, 0x93, 0x49, 0x49, 0x96, 0x97, 0x98, 0x4F,
+ 0x4F, 0x9B, 0x3F, 0x55, 0x55, 0x55, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xAB, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xB0,
+ 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0x09, 0xBD, 0xCC, 0xB0,
+ 0xB6, 0xCF, 0x2D, 0x2D, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xB8, 0xAB, 0xC3, 0xBD,
+ 0xB6, 0xB8, 0xAB, 0xC3, 0xBF, 0xBD, 0xB0, 0xB5, 0xBE, 0xA2, 0xB6, 0xBC, 0xA1,
+ 0xB8, 0xAB, 0xA5, 0xBA, 0xA4, 0xBB, 0xC1, 0xC3, 0xA6, 0xBF, 0xC4, 0xAA, 0xC6,
+ 0xA3, 0xBF, 0xAA, 0xCC, 0xBD, 0xB7, 0xAB, 0xBD, 0xAB, 0xBD, 0x3F,
+};
+
+static const unsigned char Lookup_144[128 * 3] = {
+ /* Common */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x00,
+
+/* Windows */
+ 0x00, 0x00, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x00, 0x89, 0x53, 0x8B, 0x8C,
+ 0x00, 0x00, 0x00, 0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x2D, 0x2D, 0x98, 0x99,
+ 0x53, 0x9B, 0x8C, 0x00, 0x00, 0x59, 0x09, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x2D, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41,
+ 0xC1, 0x41, 0x41, 0x41, 0x41, 0xC6, 0x43, 0x45, 0xC9, 0x45, 0x45, 0x49, 0xCD,
+ 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0xD3, 0x4F, 0x4F, 0xD6, 0xD7, 0xD6, 0x55, 0xDA,
+ 0x55, 0x55, 0xDD, 0xDE, 0xDF, 0x41, 0xC1, 0x41, 0x41, 0x41, 0x41, 0xC6, 0x43,
+ 0x45, 0xC9, 0x45, 0x45, 0x49, 0xCD, 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0xD3, 0x4F,
+ 0x4F, 0xD6, 0xF7, 0xD6, 0x55, 0xDA, 0x55, 0x55, 0xDD, 0xDE, 0x59,
+
+ /* Mac */
+ 0x00, 0x00, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x00, 0x89, 0x53, 0x8B, 0x8C,
+ 0x00, 0x00, 0x00, 0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x2D, 0x2D, 0x98, 0x99,
+ 0x53, 0x9B, 0x8C, 0x00, 0x00, 0x59, 0x09, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x2D, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41,
+ 0xC1, 0x41, 0x41, 0x41, 0x41, 0xC6, 0x43, 0x45, 0xC9, 0x45, 0x45, 0x49, 0xCD,
+ 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0xD3, 0x4F, 0x4F, 0xD6, 0xD7, 0xD6, 0x55, 0xDA,
+ 0x55, 0x55, 0xDD, 0xDE, 0xDF, 0x41, 0xC1, 0x41, 0x41, 0x41, 0x41, 0xC6, 0x43,
+ 0x45, 0xC9, 0x45, 0x45, 0x49, 0xCD, 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0xD3, 0x4F,
+ 0x4F, 0xD6, 0xF7, 0xD6, 0x55, 0xDA, 0x55, 0x55, 0xDD, 0xDE, 0x59,
+};
+
+static const unsigned char Lookup_160[128 * 3] = {
+ /* Common */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x00,
+
+/* Windows */
+ 0x00, 0x00, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x00, 0x89, 0x53, 0x8B, 0x8C,
+ 0x00, 0x00, 0x00, 0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x2D, 0x2D, 0x98, 0x99,
+ 0x53, 0x9B, 0x8C, 0x00, 0x00, 0x59, 0x09, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x2D, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41,
+ 0x41, 0x41, 0x41, 0x41, 0x41, 0xC6, 0xC7, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49,
+ 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0xD6, 0xD7, 0x4F, 0x55, 0x55,
+ 0x55, 0xDC, 0xDD, 0xDE, 0xDF, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0xC6, 0xC7,
+ 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0x4F, 0x4F,
+ 0x4F, 0xD6, 0xF7, 0x4F, 0x55, 0x55, 0x55, 0xDC, 0xDD, 0xDE, 0x59,
+
+ /* Mac */
+ 0x00, 0x00, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x00, 0x89, 0x53, 0x8B, 0x8C,
+ 0x00, 0x00, 0x00, 0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x2D, 0x2D, 0x98, 0x99,
+ 0x53, 0x9B, 0x8C, 0x00, 0x00, 0x59, 0x09, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x2D, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41,
+ 0x41, 0x41, 0x41, 0x41, 0x41, 0xC6, 0xC7, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49,
+ 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0xD6, 0xD7, 0x4F, 0x55, 0x55,
+ 0x55, 0xDC, 0xDD, 0xDE, 0xDF, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0xC6, 0xC7,
+ 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0x4F, 0x4F,
+ 0x4F, 0xD6, 0xF7, 0x4F, 0x55, 0x55, 0x55, 0xDC, 0xDD, 0xDE, 0x59,
+};
+
+static const unsigned char Lookup_176[128 * 3] = {
+ /* Common */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x00,
+
+ /* Windows */
+ 0x00, 0x00, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x00, 0x89, 0x53, 0x8B, 0x8C,
+ 0x00, 0x00, 0x00, 0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x2D, 0x2D, 0x98, 0x99,
+ 0x53, 0x9B, 0x8C, 0x00, 0x00, 0x59, 0x09, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x2D, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41,
+ 0x41, 0x41, 0x41, 0xC4, 0xC5, 0xC4, 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49,
+ 0x49, 0x49, 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0xD6, 0xD7, 0xD6, 0x55, 0x55,
+ 0x55, 0x59, 0x59, 0xDE, 0xDF, 0x41, 0x41, 0x41, 0x41, 0xC4, 0xC5, 0xC4, 0x43,
+ 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x44, 0x4E, 0x4F, 0x4F, 0x4F,
+ 0x4F, 0xD6, 0xF7, 0xD6, 0x55, 0x55, 0x55, 0x59, 0x59, 0xDE, 0x59,
+
+ /* Mac */
+ 0x80, 0x81, 0x43, 0x45, 0x4E, 0x85, 0x59, 0x41, 0x41, 0x41, 0x80, 0x41, 0x81,
+ 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x4E, 0x4F, 0x4F, 0x4F,
+ 0x85, 0x4F, 0x55, 0x55, 0x55, 0x59, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0x80, 0x85, 0xB0, 0xB1, 0xB2, 0xB3,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0x41, 0x4F, 0xBD, 0x80, 0x85, 0xC0,
+ 0xC1, 0xC2, 0xC3, 0x46, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0x09, 0x41, 0x41, 0x4F,
+ 0xCE, 0xCE, 0x2D, 0x2D, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0x59, 0x59, 0xDA,
+ 0xDB, 0xDC, 0xDD, 0x3F, 0x3F, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0x41, 0x45, 0x41,
+ 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x4F, 0x4F, 0x3F, 0x4F, 0x55, 0x55, 0x55,
+ 0x49, 0x00, 0xF7, 0x00, 0xF9, 0xFA, 0xFB, 0x3F, 0xFD, 0xFE, 0x00
+};
+
+static const unsigned char Lookup_208[128 * 3] = {
+ /* Common */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+
+/* Windows */
+ 0x80, 0x81, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x5E, 0x89, 0x8A, 0x8B, 0x8C,
+ 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+ 0x9A, 0x9B, 0x8C, 0x9D, 0x00, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0,
+ 0xC1, 0xC2, 0xC1, 0xC1, 0xC1, 0xC1, 0xC7, 0xC8, 0xC9, 0xC9, 0xCB, 0xCC, 0xCD,
+ 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA,
+ 0xDB, 0x00, 0xDD, 0xDE, 0xDF, 0x41, 0xE1, 0x41, 0xE3, 0xE4, 0xE5, 0xE6, 0x43,
+ 0x45, 0x45, 0x45, 0x45, 0xEC, 0xEC, 0x49, 0x49, 0xF0, 0xF1, 0xF2, 0xF3, 0x4F,
+ 0xF5, 0xF6, 0xF7, 0xF8, 0x55, 0xFA, 0x55, 0x55, 0x00, 0x00, 0xFF,
+
+ /* Mac */
+ 0x41, 0x81, 0x43, 0x45, 0x4E, 0x4F, 0x55, 0x41, 0x41, 0x41, 0x41, 0x8B, 0x8C,
+ 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x93, 0x49, 0x49, 0x4E, 0x4F, 0x98, 0x4F,
+ 0x4F, 0x9B, 0x55, 0x55, 0x55, 0x55, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0,
+ 0xC1, 0xC2, 0xC1, 0xC1, 0xC1, 0xC1, 0xC7, 0xC8, 0xC9, 0xC9, 0xCB, 0xCC, 0xCD,
+ 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA,
+ 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0x00, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+ 0xE8, 0xE9, 0xE9, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4,
+ 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
+};
+
+static const unsigned char Lookup_224[128 * 3] = {
+ /* Common */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
+ 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
+ 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+
+/* Windows */
+ 0x80, 0x81, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x5E, 0x89, 0x8A, 0x8B, 0x8C,
+ 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+ 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0,
+ 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD,
+ 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA,
+ 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+ 0xE8, 0xE9, 0xEA, 0xEA, 0xEC, 0xED, 0xED, 0xEF, 0xEF, 0xF1, 0xF2, 0xF3, 0xF3,
+ 0xF5, 0xF5, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0x00, 0x00, 0xFF,
+
+ /* Mac */
+ 0x41, 0x41, 0x43, 0x45, 0x4E, 0x4F, 0x55, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
+ 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x4E, 0x4F, 0x4F, 0x4F,
+ 0x4F, 0x4F, 0x55, 0x55, 0x55, 0x55, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
+ 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0,
+ 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD,
+ 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA,
+ 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+ 0xE8, 0xE9, 0xEA, 0xEA, 0xEC, 0xED, 0xED, 0xEF, 0xEF, 0xF1, 0xF2, 0xF3, 0xF3,
+ 0xF5, 0xF5, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
+};
+
+/***********************************************************************
+ *		lhash_val_of_name_sys
+ *
+ * Copy of oleaut32.LHashValOfNameSysA
+ * Produce a string hash value.
+ *
+ * PARAMS
+ *  skind [I] Type of the system.
+ *  lcid  [I] Locale id for the hash.
+ *  lpStr [I] String to hash.
+ *
+ * RETURNS
+ *  Success: The hash value of the string.
+ *  Failure: 0, if lpStr is NULL.
+ *
+ * NOTES
+ *  This function produces a two part hash: The high word is based on
+ *  skind and lcid, while the low word is based on a repeated string
+ *  hash of skind/str.
+ */
+unsigned long lhash_val_of_name_sys( syskind_t skind, LCID lcid, LPCSTR lpStr)
+{
+  ULONG nOffset, nMask = skind == SYS_MAC ? 1 : 0;
+  ULONG nHiWord, nLoWord = 0x0deadbee;
+  const unsigned char *str = (const unsigned char *)lpStr, *pnLookup = NULL;
+
+  if (!str)
+    return 0;
+
+  switch (PRIMARYLANGID(LANGIDFROMLCID(lcid)))
+  {
+  default:
+    fprintf(stderr, "Unknown lcid %lx, treating as latin-based, please report\n", lcid);
+    /* .. Fall Through .. */
+  case LANG_AFRIKAANS:  case LANG_ALBANIAN:   case LANG_ARMENIAN:
+  case LANG_ASSAMESE:   case LANG_AZERI:      case LANG_BASQUE:
+  case LANG_BELARUSIAN: case LANG_BENGALI:    case LANG_BULGARIAN:
+  case LANG_CATALAN:    case LANG_DANISH:     case LANG_DIVEHI:
+  case LANG_DUTCH:      case LANG_ENGLISH:    case LANG_ESTONIAN:
+  case LANG_FAEROESE:   case LANG_FINNISH:    case LANG_FRENCH:
+  case LANG_GALICIAN:   case LANG_GEORGIAN:   case LANG_GERMAN:
+  case LANG_GUJARATI:   case LANG_HINDI:      case LANG_INDONESIAN:
+  case LANG_ITALIAN:    case LANG_KANNADA:    case LANG_KASHMIRI:
+  case LANG_KAZAK:      case LANG_KONKANI:    case LANG_KYRGYZ:
+  case LANG_LATVIAN:    case LANG_LITHUANIAN: case LANG_MACEDONIAN:
+  case LANG_MALAY:      case LANG_MALAYALAM:  case LANG_MANIPURI:
+  case LANG_MARATHI:    case LANG_MONGOLIAN:  case LANG_NEPALI:
+  case LANG_ORIYA:      case LANG_PORTUGUESE: case LANG_PUNJABI:
+  case LANG_ROMANIAN:   case LANG_SANSKRIT:   case LANG_SERBIAN:
+  case LANG_SINDHI:     case LANG_SLOVENIAN:  case LANG_SWAHILI:
+  case LANG_SWEDISH:    case LANG_SYRIAC:     case LANG_TAMIL:
+  case LANG_TATAR:      case LANG_TELUGU:     case LANG_THAI:
+  case LANG_UKRAINIAN:  case LANG_URDU:       case LANG_UZBEK:
+  case LANG_VIETNAMESE: case LANG_GAELIC:     case LANG_MALTESE:
+  case LANG_MAORI:      case LANG_RHAETO_ROMANCE:
+  case LANG_SAAMI:      case LANG_SORBIAN:    case LANG_SUTU:
+  case LANG_TSONGA:     case LANG_TSWANA:     case LANG_VENDA:
+  case LANG_XHOSA:      case LANG_ZULU:       case LANG_ESPERANTO:
+  case LANG_WALON:      case LANG_CORNISH:    case LANG_WELSH:
+  case LANG_BRETON:
+    nOffset = 16;
+    pnLookup = Lookup_16;
+    break;
+  case LANG_CZECH:  case LANG_HUNGARIAN:  case LANG_POLISH:
+  case LANG_SLOVAK: case LANG_SPANISH:
+    nOffset = 32;
+    pnLookup = Lookup_32;
+    break;
+  case LANG_HEBREW:
+    nOffset = 48;
+    pnLookup = Lookup_48;
+    break;
+  case LANG_JAPANESE:
+    nOffset = 64;
+    pnLookup = Lookup_64;
+    break;
+  case LANG_KOREAN:
+    nOffset = 80;
+    pnLookup = Lookup_80;
+    break;
+  case LANG_CHINESE:
+    nOffset = 112;
+    pnLookup = Lookup_112;
+    break;
+  case LANG_GREEK:
+    nOffset = 128;
+    pnLookup = Lookup_128;
+    break;
+  case LANG_ICELANDIC:
+    nOffset = 144;
+    pnLookup = Lookup_144;
+    break;
+  case LANG_TURKISH:
+    nOffset = 160;
+    pnLookup = Lookup_160;
+    break;
+  case LANG_NORWEGIAN:
+    if (SUBLANGID(LANGIDFROMLCID(lcid)) == SUBLANG_NORWEGIAN_NYNORSK)
+    {
+      nOffset = 176;
+      pnLookup = Lookup_176;
+    }
+    else
+    {
+      nOffset = 16;
+      pnLookup = Lookup_16;
+    }
+    break;
+  case LANG_ARABIC:
+  case LANG_FARSI:
+    nOffset = 208;
+    pnLookup = Lookup_208;
+    break;
+  case LANG_RUSSIAN:
+    nOffset = 224;
+    pnLookup = Lookup_224;
+    break;
+  }
+
+  nHiWord = (nOffset | nMask) << 16;
+
+  while (*str)
+  {
+    ULONG newLoWord = 0, i;
+
+    /* Cumulative prime multiplication (*37) with modulo 2^32 wrap-around */
+    for (i = 0; i < 37; i++)
+      newLoWord += nLoWord;
+
+    nLoWord = newLoWord + pnLookup[*str > 0x7f && nMask ? *str + 0x80 : *str];
+    str++;
+  }
+  /* Constrain to a prime modulo and sizeof(WORD) */
+  nLoWord = (nLoWord % 65599) & 0xffff;
+
+  return nHiWord | nLoWord;
+}
--- /dev/null	2004-02-23 21:02:56.000000000 +0000
+++ tools/widl/hash.h	2005-01-06 14:37:19.239246216 +0000
@@ -0,0 +1,12 @@
+#ifndef __WIDL_HASH_H
+#define __WIDL_HASH_H
+
+typedef enum tag_syskind_t {
+    SYS_WIN16 = 0,
+    SYS_WIN32,
+    SYS_MAC
+} syskind_t;
+
+extern unsigned long lhash_val_of_name_sys( syskind_t skind, LCID lcid, LPCSTR lpStr);
+
+#endif



More information about the wine-patches mailing list