Windows2000/private/oleauto/src/mktyplib/hout.c

1112 lines
28 KiB
C

#include "mktyplib.h"
// .H file output for MKTYPLIB
#include <stdio.h>
#ifndef WIN32
#include <ole2.h> // required for dispatch.h
#include "dispatch.h"
#endif //WIN32
#include "errors.h"
#include "fileinfo.h"
#include "intlstr.h" // for szHead* definitions
// external data
extern TYPLIB typlib;
extern FILE *hHFile;
extern SYSKIND SysKind;
extern int iAlignMax;
extern int iAlignDef;
extern BOOL fSpecifiedInterCC;
// external functions
extern INT FAR FCmpCaseIns(LPSTR str1, LPSTR str2);
// private data
static CHAR *szHeadOlePrefix0 = "#undef INTERFACE\n"
"#define INTERFACE ";
static CHAR *szHeadOlePrefix1 = "DECLARE_INTERFACE";
static CHAR *szHeadOlePrefix2 = ")\n{\n";
static CHAR *szHeadOlePrefix3 = "\n /* ";
static CHAR *szHeadOlePrefix4 = " methods */\n";
static CHAR *szHeadOlePrefix5 = " properties:\n";
static CHAR *szHeadOlePrefix6 = " methods:\n";
static CHAR *szHeadOlePrefix7 = "#ifndef NO_BASEINTERFACE_FUNCS\n";
static CHAR *szHeadOleFuncPrefix1 = " "; // leading spaces
static CHAR *szHeadOleFuncPrefix2 = "STDMETHOD";
static CHAR *szHeadOleFuncPrefix3 = ", "; // after return type
static CHAR *szHeadOleArgPrefix1 = ")(THIS";
static CHAR *szHeadOleArgPrefix2 = "_ "; // only if args
static CHAR *szHeadOleArgSuffix = ") PURE;\n";
static CHAR *szHeadOleSuffix1 = " */\n";
static CHAR *szHeadOleSuffix2 = "};\n";
static CHAR *szHeadOleSuffix3 = " */\n";
static CHAR *szHeadOleSuffix7 = "#endif\n";
//Hack for profiling
//#define PROFILE
#ifdef PROFILE
static unsigned long cFuncsTotal = 0;
static unsigned long cArgsTotal = 0;
static unsigned long cVarsTotal = 0;
#endif //PROFILE
// stuff dealing with non-default interface calling conventions
static CHAR *szUndefCallType = "#undef STDMETHODCALLTYPE\n";
static CHAR *szResetCallType =
"#if defined(WIN32)\n"
"#define STDMETHODCALLTYPE STDMETHODSTDCALL\n"
"#else\n"
"#define STDMETHODCALLTYPE STDMETHODCDECL\n"
"#endif\n";
static CHAR *szDefCallTypePrefix = "#define STDMETHODCALLTYPE STDMETHOD";
static CHAR *rgszCallType[] = {
"CDECL",
"PASCAL",
"STDCALL"
};
typedef enum {
CALL_CDECL,
CALL_PASCAL,
CALL_STDCALL,
CALL_DEFAULT
} CALLINGCONV;
static CALLINGCONV ccInterCurrent = CALL_DEFAULT;
// user-specified calling conventions for all platforms
static CHAR * szCCHeader =
"\n"
"/* Macros for redefining the STDMETHOD calling convention\n"
" * (STDMETHODCALLTYPE).\n"
" */\n"
"\n"
"#if defined(_MAC)\n"
"\n"
"#if !defined(_MSC_VER)\n"
"#define STDMETHODCDECL\n"
"#define STDMETHODPASCAL\n"
"#define STDMETHODSTDCALL\n"
"#else\n"
"#define STDMETHODCDECL FAR CDECL\n"
"#define STDMETHODPASCAL FAR PASCAL\n"
"#define STDMETHODSTDCALL FAR STDCALL\n"
"#endif\n"
"\n"
"#elif defined(WIN32)\n"
"\n"
"#define STDMETHODCDECL EXPORT __cdecl\n"
"#define STDMETHODPASCAL EXPORT __pascal\n"
"#define STDMETHODSTDCALL EXPORT __stdcall\n"
"\n"
"#else /* WIN16 */\n"
"\n"
"#define STDMETHODCDECL __export FAR CDECL\n"
"#define STDMETHODPASCAL __export FAR PASCAL\n"
"#define STDMETHODSTDCALL __export FAR STDCALL\n"
"\n"
"#endif\n"
"\n";
// canned definition of IUnknown
static CHAR * szHeadIUnknown =
"\n"
" /* IUnknown methods */\n"
" STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;\n"
" STDMETHOD_(ULONG, AddRef)(THIS) PURE;\n"
" STDMETHOD_(ULONG, Release)(THIS) PURE;\n";
// canned definition of IDispatch
static CHAR * szHeadIDispatch =
"\n"
" /* IDispatch methods */\n"
" STDMETHOD(GetTypeInfoCount)(THIS_ UINT FAR* pctinfo) PURE;\n"
"\n"
" STDMETHOD(GetTypeInfo)(\n"
" THIS_\n"
" UINT itinfo,\n"
" LCID lcid,\n"
" ITypeInfo FAR* FAR* pptinfo) PURE;\n"
"\n"
" STDMETHOD(GetIDsOfNames)(\n"
" THIS_\n"
" REFIID riid,\n"
" OLECHAR FAR* FAR* rgszNames,\n"
" UINT cNames,\n"
" LCID lcid,\n"
" DISPID FAR* rgdispid) PURE;\n"
"\n"
" STDMETHOD(Invoke)(\n"
" THIS_\n"
" DISPID dispidMember,\n"
" REFIID riid,\n"
" LCID lcid,\n"
" WORD wFlags,\n"
" DISPPARAMS FAR* pdispparams,\n"
" VARIANT FAR* pvarResult,\n"
" EXCEPINFO FAR* pexcepinfo,\n"
" UINT FAR* puArgErr) PURE;\n";
static CHAR *szHeadGuidPrefix = "\nDEFINE_GUID(";
static CHAR *szHeadGuidLIBID = "LIBID_";
static CHAR *szHeadGuidCLSID = "CLSID_";
static CHAR *szHeadGuidIID = "IID_";
static CHAR *szHeadGuidDIID = "DIID_";
// prototypes
VOID FAR OutputHFile (CHAR * szHFile);
VOID NEAR HOutTypedef(LPTYPE pType);
VOID NEAR HOutEnum(LPTYPE pType);
VOID NEAR HOutStructUnion(LPTYPE pType);
VOID NEAR HOutModule(LPENTRY pEntry);
VOID NEAR HOutInterface(LPENTRY pEntry);
VOID NEAR HOutCoclass(LPENTRY pEntry);
VOID NEAR HOutBaseInter(LPENTRY pEntry, BOOL fRecurse);
VOID NEAR HOutFuncs(LPFUNC pFuncList, TENTRYKIND tentryKind);
VOID NEAR HOutElems(LPELEM pElemList, CHAR * szPrefix, CHAR * szSep, CHAR * szSepLast, BOOL fEnum);
VOID NEAR HOutType(LPTYPE pType);
VOID NEAR HOutShortNum(SHORT num, BOOL fHex);
VOID NEAR HOutLongNum(LONG num, BOOL fHex);
VOID NEAR HOutPropPrefix(LPFUNC pFunc);
VOID NEAR HOutGuid(LPATTR pAttr, CHAR * szGuidPrefix, LPSTR lpszName);
#ifdef PROFILE
VOID NEAR XOutF(LPSTR lpszData);
VOID NEAR XOut(CHAR * szData);
#else //PROFILE
#define XOutF HOutF
#define XOut HOut
#endif //PROFILE
VOID NEAR HOutF(LPSTR lpszData);
VOID NEAR HOut(CHAR * szData);
VOID NEAR SetCallType(CALLINGCONV cc);
VOID FAR OutputHFile
(
CHAR * szHFile
)
{
LPENTRY pEntry;
#ifdef WIN16
// convert szHFile in-place to OEM char set
AnsiToOem(szHFile, szHFile);
// don't bother converting back since this string is not used again
#endif // WIN16
// open the file
hHFile = fopen(szHFile, "w"); // open output file
if (hHFile == NULL)
ParseError(ERR_CANT_OPEN_HFILE);
Assert (SYS_WIN16 == 0 && SYS_WIN32 == 1 && SYS_MAC == 2 && SysKind <= SYS_MAX);
HOut(szHeadFile); // output file header
HOutF(typlib.szLibName); // output type library name
HOut(" */\n\n#ifndef _"); // output: #ifndef _<libname>_H_
HOutF(typlib.szLibName); // #define _<libname>_H_
HOut("_H_\n#define _");
HOutF(typlib.szLibName);
HOut("_H_\n");
HOutGuid(&typlib.attr, szHeadGuidLIBID, typlib.szLibName);
if (fSpecifiedInterCC) {
HOut(szCCHeader);
}
if (typlib.pEntry)
{
pEntry = (LPENTRY)ListFirst(typlib.pEntry); // point to first entry
#pragma warning(disable:4127)
while (TRUE)
#pragma warning(default:4127)
{
switch (pEntry->type.tentrykind & ~tFORWARD)
{
case tTYPEDEF:
HOutTypedef(&pEntry->type);
break;
case tENUM:
HOutEnum(&pEntry->type);
break;
case tSTRUCT:
case tUNION:
HOutStructUnion(&pEntry->type);
break;
case tMODULE:
HOutModule(pEntry);
break;
case tCOCLASS:
HOutCoclass(pEntry);
break;
case tINTERFACE:
case tDISPINTER:
HOutInterface(pEntry);
// fall through
case tINTRINSIC:
case tREF:
break; // nothing to output
#ifdef DEBUG
default:
if (pEntry->type.tentrykind & tIMPORTED)
break; // noting to output for imported types
Assert(FALSE);
#endif //DEBUG
}
// advance to next entry if not all done
if (pEntry == (LPENTRY)ListLast(typlib.pEntry))
break; // exit if all done
pEntry = (LPENTRY)pEntry->type.pNext;
} // WHILE
}
HOut("\n#endif\n");
fclose(hHFile); // done writing .H file
hHFile = NULL; // close done
// check for possible alignment problems
if (iAlignMax != iAlignDef)
ParseError(WARN_STRANGE_ALIGNMENT);
#ifdef PROFILE
printf("\n\ntotal functions: %d\n", cFuncsTotal);
printf("total function args: %d\n", cArgsTotal);
printf("total variables: %d\n", cVarsTotal);
ParseError(ERR_OM); // bogus early quit
#endif //PROFILE
}
VOID NEAR HOutTypedef
(
LPTYPE pType
)
{
XOut("\ntypedef ");
// output base type
HOutType(pType->td.ptypeAlias);
HOut(" ");
XOutF(pType->szName);
Assert(pType->td.ptypeAlias->tdesc.vt != VT_CARRAY);
XOut(";\n");
}
VOID NEAR HOutEnum
(
LPTYPE pType
)
{
XOut("\ntypedef enum ");
if (pType->structenum.szTag)
{
XOutF(pType->structenum.szTag);
if (pType->tentrykind & tFORWARD)
{
XOut(";\n");
return;
}
XOut(" ");
}
XOut("{\n");
HOutElems(pType->structenum.elemList, " ", ",\n", "\n", TRUE);
XOut("} ");
XOutF(pType->szName);
XOut(";\n");
}
VOID NEAR HOutStructUnion
(
LPTYPE pType
)
{
if ((pType->tentrykind & ~tFORWARD) == tSTRUCT)
XOut("\ntypedef struct ");
else
XOut("\ntypedef union ");
if (pType->structenum.szTag)
{
XOutF(pType->structenum.szTag);
if (pType->tentrykind & tFORWARD)
goto done;
XOut(" ");
}
XOut("{\n");
HOutElems(pType->structenum.elemList, " ", ";\n", ";\n", FALSE);
XOut("} ");
XOutF(pType->szName);
done:
XOut(";\n");
}
VOID NEAR HOutModule
(
LPENTRY pEntry
)
{
XOut(szHeadModule);
XOutF(pEntry->type.szName);
XOut(szHeadOleSuffix3);
HOutFuncs(pEntry->module.funcList, pEntry->type.tentrykind);
if (pEntry->module.constList)
HOutElems(pEntry->module.constList, " const ", ";\n", ";\n", FALSE);
}
VOID NEAR HOutCoclass
(
LPENTRY pEntry
)
{
if ((pEntry->type.tentrykind & tFORWARD) == 0) {
HOutGuid(&pEntry->attr, szHeadGuidCLSID, pEntry->type.szName);
}
// UNDONE: I don't think this will work in C.
HOut("\n#ifdef __cplusplus\nclass ");
HOutF(pEntry->type.szName);
HOut(";\n#endif\n");
}
VOID NEAR HOutInterface
(
LPENTRY pEntry
)
{
LPSTR lpszBaseName;
TENTRYKIND tentrykind;
LPINTER lpInterFirst; // first base interface, if any
LPINTER lpInterLast; // second/last base interface, if any
tentrykind = pEntry->type.tentrykind;
if (tentrykind & tFORWARD)
{
// UNDONE: proper OLE format for forward declaration of interface?
// UNDONE: I don't think this will work in C. I think it wants:
// UNDONE: typedef interface <interfacename> <interfacename>;
HOut("\ninterface ");
HOutF(pEntry->type.szName);
HOut(";\n");
return;
}
HOutGuid(&pEntry->attr,
((tentrykind == tDISPINTER) ? szHeadGuidDIID: szHeadGuidIID),
pEntry->type.szName);
lpszBaseName = NULL;
lpInterFirst = NULL;
if (pEntry->type.inter.interList)
{
lpInterFirst = (LPINTER)ListFirst(pEntry->type.inter.interList);
lpInterLast = (LPINTER)ListLast(pEntry->type.inter.interList);
// We assume there's only single inheritance at this point
// But in the case of a dispinterface, we could have the first
// base interface be IDispatch, and the 2nd base interface be
// the interface that we're capable of dispatching on. In any
// case, there can't be more than 2 interfaces in the list.
Assert((LPINTER)lpInterFirst->pNext == lpInterLast);
lpszBaseName = lpInterFirst->ptypeInter->szName;
Assert(lpszBaseName);
}
// first output the header comment
HOut((tentrykind == tDISPINTER) ? szHeadDispinter: szHeadInter);
HOutF(pEntry->type.szName);
HOut(szHeadOleSuffix3);
// then output the OLE header
HOut(szHeadOlePrefix0);
HOutF(pEntry->type.szName);
HOut("\n\n");
HOut(szHeadOlePrefix1);
if (lpszBaseName)
HOut("_");
HOut("(");
HOutF(pEntry->type.szName);
if (lpszBaseName) // if this inherits from somebody
{ // then add ", <baseinterface>"
HOut(", ");
HOutF(lpszBaseName);
}
HOut(szHeadOlePrefix2);
if (tentrykind == tDISPINTER)
{
Assert (lpszBaseName);
HOut(szHeadOlePrefix7);
HOut(szHeadIUnknown);
HOut(szHeadIDispatch);
HOut(szHeadOleSuffix7);
if (lpInterFirst != lpInterLast)
{ // specifies an interface that is dispatchable
HOut(szHeadDispatchable);
HOutF(lpInterLast->ptypeInter->szName);
HOut(szHeadOleSuffix3);
}
// first output the properties (commented out) in "struct" format
if (pEntry->dispinter.propList)
{
XOut(szHeadOlePrefix3);
XOutF(pEntry->type.szName);
XOut(szHeadOlePrefix5);
HOutElems(pEntry->dispinter.propList, " ", ";\n", ";\n", FALSE);
HOut(szHeadOleSuffix1);
}
// then output the methods (commented out) in "normal" format
if (pEntry->dispinter.methList)
{
XOut(szHeadOlePrefix3);
XOutF(pEntry->type.szName);
XOut(szHeadOlePrefix6);
HOutFuncs(pEntry->dispinter.methList, tDISPINTER);
HOut(szHeadOleSuffix1);
}
}
else
{ // an interface
// output interface functions, and base interface functions (if any)
HOutBaseInter(pEntry, FALSE);
}
// lastly, output the close curly
HOut(szHeadOleSuffix2);
}
VOID NEAR HOutBaseInter(LPENTRY pEntry, BOOL fRecurse)
{
LPINTER lpInterBase;
// hard-coded descriptions for the 2 most common
if (!FCmpCaseIns(pEntry->type.szName, "IUnknown"))
{
HOut(szHeadIUnknown);
}
else if (!FCmpCaseIns(pEntry->type.szName, "IDispatch"))
{
if (!fRecurse)
HOut(szHeadOlePrefix7);
HOut(szHeadIUnknown);
if (!fRecurse)
HOut(szHeadOleSuffix7);
HOut(szHeadIDispatch);
}
else if ((pEntry->type.tentrykind & ~tFORWARD) != tINTERFACE)
{
// can't deal with imported base interfaces
HOut(szHeadOlePrefix3);
HOutF(pEntry->type.szName);
HOut(szHeadOlePrefix4);
HOut(szHeadMethods);
}
else
{
if (pEntry->type.tentrykind & tFORWARD) {
// if this is a forward decl, follow pointer back to real
// interface (since base interfaces and functions aren't
// stored in the forward declare)
pEntry = pEntry->lpEntryForward;
}
lpInterBase = pEntry->type.inter.interList;
if (lpInterBase) // if this inherits from somebody,
{ // then first describe the base interface
if (!fRecurse)
HOut(szHeadOlePrefix7);
// HACK -- assumes we can cast LPTYPE to LPENTRY, but
// this is always true given our above validation
HOutBaseInter((LPENTRY)(lpInterBase->ptypeInter), TRUE);
if (!fRecurse)
HOut(szHeadOleSuffix7);
}
// output the interface functions in OLE format
XOut(szHeadOlePrefix3);
XOutF(pEntry->type.szName);
XOut(szHeadOlePrefix4);
HOutFuncs(pEntry->inter.funcList, tINTERFACE);
}
}
VOID NEAR HOutFuncs
(
LPFUNC pFuncList,
TENTRYKIND tentryKind
)
{
LPFUNC pFunc;
if (pFuncList == NULL) // nothing to output if no functions
return;
pFunc = (LPFUNC)ListFirst(pFuncList); // point to first entry
#pragma warning(disable:4127)
while (TRUE)
#pragma warning(default:4127)
{
#ifndef PROFILE
if (tentryKind == tINTERFACE)
{
if (fSpecifiedInterCC) {
// set up STDMETHODCALLTYPE based on the calling
// convention and SYSKIND
if (pFunc->func.attr.fAttr2 & f2CCDEFAULTED)
SetCallType(CALL_DEFAULT);
else if (pFunc->func.attr.fAttr2 & f2PASCAL)
SetCallType(CALL_PASCAL);
else if (pFunc->func.attr.fAttr2 & f2STDCALL)
SetCallType(CALL_STDCALL);
else
{
Assert(pFunc->func.attr.fAttr2 & f2CDECL)
SetCallType(CALL_CDECL);
}
}
HOut(szHeadOleFuncPrefix1); // leading spaces
HOut(szHeadOleFuncPrefix2);
if (pFunc->func.elemType->tdesc.vt == VT_HRESULT)
HOut("(");
else
{
HOut("_(");
// output function return type
HOutType(pFunc->func.elemType);
HOut(szHeadOleFuncPrefix3);
}
HOutPropPrefix(pFunc);
XOutF(pFunc->func.szElemName);
HOut(szHeadOleArgPrefix1);
if (pFunc->cArgs)
{
HOut(szHeadOleArgPrefix2);
// output list of variables, separating them by
// commas, with nothing after last item
HOutElems(pFunc->argList, "", ", ", "", FALSE);
}
XOut(szHeadOleArgSuffix);
}
else
#endif //!PROFILE
{
HOut(szHeadOleFuncPrefix1); // leading spaces
if (tentryKind == tMODULE)
HOut ("extern ");
// output function return type
HOutType(pFunc->func.elemType);
HOut(" ");
// output calling convention
if (!(pFunc->func.attr.fAttr2 & f2CCDEFAULTED)) {
if (pFunc->func.attr.fAttr2 & f2PASCAL)
HOut("__pascal ");
else if (pFunc->func.attr.fAttr2 & f2CDECL)
HOut("__cdecl ");
else if (pFunc->func.attr.fAttr2 & f2STDCALL)
HOut("__stdcall ");
#ifdef DEBUG
else Assert(FALSE);
#endif //DEBUG
}
HOutPropPrefix(pFunc);
XOutF(pFunc->func.szElemName);
Assert(pFunc->func.elemType->tdesc.vt != VT_CARRAY);
XOut("(");
#ifdef PROFILE
cArgsTotal += pFunc->cArgs;
cFuncsTotal++;
#endif //PROFILE
if (pFunc->cArgs == 0)
{
HOut("void");
}
else
{
// output list of variables, separating them by
// commas, with nothing after last item
HOutElems(pFunc->argList, "", ", ", "", FALSE);
#ifdef PROFILE
cVarsTotal-= pFunc->cArgs; // would be counted twice
#endif //PROFILE
}
XOut(");\n");
}
// advance to next entry if not all done
if (pFunc == (LPFUNC)ListLast(pFuncList))
break; // exit if all done
pFunc = (LPFUNC)pFunc->func.pNext;
}
if (fSpecifiedInterCC) {
SetCallType(CALL_DEFAULT); // reset to default STDMETHODCALLTYPE
}
}
VOID NEAR SetCallType
(
CALLINGCONV cc
)
{
Assert (fSpecifiedInterCC); // caller should have checked
if (cc != ccInterCurrent)
{ // if current different than last
HOut(szUndefCallType); // undefine current STDMETHODCALLTYPE
if (cc == CALL_DEFAULT) {
HOut(szResetCallType); // reset to default
} else {
HOut(szDefCallTypePrefix); // re-define to new value
HOut(rgszCallType[cc]);
HOut("\n");
}
ccInterCurrent = cc; // update current value
}
}
VOID NEAR HOutPropPrefix
(
LPFUNC pFunc
)
{
// add a prefix to the function name if this is a property function
if (pFunc->func.attr.fAttr & fPROPGET)
HOut("get_");
else if (pFunc->func.attr.fAttr & fPROPPUT)
HOut("put_");
else if (pFunc->func.attr.fAttr & fPROPPUTREF)
HOut("putref_");
}
VOID NEAR HOutShortNum
(
SHORT num,
BOOL fHex
)
{
CHAR szBuffer[30]; // space to list a number
sprintf(szBuffer,
fHex ? "0x%hX" : "%hd",
num);
HOut(szBuffer);
}
VOID NEAR HOutLongNum
(
LONG num,
BOOL fHex
)
{
CHAR szBuffer[30]; // space to list a number
// Stupid C will choke if this number is printed in decimal
if (num == 0x80000000)
fHex = TRUE;
sprintf(szBuffer,
fHex ? "0x%lX" : "%ld",
num);
HOut(szBuffer);
}
VOID NEAR HOutElems
(
LPELEM pElemList,
CHAR * szPrefix,
CHAR * szSep,
CHAR * szSepLast,
BOOL fEnum
)
{
LPELEM pElem;
WORD cDims;
ARRAYDESC FAR* lpAD;
BOOL fHex;
LPOLESTR lpch;
CHAR * pch;
CHAR buf[2];
UINT cch;
pElem = (LPELEM)ListFirst(pElemList); // point to first entry
#pragma warning(disable:4127)
while (TRUE)
#pragma warning(default:4127)
{
HOut(szPrefix);
if (!fEnum)
{
// output elem type, with the right number of "*'s"
HOutType(pElem->elemType);
HOut(" ");
}
XOutF(pElem->szElemName);
#ifdef PROFILE
cVarsTotal++;
#endif //PROFILE
if (!fEnum && pElem->elemType->tdesc.vt == VT_CARRAY)
{ // base type already outputted before name above
lpAD = pElem->elemType->tdesc.lpadesc;
for (cDims = 0; cDims < lpAD->cDims; cDims++)
{
HOut("[");
#if 0 // arrays of the form "a[]" aren't supported
if (lpAD->rgbounds[cDims].cElements)
#endif //0
HOutLongNum((long)lpAD->rgbounds[cDims].cElements, FALSE);
HOut("]");
}
}
if (pElem->attr.fAttr2 & f2GotConstVal)
{
HOut(" = ");
fHex = FALSE;
if (!fEnum) {
// display all the unsigned constants in Hex form
switch (pElem->elemType->tdesc.vt) {
case VT_UI1:
case VT_UI2:
case VT_UI4:
case VT_UINT:
case VT_ERROR:
fHex = TRUE;
break;
default:
break;
}
}
// output the constant element's value
switch (pElem->lpElemVal->vt)
{
case VT_I2:
case VT_BOOL:
HOutShortNum(pElem->lpElemVal->iVal, fHex);
break;
case VT_I4:
case VT_ERROR:
HOutLongNum(pElem->lpElemVal->lVal, fHex);
break;
case VT_BSTR:
HOut("\"");
// output 1 char at a time, in order to handle
// escape sequences in strings
lpch = pElem->lpElemVal->bstrVal;
cch = SysStringLen(lpch);
while (cch) {
switch(*lpch) {
case 0x0:
pch = "\\0";
break;
case 0x7:
pch = "\\a";
break;
case 0x8:
pch = "\\b";
break;
case 0x9:
pch = "\\t";
break;
case 0xA:
if (SysKind == SYS_MAC)
pch = "\\r";
else
pch = "\\n";
break;
case 0xB:
pch = "\\v";
break;
case 0xC:
pch = "\\f";
break;
case 0xD:
if (SysKind == SYS_MAC)
pch = "\\n";
else
pch = "\\r";
break;
default:
#ifdef WIN32
SideAssert (WideCharToMultiByte(CP_ACP,
0,
lpch,
1,
buf,
1,
NULL,
NULL) != 0);
#else //WIN32
buf[0] = *lpch;
#endif //WIN32
buf[1] = '\0';
pch = buf;
break;
}
HOut(pch); // output the char
lpch++;
cch--;
}
HOut("\"");
break;
// CONSIDER: support more constant types.
default:
Assert(FALSE);
}
}
// advance to next entry if not all done
if (pElem == (LPELEM)ListLast(pElemList))
{
XOut(szSepLast);
break; // exit if all done
}
XOut(szSep);
pElem = pElem->pNext;
}
}
VOID NEAR HOutType
(
LPTYPE pType
)
{
SHORT i;
CHAR * szPrefix;
switch (pType->tdesc.vt)
{
case VT_PTR:
// first output the base type
HOutType(pType->ref.ptypeBase);
// now output the proper number of "*"'s
Assert (pType->ref.cIndirect != 0);
for (i = pType->ref.cIndirect; i > 0; i--)
{
// always output "FAR" for constency (same as dispatch.h)
HOut(" FAR*");
}
break;
case VT_CARRAY:
// just output the base type -- we'll handle this stuff
// after we output the name
HOutType(pType->ref.ptypeBase);
break;
case VT_SAFEARRAY:
HOut("SAFEARRAY FAR*");
break;
case VT_BOOL: // special case -- "boolean" no good
HOut("VARIANT_BOOL");
break;
case VT_CY: // special case -- "CURRENCY" no good
HOut("CY");
break;
default:
// output "unsigned" if necessary
if (pType->tentrykind == tINTRINSIC && pType->intr.fUnsigned)
HOut("unsigned ");
switch (pType->tentrykind & ~tFORWARD)
{
case tUNION:
szPrefix = "union ";
goto outputPrefix;
case tSTRUCT:
szPrefix = "struct ";
outputPrefix:
if (pType->structenum.szTag)
{
HOut(szPrefix);
HOutF(pType->structenum.szTag);
break;
}
// otherwise, fall into default processing
default:
HOutF(pType->szName);
}
break;
}
}
VOID NEAR HOutGuid
(
LPATTR pAttr,
CHAR * szGuidPrefix,
LPSTR lpszName
)
{
CHAR szBuffer[100]; // space to list a number UNDONE: Tune
GUID FAR * lpGuid;
if ((pAttr->fAttr & fUUID) == 0)
return; // no guid to output
lpGuid = pAttr->lpUuid;
HOut(szHeadGuidPrefix);
HOut(szGuidPrefix); // prefix the user's name
HOutF(lpszName); // add the user's name
sprintf(szBuffer, ",0x%.8lX,0x%.4X,0x%.4X,0x%.2X,0x%.2X,0x%.2X,0x%.2X,0x%.2X,0x%.2X,0x%.2X,0x%.2X);\n",
lpGuid->Data1,
lpGuid->Data2,
lpGuid->Data3,
lpGuid->Data4[0],
lpGuid->Data4[1],
lpGuid->Data4[2],
lpGuid->Data4[3],
lpGuid->Data4[4],
lpGuid->Data4[5],
lpGuid->Data4[6],
lpGuid->Data4[7]
);
HOut(szBuffer);
}
VOID NEAR HOutF
(
LPSTR lpszData
)
{
CHAR szBuffer[256];
_fstrcpy(szBuffer, lpszData); // copy data near
HOut(szBuffer); // output it
}
VOID NEAR HOut
(
CHAR * szData
)
{
if (fputs(szData, hHFile) < 0) // write the data
ParseError(ERR_WRITING_HFILE);
}
#ifdef PROFILE
VOID NEAR XOutF
(
LPSTR lpszData
)
{
CHAR szBuffer[256];
_fstrcpy(szBuffer, lpszData); // copy data near
XOut(szBuffer); // output it
}
VOID NEAR XOut
(
CHAR * szData
)
{
printf(szData); // output to console
}
#endif //PROFILE