You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1321 lines
44 KiB
1321 lines
44 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1999.
|
|
//
|
|
// File: implib.cxx
|
|
//
|
|
// Contents: import lib functions
|
|
//
|
|
// Classes: NODE_MANAGER
|
|
//
|
|
// Functions: TypelibError
|
|
// TypeinfoError
|
|
// GetStringFromGuid
|
|
// AddTypeLibraryMembers
|
|
//
|
|
// History: 5-02-95 stevebl Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#pragma warning ( disable : 4514 )
|
|
|
|
#include "tlcommon.hxx"
|
|
#include "tlgen.hxx"
|
|
#include "tllist.hxx"
|
|
#include "becls.hxx"
|
|
#include "walkctxt.hxx"
|
|
|
|
// Initialize an instance of a type library list.
|
|
// This way it will clean itself up as necessary.
|
|
CTypeLibraryList gtllist;
|
|
|
|
extern short ImportLevel;
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: TypelibError
|
|
//
|
|
// Synopsis: Report generic type library error and exit.
|
|
//
|
|
// Arguments: [szFile] - file associated with the error
|
|
//
|
|
// History: 5-02-95 stevebl Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void TypelibError(char * szFile, HRESULT /* UNREF hr */)
|
|
{
|
|
RpcError(NULL, 0, ERR_TYPELIB, szFile);
|
|
exit(ERR_TYPELIB);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: TypeinfoError
|
|
//
|
|
// Synopsis: Report generic type info error and exit.
|
|
//
|
|
// History: 5-02-95 stevebl Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void TypeinfoError(HRESULT /* UNREF hr */)
|
|
{
|
|
RpcError(NULL, 0, ERR_TYPEINFO, NULL);
|
|
exit(ERR_TYPEINFO);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: AddToGuidString
|
|
//
|
|
// Synopsis: Private helper function for GetStringFromGuid.
|
|
// Adds exactly cch hex characters to the string pch.
|
|
//
|
|
// Arguments: [pch] - pointer to the next available position in the string
|
|
// buffer
|
|
// [cch] - number of characters to add to the string buffer
|
|
// [uVal] - value to be converted to text representation
|
|
//
|
|
// History: 5-02-95 stevebl Created
|
|
//
|
|
// Modifies: pch is advanced by cch characters (i.e. left pointing to the
|
|
// next available position in the buffer).
|
|
//
|
|
// Notes: pch must be large enough to accept the characters.
|
|
// The resulting string is not null terminated.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void AddToGuidString(char * &pch, unsigned cch, unsigned long uVal)
|
|
{
|
|
char bVal;
|
|
unsigned long uMask = 0xf << ((cch - 1) * 4);
|
|
while (cch)
|
|
{
|
|
bVal = (char)((uVal & uMask) >> ((cch - 1) * 4));
|
|
if (bVal < 10)
|
|
*(pch++) = char( '0' + bVal );
|
|
else
|
|
*(pch++) = char ( 'a' + bVal - 10 );
|
|
uMask >>= 4;
|
|
cch--;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetStringFromGuid
|
|
//
|
|
// Synopsis: returns the string representation of a guid
|
|
//
|
|
// Arguments: [g] - guid
|
|
//
|
|
// Returns: pointer to a newly allocated string
|
|
//
|
|
// History: 5-02-95 stevebl Created
|
|
//
|
|
// Notes: It is up to the caller to free the resulting string.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
char * GetStringFromGuid(GUID &g)
|
|
{
|
|
char * sz = new char [37];
|
|
char * pch = sz;
|
|
AddToGuidString(pch, 8, g.Data1);
|
|
*(pch++) = '-';
|
|
AddToGuidString(pch, 4, g.Data2);
|
|
*(pch++) = '-';
|
|
AddToGuidString(pch, 4, g.Data3);
|
|
*(pch++) = '-';
|
|
int i;
|
|
for (i = 0; i < 2; i++)
|
|
{
|
|
AddToGuidString(pch, 2, g.Data4[i]);
|
|
}
|
|
*(pch++) = '-';
|
|
for (; i < 8; i++)
|
|
{
|
|
AddToGuidString(pch, 2, g.Data4[i]);
|
|
}
|
|
*(pch++) = '\0';
|
|
return sz;
|
|
}
|
|
|
|
struct NODE_MANAGER_ELEMENT
|
|
{
|
|
ITypeInfo * pti;
|
|
named_node * pskl;
|
|
NODE_MANAGER_ELEMENT * pNext;
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: NODE_MANAGER
|
|
//
|
|
// Purpose: Maintains an ordered list of every ITypeInfo for which a
|
|
// node_skl has been generated.
|
|
//
|
|
// Interface: GetNode -- retrieve a node_skl * from a type library
|
|
//
|
|
// History: 5-02-95 stevebl Created
|
|
//
|
|
// Notes: A client can call GetNode() to get a node_skl * from an
|
|
// ITypeInfo pointer. If one has previously been generated then
|
|
// the caller will get a pointer to the previously generated
|
|
// node. Otherwise, GetNode() will call ExpandTI to generate one.
|
|
//
|
|
// This class exists as a mechanism to avoid infinite recursion
|
|
// when importing type infos with cyclic type dependencies.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
class NODE_MANAGER
|
|
{
|
|
private:
|
|
NODE_MANAGER_ELEMENT * pHead;
|
|
void ExpandTI(named_node * &pNode, ITypeInfo * pti);
|
|
node_skl * GetNodeFromTYPEDESC(TYPEDESC tdesc, ITypeInfo * pti);
|
|
named_node * GetNodeFromVARDESC(VARDESC vdesc, ITypeInfo * pti);
|
|
named_node * GetNodeFromFUNCDESC(FUNCDESC fdesc, ITypeInfo *pti);
|
|
void SetIDLATTRS(named_node * pNode, IDLDESC idldesc);
|
|
void AddMembers(MEMLIST * pNode, TYPEATTR * ptattr, ITypeInfo * pti);
|
|
expr_node * GetValueOfConstant(VARIANT * pVar);
|
|
public:
|
|
NODE_MANAGER()
|
|
{
|
|
pHead = NULL;
|
|
}
|
|
|
|
~NODE_MANAGER()
|
|
{
|
|
NODE_MANAGER_ELEMENT * pNext;
|
|
while (pHead)
|
|
{
|
|
pHead->pti->Release();
|
|
pNext = pHead->pNext;
|
|
delete(pHead);
|
|
pHead = pNext;
|
|
};
|
|
}
|
|
|
|
node_skl * GetNode(ITypeInfo * pti);
|
|
|
|
} gNodeManager;
|
|
|
|
BOOL FAddImportLib(char * szLibraryFileName)
|
|
{
|
|
return gtllist.Add(szLibraryFileName);
|
|
}
|
|
|
|
BOOL FIsLibraryName(char * szName)
|
|
{
|
|
return (NULL != gtllist.FindLibrary(szName));
|
|
}
|
|
|
|
extern SymTable * pBaseSymTbl;
|
|
|
|
node_href::~node_href()
|
|
{
|
|
if (pTypeInfo)
|
|
((ITypeInfo *)pTypeInfo)->Release();
|
|
}
|
|
|
|
extern IINFODICT * pInterfaceInfoDict;
|
|
char * GenIntfName();
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: node_href::Resolve
|
|
//
|
|
// Synopsis: Expands a referenced type info into a complete type graph.
|
|
//
|
|
// Returns: Pointer to the expanded typegraph.
|
|
//
|
|
// History: 5-02-95 stevebl Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
named_node * node_href::Resolve()
|
|
{
|
|
char * sz;
|
|
named_node * pReturn = (named_node *)GetChild();
|
|
if (!pReturn)
|
|
{
|
|
pInterfaceInfoDict->StartNewInterface();
|
|
|
|
// start a dummy interface for intervening stuff
|
|
node_interface * pOuter = new node_interface;
|
|
pOuter->SetSymName( GenIntfName() );
|
|
pOuter->SetFileNode( GetDefiningFile() );
|
|
pInterfaceInfoDict->SetInterfaceNode( pOuter );
|
|
|
|
pReturn = (named_node *)gNodeManager.GetNode((ITypeInfo*)pTypeInfo);
|
|
SetChild(pReturn);
|
|
sz = pReturn->GetSymName();
|
|
if ( sz )
|
|
SetSymName(sz);
|
|
|
|
pInterfaceInfoDict->EndNewInterface();
|
|
}
|
|
return pReturn;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: NODE_MANAGER::GetNode
|
|
//
|
|
// Synopsis: Gets a type graph node from a type info pointer.
|
|
//
|
|
// Arguments: [pti] - type info pointer
|
|
//
|
|
// Returns: pointer to the type graph described by the type info
|
|
//
|
|
// History: 5-02-95 stevebl Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
node_skl * NODE_MANAGER::GetNode(ITypeInfo * pti)
|
|
{
|
|
NODE_MANAGER_ELEMENT ** ppThis = &pHead;
|
|
while (*ppThis && (*ppThis)->pti <= pti)
|
|
{
|
|
if ((*ppThis)->pti == pti)
|
|
return (*ppThis)->pskl;
|
|
ppThis = &((*ppThis)->pNext);
|
|
}
|
|
NODE_MANAGER_ELEMENT * pNew = new NODE_MANAGER_ELEMENT;
|
|
pNew->pti = pti;
|
|
// Make sure no one can release this ITypeInfo pointer out from under us.
|
|
// The corresponding release() occurs in NODE_MANAGER's destructor.
|
|
pti->AddRef();
|
|
// insert the new node into the table
|
|
pNew->pNext = *ppThis;
|
|
*ppThis = pNew;
|
|
// expand the node
|
|
ExpandTI(pNew->pskl, pti);
|
|
((named_node*)(pNew->pskl))->SetFileNode(pInterfaceInfoDict->GetInterfaceNode()->GetDefiningFile() );
|
|
((named_node*)(pNew->pskl))->SetDefiningTLB(pInterfaceInfoDict->GetInterfaceNode()->GetDefiningFile() );
|
|
return pNew->pskl;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: NODE_MANAGER::ExpandTI
|
|
//
|
|
// Synopsis: This is where all the work gets done.
|
|
// Takes a type info pointer and expands it into a type graph.
|
|
//
|
|
// Arguments: [pti] - pointer to the type info
|
|
//
|
|
// Returns: pointer to the type graph
|
|
//
|
|
// History: 5-02-95 stevebl Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void NODE_MANAGER::ExpandTI(named_node * &pNode, ITypeInfo * pti)
|
|
{
|
|
TYPEATTR * ptattr;
|
|
HRESULT hr;
|
|
BSTR bstrName;
|
|
|
|
pNode = NULL;
|
|
hr = pti->GetTypeAttr(&ptattr);
|
|
pti->GetDocumentation(-1, &bstrName, NULL, NULL, NULL);
|
|
char * szName = TranscribeO2A( bstrName );
|
|
LateBound_SysFreeString(bstrName);
|
|
BOOL fExtractGuid = TRUE;
|
|
|
|
switch(ptattr->typekind)
|
|
{
|
|
case TKIND_MODULE:
|
|
pNode = new node_module();
|
|
pNode->SetSymName(szName);
|
|
// Add properties and methods
|
|
AddMembers((MEMLIST *)((node_module *)pNode), ptattr, pti);
|
|
break;
|
|
|
|
case TKIND_DISPATCH:
|
|
// The code under the if has never been run due to the bug in the condition.
|
|
// The condition according to the comment below should read as in the next line.
|
|
//
|
|
// if ( ! (ptattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION | TYPEFLAG_FDUAL)) )
|
|
//
|
|
// However, fixing the line according to the original intentions brought in
|
|
// a regression because the code paths have changed.
|
|
// Hence, this has been commented out as a workaround for the VC 5.0 release
|
|
// to force the code to execute like previously.
|
|
//
|
|
/*
|
|
if ( 0 == ptattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION | TYPEFLAG_FDUAL) )
|
|
{
|
|
pNode = new node_dispinterface();
|
|
pNode->SetSymName(szName);
|
|
// Ignore impltypes, add properties and methods
|
|
AddMembers((MEMLIST *)((node_dispinterface *)pNode), ptattr, pti);
|
|
break;
|
|
}
|
|
*/
|
|
|
|
// if TYPEFLAG_FOLEAUTOMATION or TYPEFLAG_FDUAL is set,
|
|
// erase it's impltype (which will be IDispatch since it is
|
|
// really a dispinterface) then fall through and treat it as a
|
|
// normal interface
|
|
|
|
ptattr->cImplTypes = 0;
|
|
|
|
// fall through
|
|
|
|
case TKIND_INTERFACE:
|
|
{
|
|
pNode = new node_interface();
|
|
|
|
// consider processing all attributes
|
|
if ( ( ptattr->wTypeFlags & ( TYPEFLAG_FOLEAUTOMATION | TYPEFLAG_FDUAL ) ) != 0 )
|
|
{
|
|
( ( node_interface* ) pNode )->HasOLEAutomation( TRUE );
|
|
}
|
|
pNode->SetSymName(szName);
|
|
// Add impltype as base interface reference
|
|
if (ptattr->cImplTypes)
|
|
{
|
|
ITypeInfo * ptiRef;
|
|
HREFTYPE hrt;
|
|
hr = pti->GetRefTypeOfImplType(0, &hrt);
|
|
hr = pti->GetRefTypeInfo(hrt, &ptiRef);
|
|
if (FAILED(hr))
|
|
{
|
|
TypeinfoError(hr);
|
|
}
|
|
node_interface_reference * pir =
|
|
new node_interface_reference((node_interface *)GetNode(ptiRef));
|
|
int implflags;
|
|
hr = pti->GetImplTypeFlags(0, &implflags);
|
|
if (implflags & IMPLTYPEFLAG_FDEFAULT)
|
|
{
|
|
pir->SetAttribute(ATTR_DEFAULT);
|
|
}
|
|
if (implflags & IMPLTYPEFLAG_FSOURCE)
|
|
{
|
|
pir->SetAttribute(new node_member_attr(MATTR_SOURCE));
|
|
}
|
|
if (implflags & IMPLTYPEFLAG_FDEFAULTVTABLE)
|
|
{
|
|
pir->SetAttribute(new node_member_attr(MATTR_DEFAULTVTABLE));
|
|
}
|
|
if (implflags & IMPLTYPEFLAG_FRESTRICTED)
|
|
{
|
|
pir->SetAttribute(new node_member_attr(MATTR_RESTRICTED));
|
|
}
|
|
((node_interface *)pNode)->SetMyBaseInterfaceReference(pir);
|
|
ptiRef->Release();
|
|
// NOTE - Multiple inheritance is not supported.
|
|
}
|
|
else
|
|
{
|
|
if (0 == _stricmp(szName, "IUnknown"))
|
|
((node_interface *)pNode)->SetValidRootInterface();
|
|
}
|
|
// Add properties and methods as children
|
|
AddMembers((MEMLIST *)((node_interface *)pNode), ptattr, pti);
|
|
}
|
|
break;
|
|
|
|
case TKIND_COCLASS:
|
|
pNode = new node_coclass();
|
|
pNode->SetSymName(szName);
|
|
// Add impltypes
|
|
{
|
|
unsigned cImplTypes = ptattr->cImplTypes;
|
|
while (cImplTypes--)
|
|
{
|
|
ITypeInfo * ptiRef;
|
|
HREFTYPE hrt;
|
|
hr = pti->GetRefTypeOfImplType(cImplTypes, &hrt);
|
|
hr = pti->GetRefTypeInfo(hrt, &ptiRef);
|
|
if (FAILED(hr))
|
|
{
|
|
TypeinfoError(hr);
|
|
}
|
|
node_interface_reference * pir =
|
|
new node_interface_reference((node_interface *)GetNode(ptiRef));
|
|
int implflags;
|
|
hr = pti->GetImplTypeFlags(cImplTypes, &implflags);
|
|
if (implflags & IMPLTYPEFLAG_FDEFAULT)
|
|
{
|
|
pir->SetAttribute(ATTR_DEFAULT);
|
|
}
|
|
if (implflags & IMPLTYPEFLAG_FSOURCE)
|
|
{
|
|
pir->SetAttribute(new node_member_attr(MATTR_SOURCE));
|
|
}
|
|
if (implflags & IMPLTYPEFLAG_FDEFAULTVTABLE)
|
|
{
|
|
pir->SetAttribute(new node_member_attr(MATTR_DEFAULTVTABLE));
|
|
}
|
|
if (implflags & IMPLTYPEFLAG_FRESTRICTED)
|
|
{
|
|
pir->SetAttribute(new node_member_attr(MATTR_RESTRICTED));
|
|
}
|
|
((node_coclass *)pNode)->AddFirstMember(pir);
|
|
ptiRef->Release();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TKIND_ALIAS:
|
|
pNode = new node_def(szName);
|
|
// add the type as a child
|
|
pNode->SetChild(GetNodeFromTYPEDESC(ptattr->tdescAlias, pti));
|
|
pNode->SetAttribute(new node_type_attr(TATTR_PUBLIC));
|
|
fExtractGuid = FALSE;
|
|
break;
|
|
|
|
case TKIND_ENUM:
|
|
pNode = new node_enum(szName);
|
|
// add enumeration fields
|
|
AddMembers((MEMLIST *)((node_enum *)pNode), ptattr, pti);
|
|
fExtractGuid = FALSE;
|
|
( ( node_enum * ) pNode )->SetZeePee( ptattr->cbAlignment );
|
|
break;
|
|
|
|
case TKIND_RECORD:
|
|
pNode = new node_struct(szName);
|
|
// add members
|
|
AddMembers((MEMLIST *)((node_struct *)pNode), ptattr, pti);
|
|
fExtractGuid = FALSE;
|
|
( ( node_struct * ) pNode )->SetZeePee( ptattr->cbAlignment );
|
|
break;
|
|
|
|
case TKIND_UNION:
|
|
pNode = new node_union(szName);
|
|
// add members
|
|
AddMembers((MEMLIST *)((node_union *)pNode), ptattr, pti);
|
|
fExtractGuid = FALSE;
|
|
( ( node_union * ) pNode )->SetZeePee( ptattr->cbAlignment );
|
|
break;
|
|
|
|
default:
|
|
MIDL_ASSERT(!"Illegal TKIND");
|
|
break;
|
|
}
|
|
// make sure that all the TYPEDESC flags are preserved
|
|
pNode->SetAttribute(new node_constant_attr(
|
|
new expr_constant(ptattr->wTypeFlags), ATTR_TYPEDESCATTR));
|
|
// and set each individual flag that we know about as of this writing
|
|
if (ptattr->wTypeFlags & TYPEFLAG_FLICENSED)
|
|
{
|
|
pNode->SetAttribute(new node_type_attr(TATTR_LICENSED));
|
|
}
|
|
if (ptattr->wTypeFlags & TYPEFLAG_FAPPOBJECT)
|
|
{
|
|
pNode->SetAttribute(new node_type_attr(TATTR_APPOBJECT));
|
|
}
|
|
if (ptattr->wTypeFlags & TYPEFLAG_FCONTROL)
|
|
{
|
|
pNode->SetAttribute(new node_type_attr(TATTR_CONTROL));
|
|
}
|
|
if (ptattr->wTypeFlags & TYPEFLAG_FDUAL)
|
|
{
|
|
pNode->SetAttribute(new node_type_attr(TATTR_DUAL));
|
|
}
|
|
if (ptattr->wTypeFlags & TYPEFLAG_FPROXY)
|
|
{
|
|
pNode->SetAttribute(new node_type_attr(TATTR_PROXY));
|
|
}
|
|
if (ptattr->wTypeFlags & TYPEFLAG_FNONEXTENSIBLE)
|
|
{
|
|
pNode->SetAttribute(new node_type_attr(TATTR_NONEXTENSIBLE));
|
|
}
|
|
if (ptattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)
|
|
{
|
|
pNode->SetAttribute(new node_type_attr(TATTR_OLEAUTOMATION));
|
|
}
|
|
if (ptattr->wTypeFlags & TYPEFLAG_FRESTRICTED)
|
|
{
|
|
pNode->SetAttribute(new node_member_attr(MATTR_RESTRICTED));
|
|
}
|
|
if (ptattr->wTypeFlags & TYPEFLAG_FPREDECLID)
|
|
{
|
|
pNode->SetAttribute(new node_member_attr(MATTR_PREDECLID));
|
|
}
|
|
if (ptattr->wTypeFlags & TYPEFLAG_FHIDDEN)
|
|
{
|
|
pNode->SetAttribute(ATTR_HIDDEN);
|
|
}
|
|
if (fExtractGuid)
|
|
{
|
|
char * szGuid = GetStringFromGuid(ptattr->guid);
|
|
pNode->SetAttribute(new node_guid(szGuid));
|
|
}
|
|
pti->ReleaseTypeAttr(ptattr);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: NODE_MANAGER::GetNodeFromTYPEDESC
|
|
//
|
|
// Synopsis: Returns part of a type graph from a TYPEDESC structure.
|
|
//
|
|
// Arguments: [tdesc] - the TYPEDESC
|
|
// [pti] - the type info from which the TYPEDESC was retrieved
|
|
//
|
|
// Returns: type graph node
|
|
//
|
|
// History: 5-02-95 stevebl Created
|
|
//
|
|
// Notes: There are currently a couple of problem base types:
|
|
// VT_CY, VT_BSTR, VT_VARIANT, VT_DISPATCH, and VT_UNKNOWN.
|
|
//
|
|
// These types are currently expanded by looking them up in the
|
|
// global symbol table. This works because currently oaidl.idl
|
|
// is always imported when an ODL library statement is
|
|
// ecountered. It would be nice to be able to remove our
|
|
// dependancy on oaidl.idl but before we can do that, we need to
|
|
// reimplement this code to expand these types in another way.
|
|
// (NOTE that because these are BASE TYPES in ODL, there is no
|
|
// way to place their definitions in a type library. This means
|
|
// that it is not sufficient to simply get their definitions
|
|
// from some standard type library such as STDLIB.TLB.)
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
node_skl * NODE_MANAGER::GetNodeFromTYPEDESC(TYPEDESC tdesc, ITypeInfo * pti)
|
|
{
|
|
node_skl * pReturn = NULL;
|
|
switch (tdesc.vt)
|
|
{
|
|
// base types
|
|
case VT_I2:
|
|
pReturn = new node_base_type(NODE_SHORT, ATTR_SIGNED);
|
|
((named_node *)pReturn)->SetSymName("short");
|
|
break;
|
|
case VT_I4:
|
|
pReturn = new node_base_type(NODE_LONG, ATTR_SIGNED);
|
|
((named_node *)pReturn)->SetSymName("long");
|
|
break;
|
|
case VT_R4:
|
|
pReturn = new node_base_type(NODE_FLOAT, ATTR_NONE);
|
|
((named_node *)pReturn)->SetSymName("float");
|
|
break;
|
|
case VT_R8:
|
|
pReturn = new node_base_type(NODE_DOUBLE, ATTR_NONE);
|
|
((named_node *)pReturn)->SetSymName("double");
|
|
break;
|
|
case VT_I1:
|
|
pReturn = new node_base_type(NODE_CHAR, ATTR_SIGNED);
|
|
((named_node *)pReturn)->SetSymName("char");
|
|
break;
|
|
case VT_UI1:
|
|
pReturn = new node_base_type(NODE_CHAR, ATTR_UNSIGNED);
|
|
((named_node *)pReturn)->SetSymName("char");
|
|
break;
|
|
case VT_UI2:
|
|
pReturn = new node_base_type(NODE_SHORT, ATTR_UNSIGNED);
|
|
((named_node *)pReturn)->SetSymName("short");
|
|
break;
|
|
case VT_UI4:
|
|
pReturn = new node_base_type(NODE_LONG, ATTR_UNSIGNED);
|
|
((named_node *)pReturn)->SetSymName("long");
|
|
break;
|
|
case VT_I8:
|
|
pReturn = new node_base_type(NODE_INT64, ATTR_SIGNED);
|
|
((named_node *)pReturn)->SetSymName("int64");
|
|
break;
|
|
case VT_UI8:
|
|
pReturn = new node_base_type(NODE_INT64, ATTR_UNSIGNED);
|
|
((named_node *)pReturn)->SetSymName("int64");
|
|
break;
|
|
case VT_INT:
|
|
pReturn = new node_base_type(NODE_INT, ATTR_SIGNED);
|
|
((named_node *)pReturn)->SetSymName("INT");
|
|
break;
|
|
case VT_UINT:
|
|
pReturn = new node_base_type(NODE_INT, ATTR_UNSIGNED);
|
|
((named_node *)pReturn)->SetSymName("UINT");
|
|
break;
|
|
case VT_VOID:
|
|
pReturn = new node_base_type(NODE_VOID, ATTR_NONE);
|
|
((named_node *)pReturn)->SetSymName("void");
|
|
break;
|
|
case VT_BOOL:
|
|
pReturn = new node_base_type(NODE_BOOLEAN, ATTR_NONE);
|
|
((named_node *)pReturn)->SetSymName("BOOLEAN");
|
|
break;
|
|
// simple ODL base types (not base types in IDL)
|
|
case VT_HRESULT:
|
|
pReturn = new node_base_type(NODE_SHORT, ATTR_NONE);
|
|
((named_node *)pReturn)->SetSymName("HRESULT");
|
|
break;
|
|
case VT_DATE:
|
|
pReturn = new node_base_type(NODE_LONGLONG, ATTR_NONE);
|
|
((named_node *)pReturn)->SetSymName("DATE");
|
|
break;
|
|
case VT_LPSTR:
|
|
pReturn = new node_base_type(NODE_LONGLONG, ATTR_NONE);
|
|
((named_node *)pReturn)->SetSymName("LPSTR");
|
|
break;
|
|
case VT_LPWSTR:
|
|
pReturn = new node_base_type(NODE_LONGLONG, ATTR_NONE);
|
|
((named_node *)pReturn)->SetSymName("LPWSTR");
|
|
break;
|
|
case VT_ERROR:
|
|
pReturn = new node_base_type(NODE_INT64, ATTR_NONE);
|
|
((named_node *)pReturn)->SetSymName("SCODE");
|
|
break;
|
|
// complex ODL base types
|
|
case VT_DECIMAL:
|
|
{
|
|
SymKey key("DECIMAL", NAME_DEF);
|
|
pReturn = pBaseSymTbl->SymSearch(key);
|
|
}
|
|
break;
|
|
case VT_CY:
|
|
{
|
|
SymKey key("CURRENCY", NAME_DEF);
|
|
pReturn = pBaseSymTbl->SymSearch(key);
|
|
}
|
|
break;
|
|
case VT_BSTR:
|
|
{
|
|
SymKey key("BSTR", NAME_DEF);
|
|
pReturn = pBaseSymTbl->SymSearch(key);
|
|
}
|
|
break;
|
|
case VT_VARIANT:
|
|
{
|
|
SymKey key("VARIANT", NAME_DEF);
|
|
pReturn = pBaseSymTbl->SymSearch(key);
|
|
}
|
|
break;
|
|
case VT_DISPATCH:
|
|
{
|
|
SymKey key("IDispatch", NAME_DEF);
|
|
pReturn = new node_pointer(pBaseSymTbl->SymSearch(key));
|
|
}
|
|
break;
|
|
case VT_UNKNOWN:
|
|
{
|
|
SymKey key("IUnknown", NAME_DEF);
|
|
pReturn = new node_pointer(pBaseSymTbl->SymSearch(key));
|
|
}
|
|
break;
|
|
// complex types
|
|
case VT_PTR:
|
|
pReturn = new node_pointer(GetNodeFromTYPEDESC(*(tdesc.lptdesc), pti));
|
|
break;
|
|
case VT_SAFEARRAY:
|
|
pReturn = new node_safearray(GetNodeFromTYPEDESC(*(tdesc.lptdesc), pti));
|
|
break;
|
|
case VT_CARRAY:
|
|
{
|
|
node_skl * pCurrent = NULL;
|
|
node_skl * pPrev = NULL;
|
|
for (int i = 0; i < tdesc.lpadesc->cDims; i++)
|
|
{
|
|
pCurrent = new node_array(
|
|
new expr_constant(tdesc.lpadesc->rgbounds[i].lLbound),
|
|
new expr_constant((tdesc.lpadesc->rgbounds[i].cElements
|
|
+ tdesc.lpadesc->rgbounds[i].lLbound) - 1 )
|
|
);
|
|
if (pPrev)
|
|
{
|
|
pPrev->SetChild(pCurrent);
|
|
}
|
|
else
|
|
{
|
|
pReturn = pCurrent;
|
|
}
|
|
pPrev = pCurrent;
|
|
}
|
|
if (pCurrent)
|
|
(pCurrent)->SetChild(GetNodeFromTYPEDESC(tdesc.lpadesc->tdescElem, pti));
|
|
}
|
|
break;
|
|
case VT_USERDEFINED:
|
|
{
|
|
ITypeInfo * pRef;
|
|
HRESULT hr = pti->GetRefTypeInfo(tdesc.hreftype, &pRef);
|
|
if (FAILED(hr))
|
|
{
|
|
TypeinfoError(hr);
|
|
}
|
|
node_skl* pNode = GetNode(pRef);
|
|
NODE_T nk = pNode->NodeKind();
|
|
if ( nk == NODE_INTERFACE_REFERENCE || nk == NODE_INTERFACE )
|
|
{
|
|
pReturn = new node_interface_reference( (node_interface *) pNode );
|
|
}
|
|
else
|
|
{
|
|
pReturn = pNode;
|
|
}
|
|
pRef->Release();
|
|
}
|
|
break;
|
|
default:
|
|
MIDL_ASSERT(!"Illegal variant type found in a TYPEDESC");
|
|
break;
|
|
}
|
|
if (pReturn && (pReturn->NodeKind() == NODE_DEF) &&
|
|
pReturn->GetChild() &&
|
|
(pReturn->GetChild()->NodeKind() == NODE_FORWARD))
|
|
{
|
|
node_forward * pFwd = (node_forward *) pReturn->GetChild();
|
|
node_skl * pNewSkl = pFwd->ResolveFDecl();
|
|
if (pNewSkl)
|
|
{
|
|
pReturn = new node_def_fe(pReturn->GetSymName(), pNewSkl);
|
|
}
|
|
}
|
|
return pReturn;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: NODE_MANAGER::AddMembers
|
|
//
|
|
// Synopsis: Generic routine to add type graph elements for variables and
|
|
// functions to a type graph element.
|
|
//
|
|
// Arguments: [pNode] - pointer to the parent type graph node's MEMLIST
|
|
// [ptattr] - pointer to the parent type info's TYPEATTR struct
|
|
// [pti] - pointer to the parent type info
|
|
//
|
|
// Returns: nothing
|
|
//
|
|
// Modifies: adds each new node to the MEMLIST referred to by pNode
|
|
//
|
|
// History: 5-02-95 stevebl Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void NODE_MANAGER::AddMembers(MEMLIST * pNode, TYPEATTR * ptattr, ITypeInfo * pti)
|
|
{
|
|
HRESULT hr;
|
|
named_node * pNew;
|
|
unsigned i = ptattr->cFuncs;
|
|
while (i--)
|
|
{
|
|
FUNCDESC *pfdesc;
|
|
hr = pti->GetFuncDesc(i, &pfdesc);
|
|
pNew = GetNodeFromFUNCDESC(*pfdesc, pti);
|
|
pNode->AddFirstMember(pNew);
|
|
pti->ReleaseFuncDesc(pfdesc);
|
|
}
|
|
i = ptattr->cVars;
|
|
while (i--)
|
|
{
|
|
VARDESC * pvdesc;
|
|
hr = pti->GetVarDesc(i, &pvdesc);
|
|
pNew = GetNodeFromVARDESC(*pvdesc, pti);
|
|
pNode->AddFirstMember(pNew);
|
|
pti->ReleaseVarDesc(pvdesc);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: NODE_MANAGER::GetNodeFromVARDESC
|
|
//
|
|
// Synopsis: gets a type graph node from a VARDESC
|
|
//
|
|
// Arguments: [vdesc] - VARDESC describing the variable
|
|
// [pti] - type info containing the VARDESC
|
|
//
|
|
// Returns: type graph node describing the varible
|
|
//
|
|
// History: 5-02-95 stevebl Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
named_node * NODE_MANAGER::GetNodeFromVARDESC(VARDESC vdesc, ITypeInfo * pti)
|
|
{
|
|
BSTR bstrName;
|
|
unsigned cNames;
|
|
|
|
pti->GetNames(vdesc.memid, &bstrName, 1, &cNames);
|
|
char * szName = TranscribeO2A( bstrName );
|
|
LateBound_SysFreeString(bstrName);
|
|
|
|
named_node *pNode;
|
|
if (vdesc.varkind == VAR_CONST)
|
|
{
|
|
expr_node * pExpr = GetValueOfConstant(vdesc.lpvarValue);
|
|
pNode = new node_label(szName, pExpr);
|
|
}
|
|
else
|
|
{
|
|
pNode = new node_field(szName);
|
|
}
|
|
pNode->SetBasicType(GetNodeFromTYPEDESC(vdesc.elemdescVar.tdesc, pti));
|
|
SetIDLATTRS(pNode, vdesc.elemdescVar.idldesc);
|
|
pNode->SetAttribute(new node_constant_attr(
|
|
new expr_constant(vdesc.wVarFlags), ATTR_VARDESCATTR));
|
|
if (vdesc.wVarFlags == VARFLAG_FREADONLY)
|
|
{
|
|
pNode->SetAttribute(new node_member_attr(MATTR_READONLY));
|
|
}
|
|
if (vdesc.wVarFlags == VARFLAG_FSOURCE)
|
|
{
|
|
pNode->SetAttribute(new node_member_attr(MATTR_SOURCE));
|
|
}
|
|
if (vdesc.wVarFlags == VARFLAG_FBINDABLE)
|
|
{
|
|
pNode->SetAttribute(new node_member_attr(MATTR_BINDABLE));
|
|
}
|
|
if (vdesc.wVarFlags == VARFLAG_FDISPLAYBIND)
|
|
{
|
|
pNode->SetAttribute(new node_member_attr(MATTR_DISPLAYBIND));
|
|
}
|
|
if (vdesc.wVarFlags == VARFLAG_FDEFAULTBIND)
|
|
{
|
|
pNode->SetAttribute(new node_member_attr(MATTR_DEFAULTBIND));
|
|
}
|
|
if (vdesc.wVarFlags == VARFLAG_FREQUESTEDIT)
|
|
{
|
|
pNode->SetAttribute(new node_member_attr(MATTR_REQUESTEDIT));
|
|
}
|
|
if (vdesc.wVarFlags == VARFLAG_FHIDDEN)
|
|
{
|
|
pNode->SetAttribute(ATTR_HIDDEN);
|
|
}
|
|
|
|
pNode->SetAttribute(new node_constant_attr(
|
|
new expr_constant(vdesc.memid), ATTR_ID ));
|
|
|
|
return pNode;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: NODE_MANAGER::GetNodeFromFUNCDESC
|
|
//
|
|
// Synopsis: gets a type graph node from a FUNCDESC
|
|
//
|
|
// Arguments: [fdesc] - FUNCDESC describing the function
|
|
// [pti] - type info containing the FUNCDESC
|
|
//
|
|
// Returns: type graph node describing the function
|
|
//
|
|
// History: 5-02-95 stevebl Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
named_node * NODE_MANAGER::GetNodeFromFUNCDESC(FUNCDESC fdesc, ITypeInfo *pti)
|
|
{
|
|
node_proc * pNode = new node_proc(ImportLevel, FALSE);
|
|
|
|
BSTR * rgbstrName = new BSTR [fdesc.cParams + 1];
|
|
|
|
unsigned cNames;
|
|
pti->GetNames(fdesc.memid, rgbstrName, fdesc.cParams + 1, &cNames);
|
|
char * szName = TranscribeO2A( rgbstrName[0] );
|
|
LateBound_SysFreeString( rgbstrName[0] );
|
|
pNode->SetSymName(szName);
|
|
|
|
if (fdesc.invkind == DISPATCH_PROPERTYGET
|
|
|| fdesc.funckind == FUNC_DISPATCH
|
|
|| (fdesc.elemdescFunc.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) != 0)
|
|
{
|
|
/*
|
|
* Functions with the DISPATCH_PROPERTYGET attribute are special cases.
|
|
* Their return values in the type graph are always of type HRESULT.
|
|
* The last parameter of the function (after those listed in the fdesc)
|
|
* is a pointer to the return type listed in the fdesc and it has
|
|
* the OUT and RETVAL attributes.
|
|
*/
|
|
node_skl* pChild = new node_pointer(GetNodeFromTYPEDESC(fdesc.elemdescFunc.tdesc, pti));
|
|
node_param * pParam = new node_param();
|
|
pChild->GetModifiers().SetModifier( ATTR_TAGREF );
|
|
pParam->SetSymName("retval");
|
|
pParam->SetChild( pChild );
|
|
pParam->SetAttribute(ATTR_OUT);
|
|
pParam->SetAttribute(new node_member_attr(MATTR_RETVAL));
|
|
// add the [retval] parameter at the end of the parameter list
|
|
// (the parameter list is currently empty and the other parameters
|
|
// will be added in front of this one in reverse order so that's why
|
|
// we use AddFirstMember)
|
|
pNode->AddFirstMember(pParam);
|
|
node_skl * pReturn = new node_base_type(NODE_SHORT, ATTR_NONE);
|
|
((named_node *)pReturn)->SetSymName("HRESULT");
|
|
pNode->SetChild(pReturn);
|
|
}
|
|
else
|
|
{
|
|
node_skl* pChild = GetNodeFromTYPEDESC(fdesc.elemdescFunc.tdesc, pti);
|
|
pNode->SetChild( pChild );
|
|
NODE_T nk = pChild->NodeKind();
|
|
if (nk == NODE_POINTER || nk == NODE_DEF)
|
|
{
|
|
pChild->GetModifiers().SetModifier( ATTR_TAGREF );
|
|
}
|
|
}
|
|
unsigned cParams = fdesc.cParams;
|
|
unsigned cParamsOpt = fdesc.cParamsOpt;
|
|
while (cParams--)
|
|
{
|
|
node_param * pParam = new node_param();
|
|
if (cParams + 1 < cNames)
|
|
{
|
|
szName = TranscribeO2A( rgbstrName[ cParams + 1] );
|
|
pParam->SetSymName(szName);
|
|
LateBound_SysFreeString(rgbstrName[cParams + 1]);
|
|
}
|
|
else
|
|
pParam->SetSymName("noname");
|
|
|
|
pParam->SetChild(GetNodeFromTYPEDESC(fdesc.lprgelemdescParam[cParams].tdesc, pti));
|
|
SetIDLATTRS(pParam, fdesc.lprgelemdescParam[cParams].idldesc);
|
|
if (cParamsOpt)
|
|
{
|
|
cParamsOpt--;
|
|
pParam->SetAttribute(new node_member_attr(MATTR_OPTIONAL));
|
|
}
|
|
if (pParam && pParam->GetChild())
|
|
{
|
|
NODE_T nk = pParam->GetChild()->NodeKind();
|
|
if (nk == NODE_POINTER || nk == NODE_DEF)
|
|
{
|
|
pParam->GetChild()->GetModifiers().SetModifier( ATTR_TAGREF );
|
|
}
|
|
}
|
|
pNode->AddFirstMember(pParam);
|
|
}
|
|
|
|
delete[]rgbstrName;
|
|
|
|
pNode->SetAttribute(new node_constant_attr(
|
|
new expr_constant(fdesc.wFuncFlags), ATTR_FUNCDESCATTR));
|
|
if (fdesc.wFuncFlags == FUNCFLAG_FRESTRICTED)
|
|
{
|
|
pNode->SetAttribute(new node_member_attr(MATTR_RESTRICTED));
|
|
}
|
|
if (fdesc.wFuncFlags == FUNCFLAG_FSOURCE)
|
|
{
|
|
pNode->SetAttribute(new node_member_attr(MATTR_SOURCE));
|
|
}
|
|
if (fdesc.wFuncFlags == FUNCFLAG_FBINDABLE)
|
|
{
|
|
pNode->SetAttribute(new node_member_attr(MATTR_BINDABLE));
|
|
}
|
|
if (fdesc.wFuncFlags == FUNCFLAG_FDISPLAYBIND)
|
|
{
|
|
pNode->SetAttribute(new node_member_attr(MATTR_DISPLAYBIND));
|
|
}
|
|
if (fdesc.wFuncFlags == FUNCFLAG_FDEFAULTBIND)
|
|
{
|
|
pNode->SetAttribute(new node_member_attr(MATTR_DEFAULTBIND));
|
|
}
|
|
if (fdesc.wFuncFlags == FUNCFLAG_FREQUESTEDIT)
|
|
{
|
|
pNode->SetAttribute(new node_member_attr(MATTR_REQUESTEDIT));
|
|
}
|
|
if (fdesc.wFuncFlags == FUNCFLAG_FHIDDEN)
|
|
{
|
|
pNode->SetAttribute(ATTR_HIDDEN);
|
|
}
|
|
if (fdesc.invkind == DISPATCH_PROPERTYGET)
|
|
{
|
|
szName = pNode->GetSymName();
|
|
char * szNewName = new char[strlen(szName) + 5];
|
|
sprintf(szNewName , "get_%s", szName);
|
|
pNode->SetSymName(szNewName);
|
|
pNode->SetAttribute(new node_member_attr(MATTR_PROPGET));
|
|
}
|
|
else if (fdesc.invkind == DISPATCH_PROPERTYPUT)
|
|
{
|
|
szName = pNode->GetSymName();
|
|
char * szNewName = new char[strlen(szName) + 5];
|
|
sprintf(szNewName , "put_%s", szName);
|
|
pNode->SetSymName(szNewName);
|
|
pNode->SetAttribute(new node_member_attr(MATTR_PROPPUT));
|
|
}
|
|
else if (fdesc.invkind == DISPATCH_PROPERTYPUTREF)
|
|
{
|
|
szName = pNode->GetSymName();
|
|
char * szNewName = new char[strlen(szName) + 8];
|
|
sprintf(szNewName , "putref_%s", szName);
|
|
pNode->SetSymName(szNewName);
|
|
pNode->SetAttribute(new node_member_attr(MATTR_PROPPUTREF));
|
|
}
|
|
|
|
pNode->GetModifiers().SetModifier( ATTR_TAGREF );
|
|
pNode->SetAttribute(new node_constant_attr(
|
|
new expr_constant(fdesc.memid), ATTR_ID ));
|
|
|
|
return pNode;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: NODE_MANAGER::SetIDLATTRS
|
|
//
|
|
// Synopsis: Adds IDL attributes to a type graph node
|
|
//
|
|
// Arguments: [pNode] - pointer to the type graph node
|
|
// [idldesc] - IDLDESC containing the IDL attributes
|
|
//
|
|
// History: 5-02-95 stevebl Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void NODE_MANAGER::SetIDLATTRS(named_node * pNode, IDLDESC idldesc)
|
|
{
|
|
pNode->SetAttribute(new node_constant_attr(
|
|
new expr_constant(idldesc.wIDLFlags), ATTR_IDLDESCATTR));
|
|
if (idldesc.wIDLFlags & IDLFLAG_FIN)
|
|
{
|
|
pNode->SetAttribute(ATTR_IN);
|
|
}
|
|
if (idldesc.wIDLFlags & IDLFLAG_FOUT)
|
|
{
|
|
pNode->SetAttribute(ATTR_OUT);
|
|
}
|
|
if (idldesc.wIDLFlags & IDLFLAG_FLCID)
|
|
{
|
|
pNode->SetAttribute(ATTR_FLCID);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: NODE_MANAGER::GetValueOfConstant
|
|
//
|
|
// Synopsis: creates an expr_constant node from a VARIANT
|
|
//
|
|
// Arguments: [pVar] - pointer to the variant containing the constant
|
|
//
|
|
// Returns: expr_node describing the constant expression
|
|
//
|
|
// History: 5-02-95 stevebl Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
expr_node * NODE_MANAGER::GetValueOfConstant(VARIANT * pVar)
|
|
{
|
|
expr_node * pReturn;
|
|
switch(pVar->vt)
|
|
{
|
|
case VT_UI1:
|
|
pReturn = new expr_constant(pVar->bVal);
|
|
break;
|
|
case VT_BOOL:
|
|
case VT_I2:
|
|
pReturn = new expr_constant(pVar->iVal);
|
|
break;
|
|
case VT_I4:
|
|
pReturn = new expr_constant(pVar->lVal);
|
|
break;
|
|
case VT_R4:
|
|
pReturn = new expr_constant(pVar->fltVal);
|
|
break;
|
|
case VT_R8:
|
|
pReturn = new expr_constant(pVar->dblVal);
|
|
break;
|
|
case VT_CY:
|
|
case VT_DATE:
|
|
case VT_BSTR:
|
|
case VT_ERROR:
|
|
case VT_UNKNOWN:
|
|
case VT_VARIANT:
|
|
case VT_DISPATCH:
|
|
default:
|
|
// This case is currently illegal in every situation that I am
|
|
// aware of. However, just in case this ever changes, (and since
|
|
// it is possible to handle this situation even though it may be
|
|
// illeagal) I'll go ahead and allow it anyway. The alternative
|
|
// would be to choke on it and put out an error message.
|
|
|
|
// FUTURE - perhaps display a warning here
|
|
|
|
pReturn = new expr_constant(pVar->lVal);
|
|
break;
|
|
}
|
|
return pReturn;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CTypeLibraryList::AddTypeLibraryMembers
|
|
//
|
|
// Synopsis: Adds each of a type library's members to the global symbol
|
|
// table as a node_href. If another symbol with the same name
|
|
// already exists in the table, then no node will be added
|
|
// for that member.
|
|
//
|
|
// Arguments: [ptl] - type library pointer
|
|
// [szFileName] - name of the file containing the type library
|
|
//
|
|
// History: 5-02-95 stevebl Created
|
|
//
|
|
// Notes: Typeinfos added to the global symbol table in this manner are
|
|
// not parsed and expanded into their type graphs at this time;
|
|
// type info expansion occurs during the semantic pass.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CTypeLibraryList::AddTypeLibraryMembers(ITypeLib * ptl, char * szFileName)
|
|
{
|
|
unsigned int nMem = ptl->GetTypeInfoCount();
|
|
BSTR bstrName;
|
|
HRESULT hr;
|
|
ITypeInfo * pti;
|
|
char * sz;
|
|
node_file * pFile = new node_file(szFileName, 1);
|
|
|
|
while (nMem--)
|
|
{
|
|
hr = ptl->GetDocumentation(nMem, &bstrName, NULL, NULL, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
TypelibError(szFileName, hr);
|
|
}
|
|
|
|
sz = TranscribeO2A( bstrName );
|
|
LateBound_SysFreeString(bstrName);
|
|
|
|
NAME_T type;
|
|
TYPEKIND tkind;
|
|
hr = ptl->GetTypeInfoType(nMem, &tkind);
|
|
if (FAILED(hr))
|
|
{
|
|
TypelibError(szFileName, hr);
|
|
}
|
|
|
|
if (!pCommand->IsSwitchDefined(SWITCH_MKTYPLIB))
|
|
{
|
|
switch (tkind)
|
|
{
|
|
case TKIND_ENUM:
|
|
type = NAME_ENUM;
|
|
break;
|
|
case TKIND_UNION:
|
|
type = NAME_UNION;
|
|
break;
|
|
case TKIND_RECORD:
|
|
type = NAME_TAG;
|
|
break;
|
|
default:
|
|
type = NAME_DEF;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
type = NAME_DEF;
|
|
}
|
|
SymKey key(sz, type);
|
|
if (!pBaseSymTbl->SymSearch(key))
|
|
{
|
|
hr = ptl->GetTypeInfo(nMem, &pti);
|
|
if (FAILED(hr))
|
|
{
|
|
TypelibError(szFileName, hr);
|
|
}
|
|
pItfList->Add(pti, sz);
|
|
node_href * pref = new node_href(key, pBaseSymTbl, pti, pFile);
|
|
pref->SetSymName(sz);
|
|
pBaseSymTbl->SymInsert(key, NULL, pref);
|
|
}
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: AddQualifiedReferenceToType
|
|
//
|
|
// Synopsis: Verifies that a library contains a given type and returns
|
|
// a typegraph node pointer to the type.
|
|
//
|
|
// Arguments: [szLibrary] - name of the library (_NOT_ the TLB file)
|
|
// [szType] - name of the type to be referenced
|
|
//
|
|
// Returns: a node_href * to the referenced type.
|
|
// If the type isn't found to exist in the given library then
|
|
// this routine returns NULL.
|
|
//
|
|
// History: 12-20-95 stevebl Created
|
|
//
|
|
// Notes: These types are not added to the global symbol table.
|
|
// They are also not parsed and expanded into their complete
|
|
// type graphs at this time; type info expansion occurs
|
|
// during the semantic pass.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void * AddQualifiedReferenceToType(char * szLibrary, char * szType)
|
|
{
|
|
return gtllist.AddQualifiedReferenceToType(szLibrary, szType);
|
|
}
|
|
|
|
void * CTypeLibraryList::AddQualifiedReferenceToType(char * szLibrary, char * szType)
|
|
{
|
|
ITypeLib * pTL = FindLibrary(szLibrary);
|
|
if (NULL != pTL)
|
|
{
|
|
node_file * pFile = new node_file(szLibrary, 1);
|
|
WCHAR * wsz = TranscribeA2O( szType );
|
|
ITypeInfo * ptiFound;
|
|
SYSKIND sk = ( SYSKIND ) ( pCommand->Is64BitEnv() ? SYS_WIN64 : SYS_WIN32 );
|
|
ULONG lHashVal = LateBound_LHashValOfNameSys(sk, NULL, wsz);
|
|
HRESULT hr;
|
|
MEMBERID memid;
|
|
unsigned short c;
|
|
c = 1;
|
|
hr = pTL->FindName(wsz, lHashVal, &ptiFound, &memid, &c);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (c)
|
|
{
|
|
if (-1 == memid)
|
|
{
|
|
// found a matching name
|
|
NAME_T type;
|
|
TYPEATTR * ptattr;
|
|
hr = ptiFound->GetTypeAttr(&ptattr);
|
|
if (FAILED(hr))
|
|
{
|
|
TypeinfoError(hr);
|
|
}
|
|
|
|
if (!pCommand->IsSwitchDefined(SWITCH_MKTYPLIB))
|
|
{
|
|
switch (ptattr->typekind)
|
|
{
|
|
case TKIND_ENUM:
|
|
type = NAME_ENUM;
|
|
break;
|
|
case TKIND_UNION:
|
|
type = NAME_UNION;
|
|
break;
|
|
case TKIND_RECORD:
|
|
type = NAME_TAG;
|
|
break;
|
|
default:
|
|
type = NAME_DEF;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
type = NAME_DEF;
|
|
}
|
|
ptiFound->ReleaseTypeAttr(ptattr);
|
|
pItfList->Add(ptiFound, szType);
|
|
SymKey key(szType, type);
|
|
node_href * pref = new node_href(key, pBaseSymTbl, ptiFound, pFile);
|
|
return pref;
|
|
}
|
|
// found a parameter name or some other non-global name
|
|
ptiFound->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|