From 8608467b842087949ab8f9c052d3a60bdc12ef45 Mon Sep 17 00:00:00 2001 From: Mikhail Tyukin Date: Mon, 4 Aug 2025 11:59:51 -0400 Subject: [PATCH] [WIDL][WPP] Sync to wine-10.0 Update widl/wpp tools to Wine-10.0. This is needed for compiling WinRT idl files, and for various winesyncs. --- dll/win32/actxprxy/precomp.h | 1 - dll/win32/rpcrt4/ndr_typelib.c | 25 + media/doc/WINESYNC.txt | 4 +- sdk/cmake/widl-support.cmake | 33 +- sdk/include/host/pecoff.h | 120 ++ sdk/include/psdk/mshtml.idl | 3 - sdk/include/psdk/objidl.idl | 1192 +---------------- sdk/include/psdk/objidlbase.idl | 1253 ++++++++++++++++++ sdk/include/psdk/wtypes.idl | 83 +- sdk/lib/uuid/CMakeLists.txt | 1 + sdk/tools/tools.h | 969 ++++++++++++++ sdk/tools/widl/CMakeLists.txt | 9 +- sdk/tools/widl/attribute.c | 540 ++++++++ sdk/tools/widl/client.c | 84 +- sdk/tools/widl/expr.c | 140 +- sdk/tools/widl/expr.h | 2 +- sdk/tools/widl/hash.c | 193 ++- sdk/tools/widl/hash.h | 13 +- sdk/tools/widl/header.c | 992 +++++++++----- sdk/tools/widl/header.h | 25 +- sdk/tools/widl/parser.h | 26 +- sdk/tools/widl/parser.l | 1003 +++++++------- sdk/tools/widl/parser.y | 2166 +++++++++++++++---------------- sdk/tools/widl/proxy.c | 123 +- sdk/tools/widl/register.c | 124 +- sdk/tools/widl/server.c | 61 +- sdk/tools/widl/typegen.c | 1546 ++++++++++++---------- sdk/tools/widl/typegen.h | 1 - sdk/tools/widl/typelib.c | 200 +-- sdk/tools/widl/typelib_struct.h | 560 ++++---- sdk/tools/widl/typetree.c | 1120 +++++++++++++--- sdk/tools/widl/typetree.h | 205 ++- sdk/tools/widl/utils.c | 266 +--- sdk/tools/widl/utils.h | 46 +- sdk/tools/widl/widl.c | 611 ++++----- sdk/tools/widl/widl.h | 64 +- sdk/tools/widl/widltypes.h | 213 ++- sdk/tools/widl/write_msft.c | 430 +++--- sdk/tools/widl/write_sltg.c | 443 +++---- sdk/tools/wpp/CMakeLists.txt | 8 +- sdk/tools/wpp/ppl.l | 328 ++--- sdk/tools/wpp/ppy.y | 151 +-- sdk/tools/wpp/preproc.c | 763 ----------- sdk/tools/wpp/wpp.c | 595 +++++++-- sdk/tools/wpp/wpp_private.h | 99 +- 45 files changed, 9705 insertions(+), 7129 deletions(-) create mode 100644 sdk/include/psdk/objidlbase.idl create mode 100644 sdk/tools/tools.h create mode 100644 sdk/tools/widl/attribute.c delete mode 100644 sdk/tools/wpp/preproc.c diff --git a/dll/win32/actxprxy/precomp.h b/dll/win32/actxprxy/precomp.h index 81d80f00f3b..8135d6df2f2 100644 --- a/dll/win32/actxprxy/precomp.h +++ b/dll/win32/actxprxy/precomp.h @@ -8,7 +8,6 @@ #define DECLSPEC_HIDDEN #include -#include #include #include #include diff --git a/dll/win32/rpcrt4/ndr_typelib.c b/dll/win32/rpcrt4/ndr_typelib.c index 5aa98bb9c7b..ba4e3398976 100644 --- a/dll/win32/rpcrt4/ndr_typelib.c +++ b/dll/win32/rpcrt4/ndr_typelib.c @@ -790,6 +790,9 @@ static size_t write_type_tfs(ITypeInfo *typeinfo, unsigned char *str, ITypeInfo *refinfo; TYPEATTR *attr; size_t off; +#ifdef __REACTOS__ + GUID guid; +#endif TRACE("vt %d%s\n", desc->vt, toplevel ? " (toplevel)" : ""); @@ -811,11 +814,25 @@ static size_t write_type_tfs(ITypeInfo *typeinfo, unsigned char *str, case TKIND_RECORD: off = write_struct_tfs(refinfo, str, len, attr); break; +#ifdef __REACTOS__ + case TKIND_INTERFACE: + case TKIND_DISPATCH: + /* These are treated as if they were interface pointers. */ + off = *len; + write_ip_tfs(str, len, &attr->guid); + break; + case TKIND_COCLASS: + off = *len; + get_default_iface(refinfo, attr->cImplTypes, &guid); + write_ip_tfs(str, len, &guid); + break; +#else case TKIND_INTERFACE: case TKIND_DISPATCH: case TKIND_COCLASS: assert(0); break; +#endif case TKIND_ALIAS: off = write_type_tfs(refinfo, str, len, &attr->tdescAlias, toplevel, onstack); break; @@ -1001,6 +1018,14 @@ static HRESULT get_param_info(ITypeInfo *typeinfo, TYPEDESC *tdesc, int is_in, hr = get_param_info(refinfo, &attr->tdescAlias, is_in, is_out, server_size, flags, basetype, tfs_tdesc); break; +#ifdef __REACTOS__ + case TKIND_INTERFACE: + case TKIND_DISPATCH: + case TKIND_COCLASS: + /* These are treated as if they were interface pointers. */ + *flags |= MustFree; + break; +#endif default: FIXME("unhandled kind %#x\n", attr->typekind); hr = E_NOTIMPL; diff --git a/media/doc/WINESYNC.txt b/media/doc/WINESYNC.txt index 6e55ec1d1e6..0eccb10e888 100644 --- a/media/doc/WINESYNC.txt +++ b/media/doc/WINESYNC.txt @@ -18,8 +18,8 @@ The following build tools are shared with Wine. base/ctf/msctf # Forked at Wine-10.12 sdk/tools/unicode # Synced to WineStaging-4.18 -sdk/tools/widl # Synced to WineStaging-4.0 -sdk/tools/wpp # Synced to WineStaging-2.9 +sdk/tools/widl # Synced to Wine-10.0 +sdk/tools/wpp # Synced to Wine-10.0 (Module was moved into wrc tool) The following libraries are shared with Wine. diff --git a/sdk/cmake/widl-support.cmake b/sdk/cmake/widl-support.cmake index 73717b44561..b0117147e6e 100644 --- a/sdk/cmake/widl-support.cmake +++ b/sdk/cmake/widl-support.cmake @@ -1,16 +1,19 @@ #idl files support if(ARCH STREQUAL "i386") - set(IDL_FLAGS -m32 --win32 -b i386-x-y) + set(IDL_FLAGS -m32 --win32 -b i386-x-y -nostdinc) elseif(ARCH STREQUAL "amd64") - set(IDL_FLAGS -m64 --win64 -b amd64-x-y) + set(IDL_FLAGS -m64 --win64 -b amd64-x-y -nostdinc) else() - set(IDL_FLAGS -b ${ARCH}-x-y) + set(IDL_FLAGS -b ${ARCH}-x-y -nostdinc) endif() function(add_typelib) get_includes(INCLUDES) get_defines(DEFINES) + get_includes(LIBS) + string(REPLACE "-I" "-L" LIBS "${LIBS}") + foreach(FILE ${ARGN}) if(${FILE} STREQUAL "std_ole_v1.idl") set(IDL_FLAGS ${IDL_FLAGS} --oldtlb) @@ -18,7 +21,7 @@ function(add_typelib) get_filename_component(NAME ${FILE} NAME_WE) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.tlb - COMMAND native-widl ${INCLUDES} ${DEFINES} ${IDL_FLAGS} -t -o ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.tlb ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} + COMMAND native-widl ${INCLUDES} ${LIBS} ${DEFINES} ${IDL_FLAGS} -t -o ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.tlb ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} native-widl) list(APPEND OBJECTS ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.tlb) endforeach() @@ -28,11 +31,11 @@ function(add_idl_headers TARGET) get_includes(INCLUDES) get_defines(DEFINES) foreach(FILE ${ARGN}) - get_filename_component(NAME ${FILE} NAME_WE) + get_filename_component(NAME ${FILE} NAME_WLE) set(HEADER ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.h) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.h - COMMAND native-widl ${INCLUDES} ${DEFINES} ${IDL_FLAGS} -h -o ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.h ${FILE} + COMMAND native-widl ${INCLUDES} ${DEFINES} ${IDL_FLAGS} -Oicf -h -o ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.h ${FILE} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} native-widl WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) list(APPEND HEADERS ${HEADER}) @@ -45,7 +48,7 @@ function(add_rpcproxy_files) get_defines(DEFINES) foreach(FILE ${ARGN}) - get_filename_component(NAME ${FILE} NAME_WE) + get_filename_component(NAME ${FILE} NAME_WLE) # Most proxy idl's have names like _.idl # We use this to create a dependency from the proxy to the original idl string(REPLACE "_" ";" SPLIT_FILE ${FILE}) @@ -62,8 +65,8 @@ function(add_rpcproxy_files) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_p.c ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_p.h # We generate the two files in two passes because WIDL accepts only one custom file name as output - COMMAND native-widl ${INCLUDES} ${DEFINES} ${IDL_FLAGS} -p -o ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_p.c -H ${NAME}_p.h ${FILE} - COMMAND native-widl ${INCLUDES} ${DEFINES} ${IDL_FLAGS} -h -o ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_p.h ${FILE} + COMMAND native-widl ${INCLUDES} ${DEFINES} ${IDL_FLAGS} -Oicf -p -o ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_p.c -H ${NAME}_p.h ${FILE} + COMMAND native-widl ${INCLUDES} ${DEFINES} ${IDL_FLAGS} -Oicf -h -o ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_p.h ${FILE} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} ${EXTRA_DEP} native-widl WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) endforeach() @@ -71,7 +74,7 @@ function(add_rpcproxy_files) # Extra pass to generate dlldata add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/proxy.dlldata.c - COMMAND native-widl ${INCLUDES} ${DEFINES} ${IDL_FLAGS} --dlldata-only -o ${CMAKE_CURRENT_BINARY_DIR}/proxy.dlldata.c ${IDLS} + COMMAND native-widl ${INCLUDES} ${DEFINES} ${IDL_FLAGS} -Oicf --dlldata-only -o ${CMAKE_CURRENT_BINARY_DIR}/proxy.dlldata.c ${IDLS} DEPENDS ${IDL_DEPS} native-widl WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) endfunction() @@ -91,13 +94,13 @@ function(add_rpc_files __type) message(FATAL_ERROR "Please pass either server or client as argument to add_rpc_files") endif() foreach(FILE ${ARGN}) - get_filename_component(__name ${FILE} NAME_WE) + get_filename_component(__name ${FILE} NAME_WLE) set(__name ${__name}${__suffix}) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${__name}.c ${CMAKE_CURRENT_BINARY_DIR}/${__name}.h # We generate the two files in two passes because WIDL accepts only one custom file name as output - COMMAND native-widl ${INCLUDES} ${DEFINES} ${IDL_FLAGS} ${__additional_flags} ${__server_client} -o ${CMAKE_CURRENT_BINARY_DIR}/${__name}.c -H ${__name}.h ${FILE} - COMMAND native-widl ${INCLUDES} ${DEFINES} ${IDL_FLAGS} ${__additional_flags} -h -o ${CMAKE_CURRENT_BINARY_DIR}/${__name}.h ${FILE} + COMMAND native-widl ${INCLUDES} ${DEFINES} ${IDL_FLAGS} -Oicf ${__additional_flags} ${__server_client} -o ${CMAKE_CURRENT_BINARY_DIR}/${__name}.c -H ${__name}.h ${FILE} + COMMAND native-widl ${INCLUDES} ${DEFINES} ${IDL_FLAGS} -Oicf ${__additional_flags} -h -o ${CMAKE_CURRENT_BINARY_DIR}/${__name}.h ${FILE} DEPENDS ${FILE} native-widl WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) endforeach() @@ -149,7 +152,7 @@ function(generate_idl_iids) get_filename_component(NAME ${IDL_FILE} NAME_WE) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_i.c - COMMAND native-widl ${INCLUDES} ${DEFINES} ${IDL_FLAGS} -u -o ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_i.c ${IDL_FILE} + COMMAND native-widl ${INCLUDES} ${DEFINES} ${IDL_FLAGS} -Os -u -o ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_i.c ${IDL_FILE} DEPENDS ${IDL_FILE} native-widl WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) endforeach() @@ -172,7 +175,7 @@ function(add_idl_reg_script IDL_FILE) get_filename_component(NAME ${IDL_FILE} NAME_WE) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_r.res - COMMAND native-widl ${INCLUDES} ${DEFINES} ${IDL_FLAGS} -r -o ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_r.res ${IDL_FILE} + COMMAND native-widl ${INCLUDES} ${DEFINES} ${IDL_FLAGS} -Oicf -r -o ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_r.res ${IDL_FILE} DEPENDS ${IDL_FILE} native-widl WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${NAME}_r.res PROPERTIES diff --git a/sdk/include/host/pecoff.h b/sdk/include/host/pecoff.h index f96982e910a..070cce41ab7 100644 --- a/sdk/include/host/pecoff.h +++ b/sdk/include/host/pecoff.h @@ -61,6 +61,68 @@ #define IMAGE_REL_I386_REL16 0x0002 #define IMAGE_REL_I386_DIR32 0x0006 +/* Helper macro to enable gcc's extension. */ +#ifndef __GNU_EXTENSION + #ifdef __GNUC__ + #define __GNU_EXTENSION __extension__ + #else + #define __GNU_EXTENSION + #endif +#endif /* __GNU_EXTENSION */ + + +#ifndef DUMMYUNIONNAME + #if defined(NONAMELESSUNION)// || !defined(_MSC_EXTENSIONS) + #define _ANONYMOUS_UNION + #define _UNION_NAME(x) x + #define DUMMYUNIONNAME u + #define DUMMYUNIONNAME1 u1 + #define DUMMYUNIONNAME2 u2 + #define DUMMYUNIONNAME3 u3 + #define DUMMYUNIONNAME4 u4 + #define DUMMYUNIONNAME5 u5 + #define DUMMYUNIONNAME6 u6 + #define DUMMYUNIONNAME7 u7 + #define DUMMYUNIONNAME8 u8 + #define DUMMYUNIONNAME9 u9 + #else + #define _ANONYMOUS_UNION __GNU_EXTENSION + #define _UNION_NAME(x) + #define DUMMYUNIONNAME + #define DUMMYUNIONNAME1 + #define DUMMYUNIONNAME2 + #define DUMMYUNIONNAME3 + #define DUMMYUNIONNAME4 + #define DUMMYUNIONNAME5 + #define DUMMYUNIONNAME6 + #define DUMMYUNIONNAME7 + #define DUMMYUNIONNAME8 + #define DUMMYUNIONNAME9 + #endif /* NONAMELESSUNION */ +#endif /* !DUMMYUNIONNAME */ + +#ifndef DUMMYSTRUCTNAME + #if defined(NONAMELESSUNION)// || !defined(_MSC_EXTENSIONS) + #define _ANONYMOUS_STRUCT + #define _STRUCT_NAME(x) x + #define DUMMYSTRUCTNAME s + #define DUMMYSTRUCTNAME1 s1 + #define DUMMYSTRUCTNAME2 s2 + #define DUMMYSTRUCTNAME3 s3 + #define DUMMYSTRUCTNAME4 s4 + #define DUMMYSTRUCTNAME5 s5 + #else + #define _ANONYMOUS_STRUCT __GNU_EXTENSION + #define _STRUCT_NAME(x) + #define DUMMYSTRUCTNAME + #define DUMMYSTRUCTNAME1 + #define DUMMYSTRUCTNAME2 + #define DUMMYSTRUCTNAME3 + #define DUMMYSTRUCTNAME4 + #define DUMMYSTRUCTNAME5 + #endif /* NONAMELESSUNION */ +#endif /* DUMMYSTRUCTNAME */ + #pragma pack(push,2) typedef struct _IMAGE_DOS_HEADER { WORD e_magic; @@ -102,6 +164,22 @@ typedef struct _IMAGE_DATA_DIRECTORY { DWORD Size; } IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY; +#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 +#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 +#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 +#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 +#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 +#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 +#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 +#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 +#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 +#define IMAGE_DIRECTORY_ENTRY_TLS 9 +#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 +#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 +#define IMAGE_DIRECTORY_ENTRY_IAT 12 +#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 +#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 + typedef struct _IMAGE_OPTIONAL_HEADER32 { WORD Magic; BYTE MajorLinkerVersion; @@ -223,6 +301,48 @@ typedef struct _IMAGE_BASE_RELOCATION { } IMAGE_BASE_RELOCATION,*PIMAGE_BASE_RELOCATION; #pragma pack(pop) +typedef struct _IMAGE_RESOURCE_DIRECTORY { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + WORD NumberOfNamedEntries; + WORD NumberOfIdEntries; +} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY; + +#define IMAGE_RESOURCE_NAME_IS_STRING 0x80000000 +#define IMAGE_RESOURCE_DATA_IS_DIRECTORY 0x80000000 + +typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { + _ANONYMOUS_UNION union { + _ANONYMOUS_STRUCT struct { + DWORD NameOffset:31; + DWORD NameIsString:1; + } DUMMYSTRUCTNAME; + DWORD Name; + WORD Id; + } DUMMYUNIONNAME; + _ANONYMOUS_UNION union { + DWORD OffsetToData; + _ANONYMOUS_STRUCT struct { + DWORD OffsetToDirectory:31; + DWORD DataIsDirectory:1; + } DUMMYSTRUCTNAME2; + } DUMMYUNIONNAME2; +} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY; + +typedef struct _IMAGE_RESOURCE_DIRECTORY_STRING { + USHORT Length; + CHAR NameString[ANYSIZE_ARRAY]; +} IMAGE_RESOURCE_DIRECTORY_STRING, *PIMAGE_RESOURCE_DIRECTORY_STRING; + +typedef struct _IMAGE_RESOURCE_DATA_ENTRY { + ULONG OffsetToData; + ULONG Size; + ULONG CodePage; + ULONG Reserved; +} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY; + #ifndef UNALIGNED #define UNALIGNED #endif diff --git a/sdk/include/psdk/mshtml.idl b/sdk/include/psdk/mshtml.idl index 05f79ef4fa6..c6c092c6ac2 100644 --- a/sdk/include/psdk/mshtml.idl +++ b/sdk/include/psdk/mshtml.idl @@ -9284,9 +9284,6 @@ properties: methods: WINE_HTMLDATAELEMENT_DISPINTERFACE_DECL; - [propget, id(DISPID_IHTMLDOMCONSTRUCTOR_CONSTRUCTOR), hidden] - IDispatch* constructor(); - [propput, id(DISPID_IHTMLAREAELEMENT_SHAPE)] void shape(BSTR v); diff --git a/sdk/include/psdk/objidl.idl b/sdk/include/psdk/objidl.idl index 8c9d26f6667..cd11729b292 100644 --- a/sdk/include/psdk/objidl.idl +++ b/sdk/include/psdk/objidl.idl @@ -18,166 +18,18 @@ #ifndef DO_NO_IMPORTS import "unknwn.idl"; +#define DO_NO_IMPORTS +#define OBJIDL_UNDEF_DO_NO_IMPORTS +#endif + +#include "objidlbase.idl" +#ifdef OBJIDL_UNDEF_DO_NO_IMPORTS +#undef DO_NO_IMPORTS #endif -interface IStream; -interface IEnumString; interface IRunningObjectTable; interface IMoniker; interface IAdviseSink; -interface IAsyncManager; -interface ISynchronize; - -typedef struct _COSERVERINFO { - DWORD dwReserved1; - LPWSTR pwszName; - COAUTHINFO *pAuthInfo; - DWORD dwReserved2; -} COSERVERINFO; - -/******************** Fundamentals ********************/ - -[ - local, - object, - uuid(00000003-0000-0000-C000-000000000046) -] -interface IMarshal : IUnknown -{ - typedef [unique] IMarshal *LPMARSHAL; - - HRESULT GetUnmarshalClass( - [in] REFIID riid, - [in, unique] void *pv, - [in] DWORD dwDestContext, - [in, unique] void *pvDestContext, - [in] DWORD mshlflags, - [out] CLSID *pCid); - - HRESULT GetMarshalSizeMax( - [in] REFIID riid, - [in, unique] void *pv, - [in] DWORD dwDestContext, - [in, unique] void *pvDestContext, - [in] DWORD mshlflags, - [out] DWORD *pSize); - - HRESULT MarshalInterface( - [in, unique] IStream *pStm, - [in] REFIID riid, - [in, unique] void *pv, - [in] DWORD dwDestContext, - [in, unique] void *pvDestContext, - [in] DWORD mshlflags); - - HRESULT UnmarshalInterface( - [in, unique] IStream *pStm, - [in] REFIID riid, - [out] void **ppv); - - HRESULT ReleaseMarshalData( - [in, unique] IStream *pStm); - - HRESULT DisconnectObject( - [in] DWORD dwReserved); -} - -[ - local, - object, - uuid(000001cf-0000-0000-C000-000000000046) -] -interface IMarshal2 : IMarshal -{ - typedef [unique] IMarshal2 *LPMARSHAL2; -} - -[ - local, - object, - uuid(00000018-0000-0000-C000-000000000046) -] -interface IStdMarshalInfo : IUnknown -{ - typedef [unique] IStdMarshalInfo *LPSTDMARSHALINFO; - - HRESULT GetClassForHandler( - [in] DWORD dwDestContext, - [in, unique] void *pvDestContext, - [out] CLSID *pClsid); -} - -[ - local, - object, - uuid(00000019-0000-0000-C000-000000000046) -] -interface IExternalConnection : IUnknown -{ - typedef [unique] IExternalConnection *LPEXTERNALCONNECTION; - - typedef enum tagEXTCONN { - EXTCONN_STRONG = 0x0001, - EXTCONN_WEAK = 0x0002, - EXTCONN_CALLABLE = 0x0004 - } EXTCONN; - - DWORD AddConnection( - [in] DWORD extconn, - [in] DWORD reserved); - - DWORD ReleaseConnection( - [in] DWORD extconn, - [in] DWORD reserved, - [in] BOOL fLastReleaseCloses); -} - -[ - local, - object, - uuid(00000020-0000-0000-C000-000000000046) -] -interface IMultiQI : IUnknown -{ - typedef [unique] IMultiQI *LPMULTIQI; - - typedef struct tagMULTI_QI { - const IID *pIID; - IUnknown *pItf; - HRESULT hr; - } MULTI_QI; - - HRESULT QueryMultipleInterfaces( - [in] ULONG cMQIs, - [in, out] MULTI_QI *pMQIs); -} - -[ - local, - object, - uuid(00000002-0000-0000-C000-000000000046) -] -interface IMalloc : IUnknown -{ - typedef [unique] IMalloc *LPMALLOC; - - LPVOID Alloc( - [in] SIZE_T cb); - - LPVOID Realloc( - [in] LPVOID pv, - [in] SIZE_T cb); - - void Free( - [in] LPVOID pv); - - SIZE_T GetSize( - [in] LPVOID pv); - - int DidAlloc(LPVOID pv); - - void HeapMinimize(); -} [ local, @@ -233,87 +85,6 @@ interface IMallocSpy : IUnknown void PostHeapMinimize(); } -[ - local, - object, - uuid(00000021-0000-0000-C000-000000000046) -] -interface IInternalUnknown : IUnknown -{ - HRESULT QueryInternalInterface( - [in] REFIID riid, - [out] void **ppv); -} - -[ - object, - uuid(00000100-0000-0000-C000-000000000046), - pointer_default(unique) -] -interface IEnumUnknown : IUnknown -{ - typedef [unique] IEnumUnknown *LPENUMUNKNOWN; - - [local] - HRESULT Next( - [in] ULONG celt, - [out] IUnknown **rgelt, - [out] ULONG *pceltFetched); - - [call_as(Next)] - HRESULT RemoteNext( - [in] ULONG celt, - [out, size_is(celt), length_is(*pceltFetched)] - IUnknown **rgelt, - [out] ULONG *pceltFetched); - - HRESULT Skip( - [in] ULONG celt); - - HRESULT Reset(); - - HRESULT Clone( - [out] IEnumUnknown **ppenum); -} - -[ - object, - uuid(00000022-0000-0000-C000-000000000046), - version(1.0), - pointer_default(unique) -] -interface ISurrogate : IUnknown -{ - typedef [unique] ISurrogate *LPSURROGATE; - - HRESULT LoadDllServer( - [in] REFCLSID Clsid); - HRESULT FreeSurrogate(); -} - -[ - local, - object, - uuid(00000146-0000-0000-C000-000000000046) -] -interface IGlobalInterfaceTable : IUnknown -{ - typedef [unique] IGlobalInterfaceTable *LPGLOBALINTERFACETABLE; - - HRESULT RegisterInterfaceInGlobal( - [in] IUnknown *pUnk, - [in] REFIID riid, - [out] DWORD *pdwCookie); - - HRESULT RevokeInterfaceFromGlobal( - [in] DWORD dwCookie); - - HRESULT GetInterfaceFromGlobal( - [in] DWORD dwCookie, - [in] REFIID riid, - [out, iid_is(riid)] void **ppv); -} - /******************** Monikers ********************/ [ @@ -559,7 +330,10 @@ interface IMoniker : IPersistStream MKSYS_ITEMMONIKER = 4, MKSYS_POINTERMONIKER = 5, /* MKSYS_URLMONIKER = 6, */ /* defined in urlmon.idl */ - MKSYS_CLASSMONIKER = 7 + MKSYS_CLASSMONIKER = 7, + MKSYS_OBJREFMONIKER = 8, + MKSYS_SESSIONMONIKER = 9, + MKSYS_LUAMONIKER = 10 } MKSYS; typedef [v1_enum] enum tagMKREDUCE { @@ -668,38 +442,6 @@ interface IROTData : IUnknown [out] ULONG *pcbData); } -[ - object, - uuid(00000101-0000-0000-C000-000000000046), - pointer_default(unique) -] -interface IEnumString : IUnknown -{ - typedef [unique] IEnumString *LPENUMSTRING; - - [local] - HRESULT Next( - [in] ULONG celt, - [out, size_is(celt), length_is(*pceltFetched)] - LPOLESTR *rgelt, - [out] ULONG *pceltFetched); - - [call_as(Next)] - HRESULT RemoteNext( - [in] ULONG celt, - [out, size_is(celt), length_is(*pceltFetched)] - LPOLESTR *rgelt, - [out] ULONG *pceltFetched); - - HRESULT Skip( - [in] ULONG celt); - - HRESULT Reset(); - - HRESULT Clone( - [out] IEnumString **ppenum); -} - [ object, uuid(00000140-0000-0000-C000-000000000046) @@ -714,143 +456,6 @@ interface IClassActivator : IUnknown [out, iid_is(riid)] void **ppv); } -/******************** Storage ********************/ - -[ - object, - uuid(0c733a30-2a1c-11ce-ade5-00aa0044773d), - pointer_default(unique) -] -interface ISequentialStream : IUnknown -{ - [local] - HRESULT Read( - [out, size_is(cb), length_is(*pcbRead)] - void *pv, - [in] ULONG cb, - [out] ULONG *pcbRead); - - [call_as(Read)] - HRESULT RemoteRead( - [out, size_is(cb), length_is(*pcbRead)] - byte *pv, - [in] ULONG cb, - [out] ULONG *pcbRead); - - [local] - HRESULT Write( - [in, size_is(cb)] const void *pv, - [in] ULONG cb, - [out] ULONG *pcbWritten); - - [call_as(Write)] - HRESULT RemoteWrite( - [in, size_is(cb)] const byte *pv, - [in] ULONG cb, - [out] ULONG *pcbWritten); -} - -[ - object, - uuid(0000000c-0000-0000-C000-000000000046), - pointer_default(unique) -] -interface IStream : ISequentialStream -{ - typedef [unique] IStream *LPSTREAM; - - typedef struct tagSTATSTG { - LPOLESTR pwcsName; - DWORD type; - ULARGE_INTEGER cbSize; - FILETIME mtime; - FILETIME ctime; - FILETIME atime; - DWORD grfMode; - DWORD grfLocksSupported; - CLSID clsid; - DWORD grfStateBits; - DWORD reserved; - } STATSTG; - - typedef enum tagSTGTY { - STGTY_STORAGE = 1, - STGTY_STREAM = 2, - STGTY_LOCKBYTES = 3, - STGTY_PROPERTY = 4 - } STGTY; - - typedef enum tagSTREAM_SEEK { - STREAM_SEEK_SET = 0, - STREAM_SEEK_CUR = 1, - STREAM_SEEK_END = 2 - } STREAM_SEEK; - - /* these are defined in Linux's fcntl.h, - * undefine them to avoid conflicts */ - cpp_quote("#undef LOCK_MAND") - cpp_quote("#undef LOCK_READ") - cpp_quote("#undef LOCK_WRITE") - cpp_quote("#undef LOCK_RW") - - typedef enum tagLOCKTYPE { - LOCK_WRITE = 1, - LOCK_EXCLUSIVE = 2, - LOCK_ONLYONCE = 4 - } LOCKTYPE; - - [local] - HRESULT Seek( - [in] LARGE_INTEGER dlibMove, - [in] DWORD dwOrigin, - [out] ULARGE_INTEGER *plibNewPosition); - - [call_as(Seek)] - HRESULT RemoteSeek( - [in] LARGE_INTEGER dlibMove, - [in] DWORD dwOrigin, - [out] ULARGE_INTEGER *plibNewPosition); - - HRESULT SetSize( - [in] ULARGE_INTEGER libNewSize); - - [local] - HRESULT CopyTo( - [in, unique] IStream *pstm, - [in] ULARGE_INTEGER cb, - [out] ULARGE_INTEGER *pcbRead, - [out] ULARGE_INTEGER *pcbWritten); - - [call_as(CopyTo)] - HRESULT RemoteCopyTo( - [in, unique] IStream *pstm, - [in] ULARGE_INTEGER cb, - [out] ULARGE_INTEGER *pcbRead, - [out] ULARGE_INTEGER *pcbWritten); - - HRESULT Commit( - [in] DWORD grfCommitFlags); - - HRESULT Revert(); - - HRESULT LockRegion( - [in] ULARGE_INTEGER libOffset, - [in] ULARGE_INTEGER cb, - [in] DWORD dwLockType); - - HRESULT UnlockRegion( - [in] ULARGE_INTEGER libOffset, - [in] ULARGE_INTEGER cb, - [in] DWORD dwLockType); - - HRESULT Stat( - [out] STATSTG *pstatstg, - [in] DWORD grfStatFlag); - - HRESULT Clone( - [out] IStream **ppstm); -} - [ object, uuid(0000000d-0000-0000-C000-000000000046), @@ -1426,8 +1031,14 @@ interface IAdviseSink : IUnknown default: wireHGLOBAL hGeneric; } GDI_OBJECT; + /* When NONAMELESSUNION is not defined, the presence of _STGMEDIUM_UNION + * violates the C spec, but is necessary for C++. Avoid C spec violation. */ + cpp_quote("#if !defined(NONAMELESSUNION) && !defined(__cplusplus)") + cpp_quote("#define _STGMEDIUM_UNION") + cpp_quote("#endif") + typedef struct _userSTGMEDIUM { - union switch(DWORD tymed) u { + union _STGMEDIUM_UNION switch(DWORD tymed) u { case TYMED_NULL: ; case TYMED_MFPICT: wireHMETAFILEPICT hMetaFilePict; case TYMED_ENHMF: wireHENHMETAFILE hHEnhMetaFile; @@ -1440,6 +1051,10 @@ interface IAdviseSink : IUnknown IUnknown *pUnkForRelease; } userSTGMEDIUM; + cpp_quote("#if !defined(NONAMELESSUNION) && !defined(__cplusplus)") + cpp_quote("#undef _STGMEDIUM_UNION") + cpp_quote("#endif") + typedef [unique] userSTGMEDIUM *wireSTGMEDIUM; typedef [wire_marshal(wireSTGMEDIUM)] uSTGMEDIUM STGMEDIUM; @@ -1678,379 +1293,6 @@ interface IMessageFilter : IUnknown [in] DWORD dwPendingType); } -[ - local, - object, - uuid(D5F56B60-593B-101A-B569-08002B2DBF7A) -] -interface IRpcChannelBuffer : IUnknown -{ - typedef [unique] IRpcChannelBuffer *LPRPCCHANNELBUFFER; - - typedef unsigned long RPCOLEDATAREP; - - typedef struct tagRPCOLEMESSAGE { - void *reserved1; - RPCOLEDATAREP dataRepresentation; - void *Buffer; - ULONG cbBuffer; - ULONG iMethod; - void *reserved2[5]; - ULONG rpcFlags; - } RPCOLEMESSAGE; - - typedef RPCOLEMESSAGE *PRPCOLEMESSAGE; - - HRESULT GetBuffer( - [in] RPCOLEMESSAGE *pMessage, - [in] REFIID riid); - - HRESULT SendReceive( - [in,out] RPCOLEMESSAGE *pMessage, - [out] ULONG *pStatus); - - HRESULT FreeBuffer( - [in] RPCOLEMESSAGE *pMessage); - - HRESULT GetDestCtx( - [out] DWORD *pdwDestContext, - [out] void **ppvDestContext); - - HRESULT IsConnected(); -} - -[ - local, - object, - uuid(594f31d0-7f19-11d0-b194-00a0c90dc8bf) -] -interface IRpcChannelBuffer2 : IRpcChannelBuffer -{ - typedef [unique] IRpcChannelBuffer2 *LPRPCCHANNELBUFFER2; - - HRESULT GetProtocolVersion( - [in,out] DWORD *pdwVersion); -} - -[ - local, - object, - uuid(25B15600-0115-11d0-BF0D-00AA00B8DFD2) -] -interface IRpcChannelBuffer3 : IRpcChannelBuffer2 -{ - typedef [unique] IRpcChannelBuffer3 *LPRPCCHANNELBUFFER3; - - HRESULT Send( - [in,out] RPCOLEMESSAGE *pMsg, - [out] ULONG *pulStatus); - - HRESULT Receive( - [in,out] RPCOLEMESSAGE *pMsg, - [in] ULONG ulSize, - [out] ULONG *pulStatus); - - HRESULT Cancel( - [in] RPCOLEMESSAGE *pMsg); - - HRESULT GetCallContext( - [in] RPCOLEMESSAGE *pMsg, - [in] REFIID riid, - [out] void **pInterface); - - HRESULT GetDestCtxEx( - [in] RPCOLEMESSAGE *pMsg, - [out] DWORD *pdwDestContext, - [out] void **ppvDestContext); - - HRESULT GetState( - [in] RPCOLEMESSAGE *pMsg, - [out] DWORD *pState); - - HRESULT RegisterAsync( - [in] RPCOLEMESSAGE *pMsg, - [in] IAsyncManager *pAsyncMgr); -} - -[ - local, - object, - uuid(a5029fb6-3c34-11d1-9c99-00c04fb998aa), - pointer_default(unique) -] -interface IAsyncRpcChannelBuffer : IRpcChannelBuffer2 -{ - HRESULT Send( - [in, out] RPCOLEMESSAGE *pMsg, - [in] ISynchronize *pSync, - [out] ULONG *pulStatus); - - HRESULT Receive( - [in, out] RPCOLEMESSAGE *pMsg, - [out] ULONG *pulStatus); - - HRESULT GetDestCtxEx( - [in] RPCOLEMESSAGE *pMsg, - [out] DWORD *pdwDestContext, - [out] void **ppvDestContext); -} - -[ - local, - object, - uuid(58a08519-24c8-4935-b482-3fd823333a4f) -] -interface IRpcSyntaxNegotiate : IUnknown -{ - HRESULT NegotiateSyntax( - [in, out] RPCOLEMESSAGE *pMsg); -} - -[ - local, - object, - uuid(D5F56A34-593B-101A-B569-08002B2DBF7A) -] -interface IRpcProxyBuffer : IUnknown -{ - typedef [unique] IRpcProxyBuffer *LPRPCPROXYBUFFER; - - HRESULT Connect( - [in, unique] IRpcChannelBuffer *pRpcChannelBuffer); - - void Disconnect(); -} - -[ - local, - object, - uuid(D5F56AFC-593B-101A-B569-08002B2DBF7A) -] -interface IRpcStubBuffer : IUnknown -{ - typedef [unique] IRpcStubBuffer *LPRPCSTUBBUFFER; - - HRESULT Connect( - [in] IUnknown *pUnkServer); - - void Disconnect(); - - HRESULT Invoke( - [in] RPCOLEMESSAGE *_prpcmsg, - [in] IRpcChannelBuffer *_pRpcChannelBuffer); - - IRpcStubBuffer *IsIIDSupported( - [in] REFIID riid); - - ULONG CountRefs(); - - HRESULT DebugServerQueryInterface( - void **ppv); - - void DebugServerRelease( - void *pv); -} - -[ - local, - object, - uuid(D5F569D0-593B-101A-B569-08002B2DBF7A) -] -interface IPSFactoryBuffer : IUnknown -{ - typedef [unique] IPSFactoryBuffer *LPPSFACTORYBUFFER; - - HRESULT CreateProxy( - [in] IUnknown *pUnkOuter, - [in] REFIID riid, - [out] IRpcProxyBuffer **ppProxy, - [out] void **ppv); - - HRESULT CreateStub( - [in] REFIID riid, - [in, unique] IUnknown *pUnkServer, - [out] IRpcStubBuffer **ppStub); -} - -[ - local, - object, - uuid(1008c4a0-7613-11cf-9af1-0020af6e72f4) -] -interface IChannelHook : IUnknown -{ - typedef [unique] IChannelHook *LPCHANNELHOOK; - - typedef struct SChannelHookCallInfo { - IID iid; - DWORD cbSize; - GUID uCausality; - DWORD dwServerPid; - DWORD iMethod; - void *pObject; - } SChannelHookCallInfo; - - void ClientGetSize( - [in] REFGUID uExtent, - [in] REFIID riid, - [out] ULONG *pDataSize); - - void ClientFillBuffer( - [in] REFGUID uExtent, - [in] REFIID riid, - [in, out] ULONG *pDataSize, - [in] void *pDataBuffer); - - void ClientNotify( - [in] REFGUID uExtent, - [in] REFIID riid, - [in] ULONG cbDataSize, - [in] void *pDataBuffer, - [in] DWORD lDataRep, - [in] HRESULT hrFault); - - void ServerNotify( - [in] REFGUID uExtent, - [in] REFIID riid, - [in] ULONG cbDataSize, - [in] void *pDataBuffer, - [in] DWORD lDataRep); - - void ServerGetSize( - [in] REFGUID uExtent, - [in] REFIID riid, - [in] HRESULT hrFault, - [out] ULONG *pDataSize); - - void ServerFillBuffer( - [in] REFGUID uExtent, - [in] REFIID riid, - [in, out] ULONG *pDataSize, - [in] void *pDataBuffer, - [in] HRESULT hrFault ); -} - -extern const FMTID FMTID_SummaryInformation; -extern const FMTID FMTID_DocSummaryInformation; -extern const FMTID FMTID_UserDefinedProperties; - - -/******************** Connection Points ********************/ -/* FIXME */ - -/******************** DCOM ********************/ - -[ - local, - object, - uuid(0000013D-0000-0000-C000-000000000046) -] -interface IClientSecurity : IUnknown -{ - typedef struct tagSOLE_AUTHENTICATION_SERVICE { - DWORD dwAuthnSvc; - DWORD dwAuthzSvc; - OLECHAR *pPrincipalName; - HRESULT hr; - } SOLE_AUTHENTICATION_SERVICE; - - typedef SOLE_AUTHENTICATION_SERVICE *PSOLE_AUTHENTICATION_SERVICE; - - typedef struct tagSOLE_AUTHENTICATION_INFO { - DWORD dwAuthnSvc; - DWORD dwAuthzSvc; - void *pAuthInfo; - } SOLE_AUTHENTICATION_INFO; - - const OLECHAR *COLE_DEFAULT_PRINCIPAL = (OLECHAR*) -1; - const void *COLE_DEFAULT_AUTHINFO = (void*) -1; - - typedef struct tagSOLE_AUTHENTICATION_LIST { - DWORD cAuthInfo; - SOLE_AUTHENTICATION_INFO *aAuthInfo; - } SOLE_AUTHENTICATION_LIST; - - typedef enum tagEOLE_AUTHENTICATION_CAPABILITIES { - EOAC_NONE = 0x0, - EOAC_MUTUAL_AUTH = 0x1, - EOAC_SECURE_REFS = 0x2, /* CoInitializeSecurity only */ - EOAC_ACCESS_CONTROL = 0x4, /* CoInitializeSecurity only */ - EOAC_APPID = 0x8, /* CoInitializeSecurity only */ - EOAC_DYNAMIC = 0x10, /* CoInitializeSecurity only */ - EOAC_STATIC_CLOAKING = 0x20, - EOAC_DYNAMIC_CLOAKING = 0x40, - EOAC_ANY_AUTHORITY = 0x80, - EOAC_MAKE_FULLSIC = 0x100, - EOAC_REQUIRE_FULLSIC = 0x200, /* CoInitializeSecurity only */ - EOAC_AUTO_IMPERSONATE = 0x400, /* CoInitializeSecurity only */ - EOAC_DEFAULT = 0x800, - EOAC_DISABLE_AAA = 0x1000, /* CoInitializeSecurity only */ - EOAC_NO_CUSTOM_MARSHAL = 0x2000, /* CoInitializeSecurity only */ - } EOLE_AUTHENTICATION_CAPABILITIES; - - HRESULT QueryBlanket( - [in] IUnknown *pProxy, - [out] DWORD *pAuthnSvc, - [out] DWORD *pAuthzSvc, - [out] OLECHAR **pServerPrincName, - [out] DWORD *pAuthnLevel, - [out] DWORD *pImpLevel, - [out] void **pAuthInfo, - [out] DWORD *pCapabilities); - - HRESULT SetBlanket( - [in] IUnknown *pProxy, - [in] DWORD AuthnSvc, - [in] DWORD AuthzSvc, - [in] OLECHAR *pServerPrincName, - [in] DWORD AuthnLevel, - [in] DWORD ImpLevel, - [in] void *pAuthInfo, - [in] DWORD Capabilities); - - HRESULT CopyProxy( - [in] IUnknown *pProxy, - [out] IUnknown **ppCopy); -} - -[ - local, - object, - uuid(0000013E-0000-0000-C000-000000000046) -] -interface IServerSecurity : IUnknown -{ - HRESULT QueryBlanket( - [out] DWORD *pAuthnSvc, - [out] DWORD *pAuthzSvc, - [out] OLECHAR **pServerPrincName, - [out] DWORD *pAuthnLevel, - [out] DWORD *pImpLevel, - [out] void **pPrivs, - [out] DWORD *pCapabilities); - - HRESULT ImpersonateClient(); - - HRESULT RevertToSelf(); - - BOOL IsImpersonating(); -} - -[ - local, - object, - uuid(00000024-0000-0000-C000-000000000046) -] -interface IAsyncSetup : IUnknown -{ - HRESULT GetAsyncManager( - [in] REFIID riid, - [in] IUnknown *pOuter, - [in] DWORD dwFlags, - [out] IUnknown **ppInner, - [out] IAsyncManager **ppAsyncMgr); -} - [ object, uuid(0e6d4d92-6738-11cf-9608-00aa00680db4) @@ -2065,201 +1307,6 @@ interface IDirectWriterLock : IUnknown HRESULT HaveWriteAccess(); } -[ - object, - uuid(00000030-0000-0000-C000-000000000046) -] - -interface ISynchronize : IUnknown -{ - HRESULT Wait( - [in] DWORD dwFlags, - [in] DWORD dwMilliseconds); - - HRESULT Signal(); - - HRESULT Reset(); -} - - -[ - local, - object, - uuid(00000031-0000-0000-C000-000000000046) -] -interface ISynchronizeHandle : IUnknown -{ - HRESULT GetHandle( - [out] HANDLE *ph); -} - - -[ - local, - object, - uuid(00000032-0000-0000-C000-000000000046) -] -interface ISynchronizeEvent : ISynchronizeHandle -{ - HRESULT SetEventHandle( - [in] HANDLE *ph); -} - - -[ - local, - object, - uuid(00000033-0000-0000-C000-000000000046) -] -interface ISynchronizeContainer : IUnknown -{ - HRESULT AddSynchronize( - [in] ISynchronize *pSync); - - HRESULT WaitMultiple( - [in] DWORD dwFlags, - [in] DWORD dwTimeOut, - [out] ISynchronize **ppSync); -} - -[ - local, - object, - uuid(00000025-0000-0000-C000-000000000046) -] -interface ISynchronizeMutex : ISynchronize -{ - HRESULT ReleaseMutex(); -} - -[ - local, - object, - uuid(00000029-0000-0000-C000-000000000046) -] - -interface ICancelMethodCalls : IUnknown -{ - typedef [unique] ICancelMethodCalls *LPCANCELMETHODCALLS; - - HRESULT Cancel( - [in] ULONG ulSeconds); - - HRESULT TestCancel(); -} - -[ - local, - object, - uuid(0000002A-0000-0000-C000-000000000046) -] -interface IAsyncManager : IUnknown -{ - typedef enum tagDCOM_CALL_STATE { - DCOM_NONE = 0, - DCOM_CALL_COMPLETE = 1, - DCOM_CALL_CANCELED = 2 - } DCOM_CALL_STATE; - - HRESULT CompleteCall( - [in] HRESULT Result); - - HRESULT GetCallContext( - [in] REFIID riid, - [out] void **pInterface); - - HRESULT GetState( - [out] ULONG *pulStateFlags); -} - -[ - local, - object, - uuid(1c733a30-2a1c-11ce-ade5-00aa0044773d), - pointer_default(unique) -] -interface ICallFactory : IUnknown -{ - HRESULT CreateCall( - [in] REFIID riid, - [in] IUnknown *pCtrlUnk, - [in] REFIID riid2, - [out, iid_is(riid2)] IUnknown **ppv); -} - -[ - local, - object, - uuid(00000144-0000-0000-C000-000000000046) -] -interface IRpcOptions : IUnknown -{ - HRESULT Set( - [in] IUnknown *pPrx, - [in] DWORD dwProperty, - [in] ULONG_PTR dwValue); - - HRESULT Query( - [in] IUnknown *pPrx, - [in] DWORD dwProperty, - [out] ULONG_PTR *pdwValue); -} - -enum { - COMBND_RPCTIMEOUT = 1, - COMBND_SERVER_LOCALITY = 2 -}; - -enum { - SERVER_LOCALITY_PROCESS_LOCAL = 0, - SERVER_LOCALITY_MACHINE_LOCAL = 1, - SERVER_LOCALITY_REMOTE = 2 -}; - -[ - local, - object, - uuid(00000149-0000-0000-C000-000000000046), - pointer_default(unique) -] -interface IRpcHelper : IUnknown -{ - HRESULT GetDCOMProtocolVersion( - [out] DWORD *pComVersion); - - HRESULT GetIIDFromOBJREF( - [in] void *pObjRef, - [out] IID **piid); -} - -[ - local, - object, - uuid(eb0cb9e8-7996-11d2-872e-0000f8080859) -] -interface IReleaseMarshalBuffers : IUnknown -{ - HRESULT ReleaseMarshalBuffer( - [in] RPCOLEMESSAGE *pMsg, - [in] DWORD dwFlags, - [in, unique] IUnknown *pChnl); -} - -[ - local, - object, - uuid(0000002B-0000-0000-C000-000000000046) -] -interface IWaitMultiple : IUnknown -{ - HRESULT WaitMultiple( - [in] DWORD timeout, - [out] ISynchronize **pSync); - HRESULT AddSynchronize( - [in] ISynchronize *pSync); -} - - [ object, uuid(00000026-0000-0000-C000-000000000046) @@ -2290,87 +1337,6 @@ interface IForegroundTransfer : IUnknown [in] void *lpvReserved); } -[ - local, - object, - uuid(00000147-0000-0000-C000-000000000046) -] -interface IAddrTrackingControl : IUnknown -{ - typedef [unique] IAddrTrackingControl *LPADDRTRACKINGCONTROL; - - HRESULT EnableCOMDynamicAddrTracking(); - HRESULT DisableCOMDynamicAddrTracking(); -} - -[ - local, - object, - uuid(00000148-0000-0000-C000-000000000046) -] -interface IAddrExclusionControl : IUnknown -{ - typedef [unique] IAddrExclusionControl *LPADDREXCLUSIONCONTROL; - - HRESULT GetCurrentAddrExclusionList( - [in] REFIID riid, - [out, iid_is(riid)] void **ppEnumerator); - HRESULT UpdateAddrExclusionList( - [in] IUnknown *pEnumerator); -} - -typedef enum _APTTYPE { - APTTYPE_CURRENT = -1, - APTTYPE_STA = 0, - APTTYPE_MTA = 1, - APTTYPE_NA = 2, - APTTYPE_MAINSTA = 3 -} APTTYPE; - -typedef enum _APTTYPEQUALIFIER { - APTTYPEQUALIFIER_NONE = 0, - APTTYPEQUALIFIER_IMPLICIT_MTA = 1, - APTTYPEQUALIFIER_NA_ON_MTA = 2, - APTTYPEQUALIFIER_NA_ON_STA = 3, - APTTYPEQUALIFIER_NA_ON_IMPLICIT_MTA = 4, - APTTYPEQUALIFIER_NA_ON_MAINSTA = 5 -} APTTYPEQUALIFIER; - -typedef enum _THDTYPE { - THDTYPE_BLOCKMESSAGES = 0, - THDTYPE_PROCESSMESSAGES = 1 -} THDTYPE; - -[ - local, - object, - uuid(000001ce-0000-0000-C000-000000000046), - pointer_default(unique) -] -interface IComThreadingInfo : IUnknown -{ - HRESULT GetCurrentApartmentType( - [out] APTTYPE *pAptType); - HRESULT GetCurrentThreadType( - [out] THDTYPE *pThreadType); - HRESULT GetCurrentLogicalThreadId( - [out] GUID *pguidLogicalThreadId); - HRESULT SetCurrentLogicalThreadId( - [in] REFGUID rguid); -} - - -[ - object, - pointer_default(unique), - uuid(72380d55-8d2b-43a3-8513-2b6ef31434e9) -] -interface IProcessInitControl : IUnknown -{ - HRESULT ResetInitializerTimeout( - [in] DWORD dwSecondsRemaining); -} - [ local, object, @@ -2416,40 +1382,6 @@ interface IThumbnailExtractor : IUnknown [in] IStorage *pStg); } -typedef enum tagGLOBALOPT_PROPERTIES -{ - COMGLB_EXCEPTION_HANDLING = 1, - COMGLB_APPID = 2, - COMGLB_RPC_THREADPOOL_SETTING = 3 -} GLOBALOPT_PROPERTIES; - -typedef enum tagGLOBALOPT_EH_VALUES -{ - COMGLB_EXCEPTION_HANDLE = 0, - COMGLB_EXCEPTION_DONOT_HANDLE_FATAL = 1, - COMGLB_EXCEPTION_DONOT_HANDLE = COMGLB_EXCEPTION_DONOT_HANDLE_FATAL, - COMGLB_EXCEPTION_DONOT_HANDLE_ANY = 2 -} GLOBALOPT_EH_VALUES; - -typedef enum tagGLOBALOPT_RPCTP_VALUES -{ - COMGLB_RPC_THREADPOOL_SETTING_DEFAULT_POOL = 0, - COMGLB_RPC_THREADPOOL_SETTING_PRIVATE_POOL = 1 -} GLOBALOPT_RPCTP_VALUES; - - -[ - object, - local, - pointer_default(unique), - uuid(0000015B-0000-0000-C000-000000000046) -] -interface IGlobalOptions : IUnknown -{ - HRESULT Set([in] GLOBALOPT_PROPERTIES property, [in] ULONG_PTR value); - HRESULT Query([in] GLOBALOPT_PROPERTIES property, [out ] ULONG_PTR *value); -} - [ object, pointer_default(unique), @@ -2470,83 +1402,3 @@ interface IApartmentShutdown : IUnknown { void OnUninitialize([in] UINT64 identifier); } - -cpp_quote("#ifdef USE_COM_CONTEXT_DEF") - -typedef DWORD CPFLAGS; - -typedef struct tagContextProperty -{ - GUID policyId; - CPFLAGS flags; - [unique] IUnknown *pUnk; -} ContextProperty; - -[ - local, - object, - uuid(000001c1-0000-0000-C000-000000000046) -] -interface IEnumContextProps : IUnknown -{ - typedef [unique] IEnumContextProps *LPENUMCONTEXTPROPS; - - HRESULT Next( - [in] ULONG celt, - [out, size_is(celt), length_is(*pceltFetched)] ContextProperty *pContextProperties, - [out] ULONG *pceltFetched); - - HRESULT Skip( - [in] ULONG celt); - - HRESULT Reset(); - - HRESULT Clone( - [out] IEnumContextProps **ppEnumContextProps); - - HRESULT Count( - [out] ULONG *pcelt); -} - -[ - local, - object, - uuid(000001c0-0000-0000-C000-000000000046) -] -interface IContext : IUnknown -{ - HRESULT SetProperty( - [in] REFGUID policyId, - [in] CPFLAGS flags, - [in] IUnknown *pUnk); - - HRESULT RemoveProperty( - [in] REFGUID policyId); - - HRESULT GetProperty( - [in] REFGUID guid, - [out] CPFLAGS *pFlags, - [out] IUnknown **ppUnk); - - HRESULT EnumContextProps( - [out] IEnumContextProps **ppEnumContextProps); -} - -[ - local, - object, - uuid(000001c6-0000-0000-c000-000000000046), - pointer_default(unique) -] -interface IObjContext : IContext -{ - void Reserved1(); - void Reserved2(); - void Reserved3(); - void Reserved4(); - void Reserved5(); - void Reserved6(); - void Reserved7(); -} - -cpp_quote("#endif /* defined USE_COM_CONTEXT_DEF */") diff --git a/sdk/include/psdk/objidlbase.idl b/sdk/include/psdk/objidlbase.idl new file mode 100644 index 00000000000..9a4eed4acb3 --- /dev/null +++ b/sdk/include/psdk/objidlbase.idl @@ -0,0 +1,1253 @@ +/* + * Copyright 2002 Ove Kaaven + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef DO_NO_IMPORTS +import "unknwn.idl"; +#endif + +cpp_quote("#ifndef _OBJIDLBASE_") +cpp_quote("#define _OBJIDLBASE_") + +interface IStream; +interface IEnumString; + +interface IAsyncManager; +interface ISynchronize; + +typedef struct _COSERVERINFO { + DWORD dwReserved1; + LPWSTR pwszName; + COAUTHINFO *pAuthInfo; + DWORD dwReserved2; +} COSERVERINFO; + +/******************** Fundamentals ********************/ + +[ + local, + object, + uuid(00000003-0000-0000-C000-000000000046) +] +interface IMarshal : IUnknown +{ + typedef [unique] IMarshal *LPMARSHAL; + + HRESULT GetUnmarshalClass( + [in] REFIID riid, + [in, unique] void *pv, + [in] DWORD dwDestContext, + [in, unique] void *pvDestContext, + [in] DWORD mshlflags, + [out] CLSID *pCid); + + HRESULT GetMarshalSizeMax( + [in] REFIID riid, + [in, unique] void *pv, + [in] DWORD dwDestContext, + [in, unique] void *pvDestContext, + [in] DWORD mshlflags, + [out] DWORD *pSize); + + HRESULT MarshalInterface( + [in, unique] IStream *pStm, + [in] REFIID riid, + [in, unique] void *pv, + [in] DWORD dwDestContext, + [in, unique] void *pvDestContext, + [in] DWORD mshlflags); + + HRESULT UnmarshalInterface( + [in, unique] IStream *pStm, + [in] REFIID riid, + [out] void **ppv); + + HRESULT ReleaseMarshalData( + [in, unique] IStream *pStm); + + HRESULT DisconnectObject( + [in] DWORD dwReserved); +} + +[ + local, + object, + uuid(94ea2b94-e9cc-49e0-c0ff-ee64ca8f5b90) +] +interface IAgileObject : IUnknown +{ +} + +[ + local, + object, + uuid(c03f6a43-65a4-9818-987e-e0b810d2a6f2), + pointer_default(unique) +] +interface IAgileReference : IUnknown +{ + HRESULT Resolve([in] REFIID riid, [out, retval, iid_is(riid)] void **object); +} + +[ + local, + object, + uuid(ecc8691b-c1db-4dc0-855e-65f6c551af49) +] +interface INoMarshal : IUnknown +{ +} + +[ + local, + object, + uuid(000001cf-0000-0000-C000-000000000046) +] +interface IMarshal2 : IMarshal +{ + typedef [unique] IMarshal2 *LPMARSHAL2; +} + +[ + local, + object, + uuid(00000018-0000-0000-C000-000000000046) +] +interface IStdMarshalInfo : IUnknown +{ + typedef [unique] IStdMarshalInfo *LPSTDMARSHALINFO; + + HRESULT GetClassForHandler( + [in] DWORD dwDestContext, + [in, unique] void *pvDestContext, + [out] CLSID *pClsid); +} + +[ + local, + object, + uuid(00000019-0000-0000-C000-000000000046) +] +interface IExternalConnection : IUnknown +{ + typedef [unique] IExternalConnection *LPEXTERNALCONNECTION; + + typedef enum tagEXTCONN { + EXTCONN_STRONG = 0x0001, + EXTCONN_WEAK = 0x0002, + EXTCONN_CALLABLE = 0x0004 + } EXTCONN; + + DWORD AddConnection( + [in] DWORD extconn, + [in] DWORD reserved); + + DWORD ReleaseConnection( + [in] DWORD extconn, + [in] DWORD reserved, + [in] BOOL fLastReleaseCloses); +} + +[ + local, + object, + uuid(00000020-0000-0000-C000-000000000046) +] +interface IMultiQI : IUnknown +{ + typedef [unique] IMultiQI *LPMULTIQI; + + typedef struct tagMULTI_QI { + const IID *pIID; + IUnknown *pItf; + HRESULT hr; + } MULTI_QI; + + HRESULT QueryMultipleInterfaces( + [in] ULONG cMQIs, + [in, out] MULTI_QI *pMQIs); +} + +[ + local, + object, + uuid(00000002-0000-0000-C000-000000000046) +] +interface IMalloc : IUnknown +{ + typedef [unique] IMalloc *LPMALLOC; + + LPVOID Alloc( + [in] SIZE_T cb); + + LPVOID Realloc( + [in] LPVOID pv, + [in] SIZE_T cb); + + void Free( + [in] LPVOID pv); + + SIZE_T GetSize( + [in] LPVOID pv); + + int DidAlloc(LPVOID pv); + + void HeapMinimize(); +} + +[ + local, + object, + uuid(00000021-0000-0000-C000-000000000046) +] +interface IInternalUnknown : IUnknown +{ + HRESULT QueryInternalInterface( + [in] REFIID riid, + [out] void **ppv); +} + +[ + object, + uuid(00000100-0000-0000-C000-000000000046), + pointer_default(unique) +] +interface IEnumUnknown : IUnknown +{ + typedef [unique] IEnumUnknown *LPENUMUNKNOWN; + + [local] + HRESULT Next( + [in] ULONG celt, + [out] IUnknown **rgelt, + [out] ULONG *pceltFetched); + + [call_as(Next)] + HRESULT RemoteNext( + [in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + IUnknown **rgelt, + [out] ULONG *pceltFetched); + + HRESULT Skip( + [in] ULONG celt); + + HRESULT Reset(); + + HRESULT Clone( + [out] IEnumUnknown **ppenum); +} + +[ + object, + uuid(00000022-0000-0000-C000-000000000046), + version(1.0), + pointer_default(unique) +] +interface ISurrogate : IUnknown +{ + typedef [unique] ISurrogate *LPSURROGATE; + + HRESULT LoadDllServer( + [in] REFCLSID Clsid); + HRESULT FreeSurrogate(); +} + +[ + local, + object, + uuid(00000146-0000-0000-C000-000000000046) +] +interface IGlobalInterfaceTable : IUnknown +{ + typedef [unique] IGlobalInterfaceTable *LPGLOBALINTERFACETABLE; + + HRESULT RegisterInterfaceInGlobal( + [in] IUnknown *pUnk, + [in] REFIID riid, + [out] DWORD *pdwCookie); + + HRESULT RevokeInterfaceFromGlobal( + [in] DWORD dwCookie); + + HRESULT GetInterfaceFromGlobal( + [in] DWORD dwCookie, + [in] REFIID riid, + [out, iid_is(riid)] void **ppv); +} + +[ + object, + uuid(00000101-0000-0000-C000-000000000046), + pointer_default(unique) +] +interface IEnumString : IUnknown +{ + typedef [unique] IEnumString *LPENUMSTRING; + + [local] + HRESULT Next( + [in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + LPOLESTR *rgelt, + [out] ULONG *pceltFetched); + + [call_as(Next)] + HRESULT RemoteNext( + [in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + LPOLESTR *rgelt, + [out] ULONG *pceltFetched); + + HRESULT Skip( + [in] ULONG celt); + + HRESULT Reset(); + + HRESULT Clone( + [out] IEnumString **ppenum); +} + +/******************** Storage ********************/ + +[ + object, + uuid(0c733a30-2a1c-11ce-ade5-00aa0044773d), + pointer_default(unique) +] +interface ISequentialStream : IUnknown +{ + [local] + HRESULT Read( + [out, size_is(cb), length_is(*pcbRead)] + void *pv, + [in] ULONG cb, + [out] ULONG *pcbRead); + + [call_as(Read)] + HRESULT RemoteRead( + [out, size_is(cb), length_is(*pcbRead)] + byte *pv, + [in] ULONG cb, + [out] ULONG *pcbRead); + + [local] + HRESULT Write( + [in, size_is(cb)] const void *pv, + [in] ULONG cb, + [out] ULONG *pcbWritten); + + [call_as(Write)] + HRESULT RemoteWrite( + [in, size_is(cb)] const byte *pv, + [in] ULONG cb, + [out] ULONG *pcbWritten); +} + +[ + object, + uuid(0000000c-0000-0000-C000-000000000046), + pointer_default(unique) +] +interface IStream : ISequentialStream +{ + typedef [unique] IStream *LPSTREAM; + + typedef struct tagSTATSTG { + LPOLESTR pwcsName; + DWORD type; + ULARGE_INTEGER cbSize; + FILETIME mtime; + FILETIME ctime; + FILETIME atime; + DWORD grfMode; + DWORD grfLocksSupported; + CLSID clsid; + DWORD grfStateBits; + DWORD reserved; + } STATSTG; + + typedef enum tagSTGTY { + STGTY_STORAGE = 1, + STGTY_STREAM = 2, + STGTY_LOCKBYTES = 3, + STGTY_PROPERTY = 4 + } STGTY; + + typedef enum tagSTREAM_SEEK { + STREAM_SEEK_SET = 0, + STREAM_SEEK_CUR = 1, + STREAM_SEEK_END = 2 + } STREAM_SEEK; + + /* these are defined in Linux's fcntl.h, + * undefine them to avoid conflicts */ + cpp_quote("#undef LOCK_MAND") + cpp_quote("#undef LOCK_READ") + cpp_quote("#undef LOCK_WRITE") + cpp_quote("#undef LOCK_RW") + + typedef enum tagLOCKTYPE { + LOCK_WRITE = 1, + LOCK_EXCLUSIVE = 2, + LOCK_ONLYONCE = 4 + } LOCKTYPE; + + [local] + HRESULT Seek( + [in] LARGE_INTEGER dlibMove, + [in] DWORD dwOrigin, + [out] ULARGE_INTEGER *plibNewPosition); + + [call_as(Seek)] + HRESULT RemoteSeek( + [in] LARGE_INTEGER dlibMove, + [in] DWORD dwOrigin, + [out] ULARGE_INTEGER *plibNewPosition); + + HRESULT SetSize( + [in] ULARGE_INTEGER libNewSize); + + [local] + HRESULT CopyTo( + [in, unique] IStream *pstm, + [in] ULARGE_INTEGER cb, + [out] ULARGE_INTEGER *pcbRead, + [out] ULARGE_INTEGER *pcbWritten); + + [call_as(CopyTo)] + HRESULT RemoteCopyTo( + [in, unique] IStream *pstm, + [in] ULARGE_INTEGER cb, + [out] ULARGE_INTEGER *pcbRead, + [out] ULARGE_INTEGER *pcbWritten); + + HRESULT Commit( + [in] DWORD grfCommitFlags); + + HRESULT Revert(); + + HRESULT LockRegion( + [in] ULARGE_INTEGER libOffset, + [in] ULARGE_INTEGER cb, + [in] DWORD dwLockType); + + HRESULT UnlockRegion( + [in] ULARGE_INTEGER libOffset, + [in] ULARGE_INTEGER cb, + [in] DWORD dwLockType); + + HRESULT Stat( + [out] STATSTG *pstatstg, + [in] DWORD grfStatFlag); + + HRESULT Clone( + [out] IStream **ppstm); +} + + + + +[ + local, + object, + uuid(D5F56B60-593B-101A-B569-08002B2DBF7A) +] +interface IRpcChannelBuffer : IUnknown +{ + typedef [unique] IRpcChannelBuffer *LPRPCCHANNELBUFFER; + + typedef unsigned long RPCOLEDATAREP; + + typedef struct tagRPCOLEMESSAGE { + void *reserved1; + RPCOLEDATAREP dataRepresentation; + void *Buffer; + ULONG cbBuffer; + ULONG iMethod; + void *reserved2[5]; + ULONG rpcFlags; + } RPCOLEMESSAGE; + + typedef RPCOLEMESSAGE *PRPCOLEMESSAGE; + + HRESULT GetBuffer( + [in] RPCOLEMESSAGE *pMessage, + [in] REFIID riid); + + HRESULT SendReceive( + [in,out] RPCOLEMESSAGE *pMessage, + [out] ULONG *pStatus); + + HRESULT FreeBuffer( + [in] RPCOLEMESSAGE *pMessage); + + HRESULT GetDestCtx( + [out] DWORD *pdwDestContext, + [out] void **ppvDestContext); + + HRESULT IsConnected(); +} + +[ + local, + object, + uuid(594f31d0-7f19-11d0-b194-00a0c90dc8bf) +] +interface IRpcChannelBuffer2 : IRpcChannelBuffer +{ + typedef [unique] IRpcChannelBuffer2 *LPRPCCHANNELBUFFER2; + + HRESULT GetProtocolVersion( + [in,out] DWORD *pdwVersion); +} + +[ + local, + object, + uuid(25B15600-0115-11d0-BF0D-00AA00B8DFD2) +] +interface IRpcChannelBuffer3 : IRpcChannelBuffer2 +{ + typedef [unique] IRpcChannelBuffer3 *LPRPCCHANNELBUFFER3; + + HRESULT Send( + [in,out] RPCOLEMESSAGE *pMsg, + [out] ULONG *pulStatus); + + HRESULT Receive( + [in,out] RPCOLEMESSAGE *pMsg, + [in] ULONG ulSize, + [out] ULONG *pulStatus); + + HRESULT Cancel( + [in] RPCOLEMESSAGE *pMsg); + + HRESULT GetCallContext( + [in] RPCOLEMESSAGE *pMsg, + [in] REFIID riid, + [out] void **pInterface); + + HRESULT GetDestCtxEx( + [in] RPCOLEMESSAGE *pMsg, + [out] DWORD *pdwDestContext, + [out] void **ppvDestContext); + + HRESULT GetState( + [in] RPCOLEMESSAGE *pMsg, + [out] DWORD *pState); + + HRESULT RegisterAsync( + [in] RPCOLEMESSAGE *pMsg, + [in] IAsyncManager *pAsyncMgr); +} + +[ + local, + object, + uuid(a5029fb6-3c34-11d1-9c99-00c04fb998aa), + pointer_default(unique) +] +interface IAsyncRpcChannelBuffer : IRpcChannelBuffer2 +{ + HRESULT Send( + [in, out] RPCOLEMESSAGE *pMsg, + [in] ISynchronize *pSync, + [out] ULONG *pulStatus); + + HRESULT Receive( + [in, out] RPCOLEMESSAGE *pMsg, + [out] ULONG *pulStatus); + + HRESULT GetDestCtxEx( + [in] RPCOLEMESSAGE *pMsg, + [out] DWORD *pdwDestContext, + [out] void **ppvDestContext); +} + +[ + local, + object, + uuid(58a08519-24c8-4935-b482-3fd823333a4f) +] +interface IRpcSyntaxNegotiate : IUnknown +{ + HRESULT NegotiateSyntax( + [in, out] RPCOLEMESSAGE *pMsg); +} + +[ + local, + object, + uuid(D5F56A34-593B-101A-B569-08002B2DBF7A) +] +interface IRpcProxyBuffer : IUnknown +{ + typedef [unique] IRpcProxyBuffer *LPRPCPROXYBUFFER; + + HRESULT Connect( + [in, unique] IRpcChannelBuffer *pRpcChannelBuffer); + + void Disconnect(); +} + +[ + local, + object, + uuid(D5F56AFC-593B-101A-B569-08002B2DBF7A) +] +interface IRpcStubBuffer : IUnknown +{ + typedef [unique] IRpcStubBuffer *LPRPCSTUBBUFFER; + + HRESULT Connect( + [in] IUnknown *pUnkServer); + + void Disconnect(); + + HRESULT Invoke( + [in] RPCOLEMESSAGE *_prpcmsg, + [in] IRpcChannelBuffer *_pRpcChannelBuffer); + + IRpcStubBuffer *IsIIDSupported( + [in] REFIID riid); + + ULONG CountRefs(); + + HRESULT DebugServerQueryInterface( + void **ppv); + + void DebugServerRelease( + void *pv); +} + +[ + local, + object, + uuid(D5F569D0-593B-101A-B569-08002B2DBF7A) +] +interface IPSFactoryBuffer : IUnknown +{ + typedef [unique] IPSFactoryBuffer *LPPSFACTORYBUFFER; + + HRESULT CreateProxy( + [in] IUnknown *pUnkOuter, + [in] REFIID riid, + [out] IRpcProxyBuffer **ppProxy, + [out] void **ppv); + + HRESULT CreateStub( + [in] REFIID riid, + [in, unique] IUnknown *pUnkServer, + [out] IRpcStubBuffer **ppStub); +} + +[ + local, + object, + uuid(1008c4a0-7613-11cf-9af1-0020af6e72f4) +] +interface IChannelHook : IUnknown +{ + typedef [unique] IChannelHook *LPCHANNELHOOK; + + typedef struct SChannelHookCallInfo { + IID iid; + DWORD cbSize; + GUID uCausality; + DWORD dwServerPid; + DWORD iMethod; + void *pObject; + } SChannelHookCallInfo; + + void ClientGetSize( + [in] REFGUID uExtent, + [in] REFIID riid, + [out] ULONG *pDataSize); + + void ClientFillBuffer( + [in] REFGUID uExtent, + [in] REFIID riid, + [in, out] ULONG *pDataSize, + [in] void *pDataBuffer); + + void ClientNotify( + [in] REFGUID uExtent, + [in] REFIID riid, + [in] ULONG cbDataSize, + [in] void *pDataBuffer, + [in] DWORD lDataRep, + [in] HRESULT hrFault); + + void ServerNotify( + [in] REFGUID uExtent, + [in] REFIID riid, + [in] ULONG cbDataSize, + [in] void *pDataBuffer, + [in] DWORD lDataRep); + + void ServerGetSize( + [in] REFGUID uExtent, + [in] REFIID riid, + [in] HRESULT hrFault, + [out] ULONG *pDataSize); + + void ServerFillBuffer( + [in] REFGUID uExtent, + [in] REFIID riid, + [in, out] ULONG *pDataSize, + [in] void *pDataBuffer, + [in] HRESULT hrFault ); +} + +extern const FMTID FMTID_SummaryInformation; +extern const FMTID FMTID_DocSummaryInformation; +extern const FMTID FMTID_UserDefinedProperties; + + +/******************** Connection Points ********************/ +/* FIXME */ + +/******************** DCOM ********************/ + +[ + local, + object, + uuid(0000013D-0000-0000-C000-000000000046) +] +interface IClientSecurity : IUnknown +{ + typedef struct tagSOLE_AUTHENTICATION_SERVICE { + DWORD dwAuthnSvc; + DWORD dwAuthzSvc; + OLECHAR *pPrincipalName; + HRESULT hr; + } SOLE_AUTHENTICATION_SERVICE; + + typedef SOLE_AUTHENTICATION_SERVICE *PSOLE_AUTHENTICATION_SERVICE; + + typedef struct tagSOLE_AUTHENTICATION_INFO { + DWORD dwAuthnSvc; + DWORD dwAuthzSvc; + void *pAuthInfo; + } SOLE_AUTHENTICATION_INFO; + + const OLECHAR *COLE_DEFAULT_PRINCIPAL = (OLECHAR*) -1; + const void *COLE_DEFAULT_AUTHINFO = (void*) -1; + + typedef struct tagSOLE_AUTHENTICATION_LIST { + DWORD cAuthInfo; + SOLE_AUTHENTICATION_INFO *aAuthInfo; + } SOLE_AUTHENTICATION_LIST; + + typedef enum tagEOLE_AUTHENTICATION_CAPABILITIES { + EOAC_NONE = 0x0, + EOAC_MUTUAL_AUTH = 0x1, + EOAC_SECURE_REFS = 0x2, /* CoInitializeSecurity only */ + EOAC_ACCESS_CONTROL = 0x4, /* CoInitializeSecurity only */ + EOAC_APPID = 0x8, /* CoInitializeSecurity only */ + EOAC_DYNAMIC = 0x10, /* CoInitializeSecurity only */ + EOAC_STATIC_CLOAKING = 0x20, + EOAC_DYNAMIC_CLOAKING = 0x40, + EOAC_ANY_AUTHORITY = 0x80, + EOAC_MAKE_FULLSIC = 0x100, + EOAC_REQUIRE_FULLSIC = 0x200, /* CoInitializeSecurity only */ + EOAC_AUTO_IMPERSONATE = 0x400, /* CoInitializeSecurity only */ + EOAC_DEFAULT = 0x800, + EOAC_DISABLE_AAA = 0x1000, /* CoInitializeSecurity only */ + EOAC_NO_CUSTOM_MARSHAL = 0x2000, /* CoInitializeSecurity only */ + } EOLE_AUTHENTICATION_CAPABILITIES; + + HRESULT QueryBlanket( + [in] IUnknown *pProxy, + [out] DWORD *pAuthnSvc, + [out] DWORD *pAuthzSvc, + [out] OLECHAR **pServerPrincName, + [out] DWORD *pAuthnLevel, + [out] DWORD *pImpLevel, + [out] void **pAuthInfo, + [out] DWORD *pCapabilities); + + HRESULT SetBlanket( + [in] IUnknown *pProxy, + [in] DWORD AuthnSvc, + [in] DWORD AuthzSvc, + [in] OLECHAR *pServerPrincName, + [in] DWORD AuthnLevel, + [in] DWORD ImpLevel, + [in] void *pAuthInfo, + [in] DWORD Capabilities); + + HRESULT CopyProxy( + [in] IUnknown *pProxy, + [out] IUnknown **ppCopy); +} + +[ + local, + object, + uuid(0000013E-0000-0000-C000-000000000046) +] +interface IServerSecurity : IUnknown +{ + HRESULT QueryBlanket( + [out] DWORD *pAuthnSvc, + [out] DWORD *pAuthzSvc, + [out] OLECHAR **pServerPrincName, + [out] DWORD *pAuthnLevel, + [out] DWORD *pImpLevel, + [out] void **pPrivs, + [out] DWORD *pCapabilities); + + HRESULT ImpersonateClient(); + + HRESULT RevertToSelf(); + + BOOL IsImpersonating(); +} + +[ + local, + object, + uuid(00000024-0000-0000-C000-000000000046) +] +interface IAsyncSetup : IUnknown +{ + HRESULT GetAsyncManager( + [in] REFIID riid, + [in] IUnknown *pOuter, + [in] DWORD dwFlags, + [out] IUnknown **ppInner, + [out] IAsyncManager **ppAsyncMgr); +} + +[ + object, + uuid(00000030-0000-0000-C000-000000000046) +] + +interface ISynchronize : IUnknown +{ + HRESULT Wait( + [in] DWORD dwFlags, + [in] DWORD dwMilliseconds); + + HRESULT Signal(); + + HRESULT Reset(); +} + + +[ + local, + object, + uuid(00000031-0000-0000-C000-000000000046) +] +interface ISynchronizeHandle : IUnknown +{ + HRESULT GetHandle( + [out] HANDLE *ph); +} + + +[ + local, + object, + uuid(00000032-0000-0000-C000-000000000046) +] +interface ISynchronizeEvent : ISynchronizeHandle +{ + HRESULT SetEventHandle( + [in] HANDLE *ph); +} + + +[ + local, + object, + uuid(00000033-0000-0000-C000-000000000046) +] +interface ISynchronizeContainer : IUnknown +{ + HRESULT AddSynchronize( + [in] ISynchronize *pSync); + + HRESULT WaitMultiple( + [in] DWORD dwFlags, + [in] DWORD dwTimeOut, + [out] ISynchronize **ppSync); +} + +[ + local, + object, + uuid(00000025-0000-0000-C000-000000000046) +] +interface ISynchronizeMutex : ISynchronize +{ + HRESULT ReleaseMutex(); +} + +[ + local, + object, + uuid(00000029-0000-0000-C000-000000000046) +] + +interface ICancelMethodCalls : IUnknown +{ + typedef [unique] ICancelMethodCalls *LPCANCELMETHODCALLS; + + HRESULT Cancel( + [in] ULONG ulSeconds); + + HRESULT TestCancel(); +} + +[ + local, + object, + uuid(0000002A-0000-0000-C000-000000000046) +] +interface IAsyncManager : IUnknown +{ + typedef enum tagDCOM_CALL_STATE { + DCOM_NONE = 0, + DCOM_CALL_COMPLETE = 1, + DCOM_CALL_CANCELED = 2 + } DCOM_CALL_STATE; + + HRESULT CompleteCall( + [in] HRESULT Result); + + HRESULT GetCallContext( + [in] REFIID riid, + [out] void **pInterface); + + HRESULT GetState( + [out] ULONG *pulStateFlags); +} + +[ + local, + object, + uuid(1c733a30-2a1c-11ce-ade5-00aa0044773d), + pointer_default(unique) +] +interface ICallFactory : IUnknown +{ + HRESULT CreateCall( + [in] REFIID riid, + [in] IUnknown *pCtrlUnk, + [in] REFIID riid2, + [out, iid_is(riid2)] IUnknown **ppv); +} + +[ + local, + object, + uuid(00000144-0000-0000-C000-000000000046) +] +interface IRpcOptions : IUnknown +{ + HRESULT Set( + [in] IUnknown *pPrx, + [in] DWORD dwProperty, + [in] ULONG_PTR dwValue); + + HRESULT Query( + [in] IUnknown *pPrx, + [in] DWORD dwProperty, + [out] ULONG_PTR *pdwValue); +} + +enum { + COMBND_RPCTIMEOUT = 1, + COMBND_SERVER_LOCALITY = 2 +}; + +enum { + SERVER_LOCALITY_PROCESS_LOCAL = 0, + SERVER_LOCALITY_MACHINE_LOCAL = 1, + SERVER_LOCALITY_REMOTE = 2 +}; + +[ + local, + object, + uuid(00000149-0000-0000-C000-000000000046), + pointer_default(unique) +] +interface IRpcHelper : IUnknown +{ + HRESULT GetDCOMProtocolVersion( + [out] DWORD *pComVersion); + + HRESULT GetIIDFromOBJREF( + [in] void *pObjRef, + [out] IID **piid); +} + +[ + local, + object, + uuid(eb0cb9e8-7996-11d2-872e-0000f8080859) +] +interface IReleaseMarshalBuffers : IUnknown +{ + HRESULT ReleaseMarshalBuffer( + [in] RPCOLEMESSAGE *pMsg, + [in] DWORD dwFlags, + [in, unique] IUnknown *pChnl); +} + +[ + local, + object, + uuid(0000002B-0000-0000-C000-000000000046) +] +interface IWaitMultiple : IUnknown +{ + HRESULT WaitMultiple( + [in] DWORD timeout, + [out] ISynchronize **pSync); + HRESULT AddSynchronize( + [in] ISynchronize *pSync); +} + + +[ + local, + object, + uuid(00000147-0000-0000-C000-000000000046) +] +interface IAddrTrackingControl : IUnknown +{ + typedef [unique] IAddrTrackingControl *LPADDRTRACKINGCONTROL; + + HRESULT EnableCOMDynamicAddrTracking(); + HRESULT DisableCOMDynamicAddrTracking(); +} + +[ + local, + object, + uuid(00000148-0000-0000-C000-000000000046) +] +interface IAddrExclusionControl : IUnknown +{ + typedef [unique] IAddrExclusionControl *LPADDREXCLUSIONCONTROL; + + HRESULT GetCurrentAddrExclusionList( + [in] REFIID riid, + [out, iid_is(riid)] void **ppEnumerator); + HRESULT UpdateAddrExclusionList( + [in] IUnknown *pEnumerator); +} + +typedef enum _APTTYPE { + APTTYPE_CURRENT = -1, + APTTYPE_STA = 0, + APTTYPE_MTA = 1, + APTTYPE_NA = 2, + APTTYPE_MAINSTA = 3 +} APTTYPE; + +typedef enum _APTTYPEQUALIFIER { + APTTYPEQUALIFIER_NONE, + APTTYPEQUALIFIER_IMPLICIT_MTA, + APTTYPEQUALIFIER_NA_ON_MTA, + APTTYPEQUALIFIER_NA_ON_STA, + APTTYPEQUALIFIER_NA_ON_IMPLICIT_MTA, + APTTYPEQUALIFIER_NA_ON_MAINSTA +} APTTYPEQUALIFIER; + +typedef enum _THDTYPE { + THDTYPE_BLOCKMESSAGES = 0, + THDTYPE_PROCESSMESSAGES = 1 +} THDTYPE; + +[ + local, + object, + uuid(000001ce-0000-0000-C000-000000000046), + pointer_default(unique) +] +interface IComThreadingInfo : IUnknown +{ + HRESULT GetCurrentApartmentType( + [out] APTTYPE *pAptType); + HRESULT GetCurrentThreadType( + [out] THDTYPE *pThreadType); + HRESULT GetCurrentLogicalThreadId( + [out] GUID *pguidLogicalThreadId); + HRESULT SetCurrentLogicalThreadId( + [in] REFGUID rguid); +} + + +[ + object, + pointer_default(unique), + uuid(72380d55-8d2b-43a3-8513-2b6ef31434e9) +] +interface IProcessInitControl : IUnknown +{ + HRESULT ResetInitializerTimeout( + [in] DWORD dwSecondsRemaining); +} + +typedef enum tagGLOBALOPT_PROPERTIES +{ + COMGLB_EXCEPTION_HANDLING = 1, + COMGLB_APPID = 2, + COMGLB_RPC_THREADPOOL_SETTING = 3, + COMGLB_RO_SETTINGS = 4, + COMGLB_UNMARSHALING_POLICY = 5, + COMGLB_PROPERTIES_RESERVED1 = 6, + COMGLB_PROPERTIES_RESERVED2 = 7, + COMGLB_PROPERTIES_RESERVED3 = 8, +} GLOBALOPT_PROPERTIES; + +typedef enum tagGLOBALOPT_EH_VALUES +{ + COMGLB_EXCEPTION_HANDLE = 0, + COMGLB_EXCEPTION_DONOT_HANDLE_FATAL = 1, + COMGLB_EXCEPTION_DONOT_HANDLE = COMGLB_EXCEPTION_DONOT_HANDLE_FATAL, + COMGLB_EXCEPTION_DONOT_HANDLE_ANY = 2 +} GLOBALOPT_EH_VALUES; + +typedef enum tagGLOBALOPT_RPCTP_VALUES +{ + COMGLB_RPC_THREADPOOL_SETTING_DEFAULT_POOL = 0, + COMGLB_RPC_THREADPOOL_SETTING_PRIVATE_POOL = 1 +} GLOBALOPT_RPCTP_VALUES; + +typedef enum tagGLOBALOPT_RO_FLAGS +{ + COMGLB_STA_MODALLOOP_REMOVE_TOUCH_MESSAGES = 0x1, + COMGLB_STA_MODALLOOP_SHARED_QUEUE_REMOVE_INPUT_MESSAGES = 0x2, + COMGLB_STA_MODALLOOP_SHARED_QUEUE_DONOT_REMOVE_INPUT_MESSAGES = 0x4, + COMGLB_FAST_RUNDOWN = 0x8, + COMGLB_RESERVED1 = 0x10, + COMGLB_RESERVED2 = 0x20, + COMGLB_RESERVED3 = 0x40, + COMGLB_STA_MODALLOOP_SHARED_QUEUE_REORDER_POINTER_MESSAGES = 0x80, + COMGLB_RESERVED4 = 0x100, + COMGLB_RESERVED5 = 0x200, + COMGLB_RESERVED6 = 0x400, +} GLOBALOPT_RO_FLAGS; + +typedef enum tagGLOBALOPT_UNMARSHALING_POLICY_VALUES +{ + COMGLB_UNMARSHALING_POLICY_NORMAL = 0, + COMGLB_UNMARSHALING_POLICY_STRONG = 1, + COMGLB_UNMARSHALING_POLICY_HYBRID = 2, +} GLOBALOPT_UNMARSHALING_POLICY_VALUES; + +[ + object, + local, + pointer_default(unique), + uuid(0000015B-0000-0000-C000-000000000046) +] +interface IGlobalOptions : IUnknown +{ + HRESULT Set([in] GLOBALOPT_PROPERTIES property, [in] ULONG_PTR value); + HRESULT Query([in] GLOBALOPT_PROPERTIES property, [out ] ULONG_PTR *value); +} + +cpp_quote("#ifdef USE_COM_CONTEXT_DEF") + +typedef DWORD CPFLAGS; + +typedef struct tagContextProperty +{ + GUID policyId; + CPFLAGS flags; + [unique] IUnknown *pUnk; +} ContextProperty; + +[ + local, + object, + uuid(000001c1-0000-0000-C000-000000000046) +] +interface IEnumContextProps : IUnknown +{ + typedef [unique] IEnumContextProps *LPENUMCONTEXTPROPS; + + HRESULT Next( + [in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] ContextProperty *pContextProperties, + [out] ULONG *pceltFetched); + + HRESULT Skip( + [in] ULONG celt); + + HRESULT Reset(); + + HRESULT Clone( + [out] IEnumContextProps **ppEnumContextProps); + + HRESULT Count( + [out] ULONG *pcelt); +} + +[ + local, + object, + uuid(000001c0-0000-0000-C000-000000000046) +] +interface IContext : IUnknown +{ + HRESULT SetProperty( + [in] REFGUID policyId, + [in] CPFLAGS flags, + [in] IUnknown *pUnk); + + HRESULT RemoveProperty( + [in] REFGUID policyId); + + HRESULT GetProperty( + [in] REFGUID guid, + [out] CPFLAGS *pFlags, + [out] IUnknown **ppUnk); + + HRESULT EnumContextProps( + [out] IEnumContextProps **ppEnumContextProps); +} + +[ + local, + object, + uuid(000001c6-0000-0000-c000-000000000046), + pointer_default(unique) +] +interface IObjContext : IContext +{ + void Reserved1(); + void Reserved2(); + void Reserved3(); + void Reserved4(); + void Reserved5(); + void Reserved6(); + void Reserved7(); +} + +cpp_quote("#endif /* defined USE_COM_CONTEXT_DEF */") +cpp_quote("#endif /* defined _OBJIDLBASE_ */") diff --git a/sdk/include/psdk/wtypes.idl b/sdk/include/psdk/wtypes.idl index 579f2318e34..77a9f1c761a 100644 --- a/sdk/include/psdk/wtypes.idl +++ b/sdk/include/psdk/wtypes.idl @@ -21,16 +21,6 @@ import "basetsd.h"; import "guiddef.h"; -cpp_quote("#ifndef __wtypes_h__") -cpp_quote("#define __wtypes_h__") -cpp_quote("#endif") - -cpp_quote("#ifdef _MSC_VER") -cpp_quote("#pragma warning(push)") -cpp_quote("#pragma warning(disable:4201)") -cpp_quote("#pragma warning(disable:4820)") -cpp_quote("#endif") - [ uuid(D3980A60-910C-1068-9341-00DD010F2F1C), version(0.1), @@ -43,7 +33,7 @@ interface IWinTypes /******************** BASIC WIN32 TYPES ********************/ cpp_quote("#if 0 /* winnt.h */") /* don't redefine these */ -typedef unsigned char BYTE; +typedef byte BYTE; typedef unsigned short WORD; typedef unsigned long DWORD; typedef long BOOL; @@ -120,7 +110,9 @@ typedef struct _SID { UCHAR SubAuthorityCount; SID_IDENTIFIER_AUTHORITY IdentifierAuthority; [size_is(SubAuthorityCount)] ULONG SubAuthority[*]; -} SID, *PSID; +} SID, *PISID; + +typedef void *PSID; typedef USHORT SECURITY_DESCRIPTOR_CONTROL, *PSECURITY_DESCRIPTOR_CONTROL; @@ -141,12 +133,12 @@ typedef struct _SECURITY_DESCRIPTOR { PSID Group; PACL Sacl; PACL Dacl; -} SECURITY_DESCRIPTOR, *PSECURITY_DESCRIPTOR; +} SECURITY_DESCRIPTOR, *PISECURITY_DESCRIPTOR; typedef struct _SECURITY_ATTRIBUTES { DWORD nLength; - LPVOID lpSecurityDescriptor; + [size_is(nLength)] LPVOID lpSecurityDescriptor; BOOL bInheritHandle; } SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES; @@ -297,7 +289,11 @@ typedef WCHAR OLECHAR; typedef [string] OLECHAR *LPOLESTR; typedef [string] const OLECHAR *LPCOLESTR; cpp_quote("#ifndef __WINESRC__") -cpp_quote("#define OLESTR(str) L##str") +cpp_quote("# ifdef WINE_UNICODE_NATIVE") +cpp_quote("# define OLESTR(str) L##str") +cpp_quote("# else") +cpp_quote("# define OLESTR(str) u##str") +cpp_quote("# endif") cpp_quote("#endif") typedef LONG SCODE; @@ -342,22 +338,31 @@ cpp_quote("#define ROTFLAGS_ALLOWANYCLIENT 0x2") cpp_quote("#endif") typedef enum tagCLSCTX { - CLSCTX_INPROC_SERVER = 0x1, - CLSCTX_INPROC_HANDLER = 0x2, - CLSCTX_LOCAL_SERVER = 0x4, - CLSCTX_INPROC_SERVER16 = 0x8, - CLSCTX_REMOTE_SERVER = 0x10, - CLSCTX_INPROC_HANDLER16 = 0x20, - CLSCTX_INPROC_SERVERX86 = 0x40, - CLSCTX_INPROC_HANDLERX86 = 0x80, - CLSCTX_ESERVER_HANDLER = 0x100, - CLSCTX_NO_CODE_DOWNLOAD = 0x400, - CLSCTX_NO_CUSTOM_MARSHAL = 0x1000, - CLSCTX_ENABLE_CODE_DOWNLOAD = 0x2000, - CLSCTX_NO_FAILURE_LOG = 0x4000, - CLSCTX_DISABLE_AAA = 0x8000, - CLSCTX_ENABLE_AAA = 0x10000, - CLSCTX_FROM_DEFAULT_CONTEXT = 0x20000 + CLSCTX_INPROC_SERVER = 0x00000001, + CLSCTX_INPROC_HANDLER = 0x00000002, + CLSCTX_LOCAL_SERVER = 0x00000004, + CLSCTX_INPROC_SERVER16 = 0x00000008, + CLSCTX_REMOTE_SERVER = 0x00000010, + CLSCTX_INPROC_HANDLER16 = 0x00000020, + CLSCTX_INPROC_SERVERX86 = 0x00000040, + CLSCTX_INPROC_HANDLERX86 = 0x00000080, + CLSCTX_ESERVER_HANDLER = 0x00000100, + CLSCTX_NO_CODE_DOWNLOAD = 0x00000400, + CLSCTX_NO_CUSTOM_MARSHAL = 0x00001000, + CLSCTX_ENABLE_CODE_DOWNLOAD = 0x00002000, + CLSCTX_NO_FAILURE_LOG = 0x00004000, + CLSCTX_DISABLE_AAA = 0x00008000, + CLSCTX_ENABLE_AAA = 0x00010000, + CLSCTX_FROM_DEFAULT_CONTEXT = 0x00020000, + CLSCTX_ACTIVATE_X86_SERVER = 0x00040000, + CLSCTX_ACTIVATE_32_BIT_SERVER = CLSCTX_ACTIVATE_X86_SERVER, + CLSCTX_ACTIVATE_64_BIT_SERVER = 0x00080000, + CLSCTX_ENABLE_CLOAKING = 0x00100000, + CLSCTX_APPCONTAINER = 0x00400000, + CLSCTX_ACTIVATE_AAA_AS_IU = 0x00800000, + CLSCTX_RESERVED6 = 0x01000000, + CLSCTX_ACTIVATE_ARM32_SERVER = 0x02000000, + CLSCTX_PS_DLL = 0x80000000, } CLSCTX; cpp_quote("#define CLSCTX_INPROC (CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER)") @@ -560,6 +565,7 @@ typedef [unique] RemotableHandle *wireHFONT; typedef [unique] RemotableHandle *wireHICON; typedef [unique] RemotableHandle *wireHMENU; typedef [unique] RemotableHandle *wireHWND; +typedef [unique] RemotableHandle *wireHMONITOR; cpp_quote("#if 0") /* for IDL only (C/C++ defs are in windef.h) */ DECLARE_WIREM_HANDLE(HACCEL); @@ -569,6 +575,7 @@ DECLARE_WIREM_HANDLE(HFONT); DECLARE_WIREM_HANDLE(HICON); DECLARE_WIREM_HANDLE(HMENU); DECLARE_WIREM_HANDLE(HWND); +DECLARE_WIREM_HANDLE(HMONITOR); typedef HICON HCURSOR; @@ -639,13 +646,8 @@ cpp_quote("#ifndef _tagCY_DEFINED") cpp_quote("#define _tagCY_DEFINED") cpp_quote("typedef union tagCY {") cpp_quote(" struct {") -cpp_quote("#ifdef WORDS_BIGENDIAN") -cpp_quote(" LONG Hi;") -cpp_quote(" ULONG Lo;") -cpp_quote("#else") cpp_quote(" ULONG Lo;") cpp_quote(" LONG Hi;") -cpp_quote("#endif") cpp_quote(" } DUMMYSTRUCTNAME;") cpp_quote(" LONGLONG int64;") cpp_quote("} CY;") @@ -675,13 +677,8 @@ cpp_quote(" } DUMMYUNIONNAME;") cpp_quote(" ULONG Hi32;") cpp_quote(" union {") cpp_quote(" struct {") -cpp_quote("#ifdef WORDS_BIGENDIAN") -cpp_quote(" ULONG Mid32;") -cpp_quote(" ULONG Lo32;") -cpp_quote("#else") cpp_quote(" ULONG Lo32;") cpp_quote(" ULONG Mid32;") -cpp_quote("#endif") cpp_quote(" } DUMMYSTRUCTNAME1;") cpp_quote(" ULONGLONG Lo64;") cpp_quote(" } DUMMYUNIONNAME1;") @@ -847,7 +844,3 @@ typedef struct _tagpropertykey cpp_quote("#endif /*PROPERTYKEY_DEFINED*/") } /* interface IWinTypes */ - -cpp_quote("#ifdef _MSC_VER") -cpp_quote("#pragma warning(pop)") -cpp_quote("#endif") diff --git a/sdk/lib/uuid/CMakeLists.txt b/sdk/lib/uuid/CMakeLists.txt index 52f8eb65f16..9cc61185c22 100644 --- a/sdk/lib/uuid/CMakeLists.txt +++ b/sdk/lib/uuid/CMakeLists.txt @@ -87,6 +87,7 @@ list(APPEND IDL_SOURCES # netprov.idl oaidl.idl objidl.idl + objidlbase.idl objsafe.idl ocidl.idl ocmm.idl diff --git a/sdk/tools/tools.h b/sdk/tools/tools.h new file mode 100644 index 00000000000..fd21807cbf6 --- /dev/null +++ b/sdk/tools/tools.h @@ -0,0 +1,969 @@ +/* + * Helper functions for the Wine tools + * + * Copyright 2021 Alexandre Julliard + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_TOOLS_H +#define __WINE_TOOLS_H + +#ifndef __WINE_CONFIG_H +# error You must include config.h to use this header +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_SYSCTL_H +# include +#endif + +#ifdef _WIN32 +# include +# include +# include +# define mkdir(path,mode) mkdir(path) +# ifndef S_ISREG +# define S_ISREG(mod) (((mod) & _S_IFMT) == _S_IFREG) +# endif +# ifdef _MSC_VER +# define popen _popen +# define pclose _pclose +# define strtoll _strtoi64 +# define strtoull _strtoui64 +# define strncasecmp _strnicmp +# define strcasecmp _stricmp +# endif +#ifdef __REACTOS__ +#define MAX_PATH 260 +#define ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0])) +#else +# include +# include +#endif +#else +extern char **environ; +# include +# include +# include +# ifndef O_BINARY +# define O_BINARY 0 +# endif +# ifndef __int64 +# if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) +# define __int64 long +# else +# define __int64 long long +# endif +# endif +#endif + +#if !defined(__GNUC__) && !defined(__attribute__) +#define __attribute__(x) +#endif + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + +struct target +{ + enum { CPU_i386, CPU_x86_64, CPU_ARM, CPU_ARM64, CPU_ARM64EC } cpu; + + enum + { + PLATFORM_UNSPECIFIED, + PLATFORM_APPLE, + PLATFORM_ANDROID, + PLATFORM_LINUX, + PLATFORM_FREEBSD, + PLATFORM_SOLARIS, + PLATFORM_WINDOWS, + PLATFORM_MINGW, + PLATFORM_CYGWIN + } platform; +}; + +static inline void *xmalloc( size_t size ) +{ + void *res = malloc( size ? size : 1 ); + + if (res == NULL) + { + fprintf( stderr, "Virtual memory exhausted.\n" ); + exit(1); + } + return res; +} + +static inline void *xrealloc (void *ptr, size_t size) +{ + void *res = realloc( ptr, size ); + + if (size && res == NULL) + { + fprintf( stderr, "Virtual memory exhausted.\n" ); + exit(1); + } + return res; +} + +static inline char *xstrdup( const char *str ) +{ + return strcpy( xmalloc( strlen(str)+1 ), str ); +} + +static inline int strendswith( const char *str, const char *end ) +{ + int l = strlen( str ); + int m = strlen( end ); + return l >= m && !strcmp( str + l - m, end ); +} + +static char *strmake( const char* fmt, ... ) __attribute__ ((__format__ (__printf__, 1, 2))); +static inline char *strmake( const char* fmt, ... ) +{ + int n; + size_t size = 100; + va_list ap; + + for (;;) + { + char *p = xmalloc( size ); + va_start( ap, fmt ); + n = vsnprintf( p, size, fmt, ap ); + va_end( ap ); + if (n == -1) size *= 2; + else if ((size_t)n >= size) size = n + 1; + else return p; + free( p ); + } +} + +/* string array functions */ + +struct strarray +{ + unsigned int count; /* strings in use */ + unsigned int size; /* total allocated size */ + const char **str; +}; + +static const struct strarray empty_strarray; + +static inline void strarray_add( struct strarray *array, const char *str ) +{ + if (array->count == array->size) + { + if (array->size) array->size *= 2; + else array->size = 16; + array->str = xrealloc( array->str, sizeof(array->str[0]) * array->size ); + } + array->str[array->count++] = str; +} + +static inline void strarray_addall( struct strarray *array, struct strarray added ) +{ + unsigned int i; + + for (i = 0; i < added.count; i++) strarray_add( array, added.str[i] ); +} + +static inline int strarray_exists( const struct strarray *array, const char *str ) +{ + unsigned int i; + + for (i = 0; i < array->count; i++) if (!strcmp( array->str[i], str )) return 1; + return 0; +} + +static inline void strarray_add_uniq( struct strarray *array, const char *str ) +{ + if (!strarray_exists( array, str )) strarray_add( array, str ); +} + +static inline void strarray_addall_uniq( struct strarray *array, struct strarray added ) +{ + unsigned int i; + + for (i = 0; i < added.count; i++) strarray_add_uniq( array, added.str[i] ); +} + +static inline struct strarray strarray_fromstring( const char *str, const char *delim ) +{ + struct strarray array = empty_strarray; + char *buf = xstrdup( str ); + const char *tok; + + for (tok = strtok( buf, delim ); tok; tok = strtok( NULL, delim )) + strarray_add( &array, xstrdup( tok )); + free( buf ); + return array; +} + +static inline struct strarray strarray_frompath( const char *path ) +{ + if (!path) return empty_strarray; +#ifdef _WIN32 + return strarray_fromstring( path, ";" ); +#else + return strarray_fromstring( path, ":" ); +#endif +} + +static inline char *strarray_tostring( struct strarray array, const char *sep ) +{ + char *str; + unsigned int i, len = 1 + (array.count - 1) * strlen(sep); + + if (!array.count) return xstrdup(""); + for (i = 0; i < array.count; i++) len += strlen( array.str[i] ); + str = xmalloc( len ); + strcpy( str, array.str[0] ); + for (i = 1; i < array.count; i++) + { + strcat( str, sep ); + strcat( str, array.str[i] ); + } + return str; +} + +static inline void strarray_qsort( struct strarray *array, int (*func)(const char **, const char **) ) +{ + if (array->count) qsort( array->str, array->count, sizeof(*array->str), (void *)func ); +} + +static inline const char *strarray_bsearch( const struct strarray *array, const char *str, + int (*func)(const char **, const char **) ) +{ + char **res = NULL; + + if (array->count) res = bsearch( &str, array->str, array->count, sizeof(*array->str), (void *)func ); + return res ? *res : NULL; +} + +static inline void strarray_trace( struct strarray args ) +{ + unsigned int i; + + for (i = 0; i < args.count; i++) + { + if (strpbrk( args.str[i], " \t\n\r")) printf( "\"%s\"", args.str[i] ); + else printf( "%s", args.str[i] ); + putchar( i < args.count - 1 ? ' ' : '\n' ); + } +} + +static inline int strarray_spawn( struct strarray args ) +{ +#ifdef _WIN32 + strarray_add( &args, NULL ); + return _spawnvp( _P_WAIT, args.str[0], args.str ); +#else + pid_t pid, wret; + int status; + + strarray_add( &args, NULL ); + if (posix_spawnp( &pid, args.str[0], NULL, NULL, (char **)args.str, environ )) + return -1; + + while (pid != (wret = waitpid( pid, &status, 0 ))) + if (wret == -1 && errno != EINTR) break; + + if (pid == wret && WIFEXITED(status)) return WEXITSTATUS(status); + return 255; /* abnormal exit with an abort or an interrupt */ +#endif +} + +static inline char *get_basename( const char *file ) +{ + const char *ret = strrchr( file, '/' ); + return xstrdup( ret ? ret + 1 : file ); +} + +static inline char *get_basename_noext( const char *file ) +{ + char *ext, *ret = get_basename( file ); + if ((ext = strrchr( ret, '.' ))) *ext = 0; + return ret; +} + +static inline char *get_dirname( const char *file ) +{ + const char *end = strrchr( file, '/' ); + if (!end) return xstrdup( "." ); + if (end == file) end++; + return strmake( "%.*s", (int)(end - file), file ); +} + +static inline char *replace_extension( const char *name, const char *old_ext, const char *new_ext ) +{ + int name_len = strlen( name ); + + if (strendswith( name, old_ext )) name_len -= strlen( old_ext ); + return strmake( "%.*s%s", name_len, name, new_ext ); +} + +/* build a path with the relative dir from 'from' to 'dest' appended to base */ +static inline char *build_relative_path( const char *base, const char *from, const char *dest ) +{ + const char *start; + char *ret; + unsigned int dotdots = 0; + + for (;;) + { + while (*from == '/') from++; + while (*dest == '/') dest++; + start = dest; /* save start of next path element */ + if (!*from) break; + + while (*from && *from != '/' && *from == *dest) { from++; dest++; } + if ((!*from || *from == '/') && (!*dest || *dest == '/')) continue; + + do /* count remaining elements in 'from' */ + { + dotdots++; + while (*from && *from != '/') from++; + while (*from == '/') from++; + } + while (*from); + break; + } + + ret = xmalloc( strlen(base) + 3 * dotdots + strlen(start) + 2 ); + strcpy( ret, base ); + while (dotdots--) strcat( ret, "/.." ); + + if (!start[0]) return ret; + strcat( ret, "/" ); + strcat( ret, start ); + return ret; +} + +/* temp files management */ + +extern const char *temp_dir; +extern struct strarray temp_files; + +static inline char *make_temp_dir(void) +{ + unsigned int value = time(NULL) + getpid(); + int count; + char *name; + const char *tmpdir = NULL; + +#ifdef __REACTOS__ +#ifdef _WIN32 + if (!(tmpdir = getenv("TEMP"))) tmpdir = "temp"; +#else + if (!(tmpdir = getenv("TMPDIR"))) tmpdir = "/tmp"; +#endif +#endif + + for (count = 0; count < 0x8000; count++) + { + if (tmpdir) + name = strmake( "%s/tmp%08x", tmpdir, value ); + else + name = strmake( "tmp%08x", value ); + if (!mkdir( name, 0700 )) return name; + value += 7777; + if (errno == EACCES && !tmpdir) + { + if (!(tmpdir = getenv("TMPDIR"))) tmpdir = "/tmp"; + } + free( name ); + } + fprintf( stderr, "failed to create directory for temp files\n" ); + exit(1); +} + +static inline char *make_temp_file( const char *prefix, const char *suffix ) +{ + static unsigned int value; + int fd, count; + char *name; + + if (!temp_dir) temp_dir = make_temp_dir(); + if (!suffix) suffix = ""; + if (!prefix) prefix = "tmp"; + else prefix = get_basename_noext( prefix ); + + for (count = 0; count < 0x8000; count++) + { + name = strmake( "%s/%s-%08x%s", temp_dir, prefix, value++, suffix ); + fd = open( name, O_RDWR | O_CREAT | O_EXCL, 0600 ); + if (fd >= 0) + { +#ifdef HAVE_SIGPROCMASK /* block signals while manipulating the temp files list */ + sigset_t mask_set, old_set; + + sigemptyset( &mask_set ); + sigaddset( &mask_set, SIGHUP ); + sigaddset( &mask_set, SIGTERM ); + sigaddset( &mask_set, SIGINT ); + sigprocmask( SIG_BLOCK, &mask_set, &old_set ); + strarray_add( &temp_files, name ); + sigprocmask( SIG_SETMASK, &old_set, NULL ); +#else + strarray_add( &temp_files, name ); +#endif + close( fd ); + return name; + } + free( name ); + } + fprintf( stderr, "failed to create temp file for %s%s in %s\n", prefix, suffix, temp_dir ); + exit(1); +} + +static inline void remove_temp_files(void) +{ + unsigned int i; + + for (i = 0; i < temp_files.count; i++) if (temp_files.str[i]) unlink( temp_files.str[i] ); + if (temp_dir) rmdir( temp_dir ); +} + + +static inline void init_signals( void (*cleanup)(int) ) +{ + signal( SIGTERM, cleanup ); + signal( SIGINT, cleanup ); +#ifdef SIGHUP + signal( SIGHUP, cleanup ); +#endif +} + + +static inline void *read_file( const char *name, size_t *size ) +{ + struct stat st; + int res, fd; + void *data; + + if ((fd = open( name, O_RDONLY | O_BINARY )) == -1) return NULL; + fstat( fd, &st ); + data = xmalloc( st.st_size ); + res = read( fd, data, st.st_size ); + if (res == -1) + { + free( data ); + data = NULL; + *size = 0; + } + else *size = res; + close( fd ); + return data; +} + + +static inline struct target get_default_target(void) +{ + struct target target; +#ifdef __i386__ + target.cpu = CPU_i386; +#elif defined(__x86_64__) + target.cpu = CPU_x86_64; +#elif defined(__arm__) + target.cpu = CPU_ARM; +#elif defined(__aarch64__) + target.cpu = CPU_ARM64; +#else +#error Unsupported CPU +#endif + +#ifdef __APPLE__ + target.platform = PLATFORM_APPLE; +#elif defined(__ANDROID__) + target.platform = PLATFORM_ANDROID; +#elif defined(__linux__) + target.platform = PLATFORM_LINUX; +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + target.platform = PLATFORM_FREEBSD; +#elif defined(__sun) + target.platform = PLATFORM_SOLARIS; +#elif defined(__CYGWIN__) + target.platform = PLATFORM_CYGWIN; +#elif defined(_WIN32) + target.platform = PLATFORM_MINGW; +#else + target.platform = PLATFORM_UNSPECIFIED; +#endif + + return target; +} + + +static inline unsigned int get_target_ptr_size( struct target target ) +{ + static const unsigned int sizes[] = + { + [CPU_i386] = 4, + [CPU_x86_64] = 8, + [CPU_ARM] = 4, + [CPU_ARM64] = 8, + [CPU_ARM64EC] = 8, + }; + return sizes[target.cpu]; +} + + +static inline void set_target_ptr_size( struct target *target, unsigned int size ) +{ + switch (target->cpu) + { + case CPU_i386: + if (size == 8) target->cpu = CPU_x86_64; + break; + case CPU_x86_64: + if (size == 4) target->cpu = CPU_i386; + break; + case CPU_ARM: + if (size == 8) target->cpu = CPU_ARM64; + break; + case CPU_ARM64: + case CPU_ARM64EC: + if (size == 4) target->cpu = CPU_ARM; + break; + } +} + + +static inline int get_cpu_from_name( const char *name ) +{ + static const struct + { + const char *name; + int cpu; + } cpu_names[] = + { + { "i386", CPU_i386 }, + { "i486", CPU_i386 }, + { "i586", CPU_i386 }, + { "i686", CPU_i386 }, + { "i786", CPU_i386 }, + { "x86_64", CPU_x86_64 }, + { "amd64", CPU_x86_64 }, + { "aarch64", CPU_ARM64 }, + { "arm64ec", CPU_ARM64EC }, + { "arm64", CPU_ARM64 }, + { "arm", CPU_ARM }, + }; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(cpu_names); i++) + if (!strncmp( cpu_names[i].name, name, strlen(cpu_names[i].name) )) return cpu_names[i].cpu; + return -1; +} + + +static inline int get_platform_from_name( const char *name ) +{ + static const struct + { + const char *name; + int platform; + } platform_names[] = + { + { "macos", PLATFORM_APPLE }, + { "darwin", PLATFORM_APPLE }, + { "android", PLATFORM_ANDROID }, + { "linux", PLATFORM_LINUX }, + { "freebsd", PLATFORM_FREEBSD }, + { "solaris", PLATFORM_SOLARIS }, + { "mingw32", PLATFORM_MINGW }, + { "windows-gnu", PLATFORM_MINGW }, + { "winnt", PLATFORM_MINGW }, + { "windows", PLATFORM_WINDOWS }, + { "cygwin", PLATFORM_CYGWIN }, + }; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(platform_names); i++) + if (!strncmp( platform_names[i].name, name, strlen(platform_names[i].name) )) + return platform_names[i].platform; + return -1; +}; + + +static inline const char *get_arch_dir( struct target target ) +{ + static const char *cpu_names[] = + { + [CPU_i386] = "i386", + [CPU_x86_64] = "x86_64", + [CPU_ARM] = "arm", + [CPU_ARM64] = "aarch64", + [CPU_ARM64EC] = "aarch64", + }; + + if (!cpu_names[target.cpu]) return ""; + + switch (target.platform) + { + case PLATFORM_WINDOWS: + case PLATFORM_CYGWIN: + case PLATFORM_MINGW: + return strmake( "/%s-windows", cpu_names[target.cpu] ); + default: + return strmake( "/%s-unix", cpu_names[target.cpu] ); + } +} + +static inline int parse_target( const char *name, struct target *target ) +{ + int res; + char *p, *spec = xstrdup( name ); + + /* target specification is in the form CPU-MANUFACTURER-OS or CPU-MANUFACTURER-KERNEL-OS */ + + /* get the CPU part */ + + if ((p = strchr( spec, '-' ))) + { + *p++ = 0; + if ((res = get_cpu_from_name( spec )) == -1) + { + free( spec ); + return 0; + } + target->cpu = res; + } + else if (!strcmp( spec, "mingw32" )) + { + target->cpu = CPU_i386; + p = spec; + } + else + { + free( spec ); + return 0; + } + + /* get the OS part */ + + target->platform = PLATFORM_UNSPECIFIED; /* default value */ + for (;;) + { + if ((res = get_platform_from_name( p )) != -1) + { + target->platform = res; + break; + } + if (!(p = strchr( p, '-' ))) break; + p++; + } + + free( spec ); + return 1; +} + + +static inline struct target init_argv0_target( const char *argv0 ) +{ + char *name = get_basename( argv0 ); + struct target target; + + if (!strchr( name, '-' ) || !parse_target( name, &target )) + target = get_default_target(); + + free( name ); + return target; +} + + +static inline char *get_bindir( const char *argv0 ) +{ +#ifdef __REACTOS__ + return NULL; +#else +#ifndef _WIN32 + char *dir = NULL; + +#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) \ + || defined(__CYGWIN__) || defined(__MSYS__) + dir = realpath( "/proc/self/exe", NULL ); +#elif defined (__FreeBSD__) || defined(__DragonFly__) + static int pathname[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; + size_t path_size = PATH_MAX; + char *path = xmalloc( path_size ); + if (!sysctl( pathname, ARRAY_SIZE(pathname), path, &path_size, NULL, 0 )) + dir = realpath( path, NULL ); + free( path ); +#endif + if (!dir && !(dir = realpath( argv0, NULL ))) return NULL; + return get_dirname( dir ); +#else + char path[MAX_PATH], *p; + GetModuleFileNameA( NULL, path, ARRAYSIZE(path) ); + for (p = path; *p; p++) if (*p == '\\') *p = '/'; + return get_dirname( path ); +#endif +#endif +} + +#ifdef LIBDIR +static inline const char *get_libdir( const char *bindir ) +{ +#ifdef BINDIR + if (bindir) return build_relative_path( bindir, BINDIR, LIBDIR ); +#endif + return LIBDIR; +} +#endif + +#ifdef DATADIR +static inline const char *get_datadir( const char *bindir ) +{ +#ifdef BINDIR + if (bindir) return build_relative_path( bindir, BINDIR, DATADIR ); +#endif + return DATADIR; +} +#endif + +#ifdef INCLUDEDIR +static inline const char *get_includedir( const char *bindir ) +{ +#ifdef BINDIR + if (bindir) return build_relative_path( bindir, BINDIR, INCLUDEDIR ); +#endif + return INCLUDEDIR; +} +#endif + +static inline const char *get_nlsdir( const char *bindir, const char *srcdir ) +{ + if (bindir && strendswith( bindir, srcdir )) return strmake( "%s/../../nls", bindir ); +#ifdef DATADIR + else + { + const char *datadir = get_datadir( bindir ); + if (datadir) return strmake( "%s/wine/nls", datadir ); + } +#endif + return NULL; +} + + +/* output buffer management */ + +extern unsigned char *output_buffer; +extern size_t output_buffer_pos; +extern size_t output_buffer_size; + +static inline void check_output_buffer_space( size_t size ) +{ + if (output_buffer_pos + size >= output_buffer_size) + { + output_buffer_size = max( output_buffer_size * 2, output_buffer_pos + size ); + output_buffer = xrealloc( output_buffer, output_buffer_size ); + } +} + +static inline void init_output_buffer(void) +{ + output_buffer_size = 1024; + output_buffer_pos = 0; + output_buffer = xmalloc( output_buffer_size ); +} + +static inline void put_data( const void *data, size_t size ) +{ + check_output_buffer_space( size ); + memcpy( output_buffer + output_buffer_pos, data, size ); + output_buffer_pos += size; +} + +static inline void put_byte( unsigned char val ) +{ + check_output_buffer_space( 1 ); + output_buffer[output_buffer_pos++] = val; +} + +static inline void put_word( unsigned short val ) +{ + check_output_buffer_space( 2 ); + output_buffer[output_buffer_pos++] = val; + output_buffer[output_buffer_pos++] = val >> 8; +} + +static inline void put_dword( unsigned int val ) +{ + check_output_buffer_space( 4 ); + output_buffer[output_buffer_pos++] = val; + output_buffer[output_buffer_pos++] = val >> 8; + output_buffer[output_buffer_pos++] = val >> 16; + output_buffer[output_buffer_pos++] = val >> 24; +} + +static inline void put_qword( unsigned int val ) +{ + put_dword( val ); + put_dword( 0 ); +} + +static inline void align_output( unsigned int align ) +{ + size_t size = align - (output_buffer_pos % align); + + if (size == align) return; + check_output_buffer_space( size ); + memset( output_buffer + output_buffer_pos, 0, size ); + output_buffer_pos += size; +} + +static inline void flush_output_buffer( const char *name ) +{ + int fd = open( name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666 ); + + if (fd == -1 || write( fd, output_buffer, output_buffer_pos ) != output_buffer_pos) + { + perror( name ); + exit(1); + } + close( fd ); + free( output_buffer ); +} + +/* command-line option parsing */ +/* partly based on the Glibc getopt() implementation */ + +struct long_option +{ + const char *name; + int has_arg; + int val; +}; + +static inline struct strarray parse_options( int argc, char **argv, const char *short_opts, + const struct long_option *long_opts, int long_only, + void (*callback)( int, char* ) ) +{ + struct strarray ret = empty_strarray; + const char *flag; + char *start, *end; + int i; + +#define OPT_ERR(fmt) { callback( '?', strmake( fmt, argv[i] )); continue; } + + for (i = 1; i < argc; i++) + { + if (argv[i][0] != '-' || !argv[i][1]) /* not an option */ + { + strarray_add( &ret, argv[i] ); + continue; + } + if (!strcmp( argv[i], "--" )) + { + /* add remaining args */ + while (++i < argc) strarray_add( &ret, argv[i] ); + break; + } + start = argv[i] + 1 + (argv[i][1] == '-'); + + if (argv[i][1] == '-' || (long_only && (argv[i][2] || !strchr( short_opts, argv[i][1] )))) + { + /* handle long option */ + const struct long_option *opt, *found = NULL; + int count = 0; + + if (!(end = strchr( start, '=' ))) end = start + strlen(start); + for (opt = long_opts; opt && opt->name; opt++) + { + if (strncmp( opt->name, start, end - start )) continue; + if (!opt->name[end - start]) /* exact match */ + { + found = opt; + count = 1; + break; + } + if (!found) + { + found = opt; + count++; + } + else if (long_only || found->has_arg != opt->has_arg || found->val != opt->val) + { + count++; + } + } + + if (count > 1) OPT_ERR( "option '%s' is ambiguous" ); + + if (found) + { + if (*end) + { + if (!found->has_arg) OPT_ERR( "argument not allowed in '%s'" ); + end++; /* skip '=' */ + } + else if (found->has_arg == 1) + { + if (i == argc - 1) OPT_ERR( "option '%s' requires an argument" ); + end = argv[++i]; + } + else end = NULL; + + callback( found->val, end ); + continue; + } + if (argv[i][1] == '-' || !long_only || !strchr( short_opts, argv[i][1] )) + OPT_ERR( "unrecognized option '%s'" ); + } + + /* handle short option */ + for ( ; *start; start++) + { + if (!(flag = strchr( short_opts, *start ))) OPT_ERR( "invalid option '%s'" ); + if (flag[1] == ':') + { + end = start + 1; + if (!*end) end = NULL; + if (flag[2] != ':' && !end) + { + if (i == argc - 1) OPT_ERR( "option '%s' requires an argument" ); + end = argv[++i]; + } + callback( *start, end ); + break; + } + callback( *start, NULL ); + } + } + return ret; +#undef OPT_ERR +} + +#endif /* __WINE_TOOLS_H */ diff --git a/sdk/tools/widl/CMakeLists.txt b/sdk/tools/widl/CMakeLists.txt index 4346c14a188..b2df9c9c52f 100644 --- a/sdk/tools/widl/CMakeLists.txt +++ b/sdk/tools/widl/CMakeLists.txt @@ -11,10 +11,11 @@ if(MSVC) endif() FLEX_TARGET(p_scanner parser.l ${CMAKE_CURRENT_BINARY_DIR}/parser.yy.c) -BISON_TARGET(p_parser parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.tab.c COMPILE_FLAGS "-p parser_") +BISON_TARGET(p_parser parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.tab.c) ADD_FLEX_BISON_DEPENDENCY(p_scanner p_parser) list(APPEND SOURCE + attribute.c client.c expr.c hash.c @@ -35,7 +36,8 @@ list(APPEND SOURCE ../port/getopt1.c ../port/mkstemps.c) -add_definitions(-DINT16=SHORT -DLANG_SCOTTISH_GAELIC=0x91) +add_definitions(-DINT16=SHORT -DLANG_SCOTTISH_GAELIC=0x91 -DINCLUDEDIR="unused" -DLIBDIR="unused") +include_directories(${REACTOS_SOURCE_DIR}/sdk/tools/wpp/) add_host_tool(widl ${SOURCE}) target_link_libraries(widl PRIVATE host_includes wpphost) @@ -49,5 +51,8 @@ if(MSVC) # Disable warning "'=': conversion from 'a' to 'b', possible loss of data" target_compile_options(widl PRIVATE "/wd4244") + # Disable warning "warning C4090: 'function': different 'const' qualifiers" + target_compile_options(widl PRIVATE "/wd4090") + target_compile_options(widl PRIVATE "-WX") endif() diff --git a/sdk/tools/widl/attribute.c b/sdk/tools/widl/attribute.c new file mode 100644 index 00000000000..bcd804e272f --- /dev/null +++ b/sdk/tools/widl/attribute.c @@ -0,0 +1,540 @@ +/* + * Copyright 2002 Ove Kaaven + * Copyright 2006-2008 Robert Shearman + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include "widl.h" +#include "typetree.h" + +#include "parser.tab.h" + +attr_t *attr_int( struct location where, enum attr_type attr_type, unsigned int val ) +{ + attr_t *a = xmalloc( sizeof(attr_t) ); + a->where = where; + a->type = attr_type; + a->u.ival = val; + return a; +} + +attr_t *attr_ptr( struct location where, enum attr_type attr_type, void *val ) +{ + attr_t *a = xmalloc( sizeof(attr_t) ); + a->where = where; + a->type = attr_type; + a->u.pval = val; + return a; +} + +int is_attr( const attr_list_t *list, enum attr_type attr_type ) +{ + const attr_t *attr; + if (!list) return 0; + LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry ) + if (attr->type == attr_type) return 1; + return 0; +} + +int is_ptrchain_attr( const var_t *var, enum attr_type attr_type ) +{ + type_t *type = var->declspec.type; + if (is_attr( var->attrs, attr_type )) return 1; + for (;;) + { + if (is_attr( type->attrs, attr_type )) return 1; + else if (type_is_alias( type )) type = type_alias_get_aliasee_type( type ); + else if (type_is_ptr( type )) type = type_pointer_get_ref_type( type ); + else return 0; + } +} + +int is_aliaschain_attr( const type_t *type, enum attr_type attr_type ) +{ + const type_t *t = type; + for (;;) + { + if (is_attr( t->attrs, attr_type )) return 1; + else if (type_is_alias( t )) t = type_alias_get_aliasee_type( t ); + else return 0; + } +} + +unsigned int get_attrv( const attr_list_t *list, enum attr_type attr_type ) +{ + const attr_t *attr; + if (!list) return 0; + LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry ) + if (attr->type == attr_type) return attr->u.ival; + return 0; +} + +void *get_attrp( const attr_list_t *list, enum attr_type attr_type ) +{ + const attr_t *attr; + if (!list) return NULL; + LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry ) + if (attr->type == attr_type) return attr->u.pval; + return NULL; +} + +void *get_aliaschain_attrp( const type_t *type, enum attr_type attr_type ) +{ + for (;;) + { + if (is_attr( type->attrs, attr_type )) return get_attrp( type->attrs, attr_type ); + if (!type_is_alias( type )) return NULL; + type = type_alias_get_aliasee_type( type ); + } +} + +struct allowed_attr +{ + unsigned int dce_compatible : 1; + unsigned int acf : 1; + unsigned int multiple : 1; + + unsigned int on_interface : 1; + unsigned int on_function : 1; + unsigned int on_arg : 1; + unsigned int on_type : 1; + unsigned int on_enum : 1; + unsigned int on_enum_member : 1; + unsigned int on_struct : 2; + unsigned int on_union : 1; + unsigned int on_field : 1; + unsigned int on_library : 1; + unsigned int on_dispinterface : 1; + unsigned int on_module : 1; + unsigned int on_coclass : 1; + unsigned int on_apicontract : 1; + unsigned int on_runtimeclass : 1; + const char *display_name; +}; + +struct allowed_attr allowed_attr[] = +{ + /* attr { D ACF M I Fn ARG T En Enm St Un Fi L DI M C AC R } */ + /* ATTR_ACTIVATABLE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "activatable" }, + /* ATTR_AGGREGATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "aggregatable" }, + /* ATTR_ALLOCATE */ { 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "allocate" }, + /* ATTR_ANNOTATION */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "annotation" }, + /* ATTR_APPOBJECT */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "appobject" }, + /* ATTR_ASYNC */ { 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "async" }, + /* ATTR_ASYNCUUID */ { 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "async_uuid" }, + /* ATTR_AUTO_HANDLE */ { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "auto_handle" }, + /* ATTR_BINDABLE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "bindable" }, + /* ATTR_BROADCAST */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "broadcast" }, + /* ATTR_CALLAS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "call_as" }, + /* ATTR_CALLCONV */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + /* ATTR_CASE */ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "case" }, + /* ATTR_CODE */ { 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "code" }, + /* ATTR_COMMSTATUS */ { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "comm_status" }, + /* ATTR_COMPOSABLE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "composable" }, + /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" }, + /* ATTR_CONTRACT */ { 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, "contract" }, + /* ATTR_CONTRACTVERSION */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "contractversion" }, + /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, "control" }, + /* ATTR_CUSTOM */ { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, "custom" }, + /* ATTR_DECODE */ { 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "decode" }, + /* ATTR_DEFAULT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, "default" }, + /* ATTR_DEFAULT_OVERLOAD */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default_overload" }, + /* ATTR_DEFAULTBIND */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultbind" }, + /* ATTR_DEFAULTCOLLELEM */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultcollelem" }, + /* ATTR_DEFAULTVALUE */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultvalue" }, + /* ATTR_DEFAULTVTABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "defaultvtable" }, + /* ATTR_DEPRECATED */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "deprecated" }, + /* ATTR_DISABLECONSISTENCYCHECK */{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "disable_consistency_check" }, + /* ATTR_DISPINTERFACE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, NULL }, + /* ATTR_DISPLAYBIND */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "displaybind" }, + /* ATTR_DLLNAME */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "dllname" }, + /* ATTR_DUAL */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "dual" }, + /* ATTR_ENABLEALLOCATE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "enable_allocate" }, + /* ATTR_ENCODE */ { 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "encode" }, + /* ATTR_ENDPOINT */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "endpoint" }, + /* ATTR_ENTRY */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "entry" }, + /* ATTR_EVENTADD */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "eventadd" }, + /* ATTR_EVENTREMOVE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "eventremove" }, + /* ATTR_EXCLUSIVETO */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "exclusive_to" }, + /* ATTR_EXPLICIT_HANDLE */ { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "explicit_handle" }, + /* ATTR_FAULTSTATUS */ { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "fault_status" }, + /* ATTR_FLAGS */ { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "flags" }, + /* ATTR_FORCEALLOCATE */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "force_allocate" }, + /* ATTR_HANDLE */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "handle" }, + /* ATTR_HELPCONTEXT */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "helpcontext" }, + /* ATTR_HELPFILE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "helpfile" }, + /* ATTR_HELPSTRING */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "helpstring" }, + /* ATTR_HELPSTRINGCONTEXT */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "helpstringcontext" }, + /* ATTR_HELPSTRINGDLL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "helpstringdll" }, + /* ATTR_HIDDEN */ { 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, "hidden" }, + /* ATTR_ID */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, "id" }, + /* ATTR_IDEMPOTENT */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "idempotent" }, + /* ATTR_IGNORE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "ignore" }, + /* ATTR_IIDIS */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "iid_is" }, + /* ATTR_IMMEDIATEBIND */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "immediatebind" }, + /* ATTR_IMPLICIT_HANDLE */ { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "implicit_handle" }, + /* ATTR_IN */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" }, + /* ATTR_INPUTSYNC */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" }, + /* ATTR_LENGTHIS */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "length_is" }, + /* ATTR_LIBLCID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "lcid" }, + /* ATTR_LICENSED */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "licensed" }, + /* ATTR_LOCAL */ { 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "local" }, + /* ATTR_MARSHALING_BEHAVIOR */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "marshaling_behavior" }, + /* ATTR_MAYBE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "maybe" }, + /* ATTR_MESSAGE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "message" }, + /* ATTR_NOCODE */ { 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nocode" }, + /* ATTR_NONBROWSABLE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonbrowsable" }, + /* ATTR_NONCREATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "noncreatable" }, + /* ATTR_NONEXTENSIBLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonextensible" }, + /* ATTR_NOTIFY */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify" }, + /* ATTR_NOTIFYFLAG */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify_flag" }, + /* ATTR_OBJECT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "object" }, + /* ATTR_ODL */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "odl" }, + /* ATTR_OLEAUTOMATION */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "oleautomation" }, + /* ATTR_OPTIMIZE */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optimize" }, + /* ATTR_OPTIONAL */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optional" }, + /* ATTR_OUT */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "out" }, + /* ATTR_OVERLOAD */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "overload" }, + /* ATTR_PARAMLCID */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "lcid" }, + /* ATTR_PARTIALIGNORE */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "partial_ignore" }, + /* ATTR_POINTERDEFAULT */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "pointer_default" }, + /* ATTR_POINTERTYPE */ { 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "ref, unique or ptr" }, + /* ATTR_PROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "progid" }, + /* ATTR_PROPGET */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propget" }, + /* ATTR_PROPPUT */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propput" }, + /* ATTR_PROPPUTREF */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propputref" }, + /* ATTR_PROTECTED */ { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "protected" }, + /* ATTR_PROXY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "proxy" }, + /* ATTR_PUBLIC */ { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "public" }, + /* ATTR_RANGE */ { 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "range" }, + /* ATTR_READONLY */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "readonly" }, + /* ATTR_REPRESENTAS */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "represent_as" }, + /* ATTR_REQUESTEDIT */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "requestedit" }, + /* ATTR_RESTRICTED */ { 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, "restricted" }, + /* ATTR_RETVAL */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "retval" }, + /* ATTR_SIZEIS */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "size_is" }, + /* ATTR_SOURCE */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "source" }, + /* ATTR_STATIC */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "static" }, + /* ATTR_STRICTCONTEXTHANDLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "strict_context_handle" }, + /* ATTR_STRING */ { 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "string" }, + /* ATTR_SWITCHIS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "switch_is" }, + /* ATTR_SWITCHTYPE */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "switch_type" }, + /* ATTR_THREADING */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, "threading" }, + /* ATTR_TRANSMITAS */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "transmit_as" }, + /* ATTR_UIDEFAULT */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "uidefault" }, + /* ATTR_USESGETLASTERROR */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "usesgetlasterror" }, + /* ATTR_USERMARSHAL */ { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "user_marshal" }, + /* ATTR_UUID */ { 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, "uuid" }, + /* ATTR_V1ENUM */ { 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "v1_enum" }, + /* ATTR_VARARG */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "vararg" }, + /* ATTR_VERSION */ { 1, 0, 0, 1, 0, 0, 1, 1, 0, 2, 0, 0, 1, 0, 1, 1, 0, 1, "version" }, + /* ATTR_VIPROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "vi_progid" }, + /* ATTR_WIREMARSHAL */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "wire_marshal" }, +}; + +static const char *get_attr_display_name( enum attr_type attr_type ) +{ + return allowed_attr[attr_type].display_name; +} + +attr_list_t *append_attr( attr_list_t *list, attr_t *attr ) +{ + attr_t *attr_existing; + if (!attr) return list; + if (!list) + { + list = xmalloc( sizeof(*list) ); + list_init( list ); + } + if (!allowed_attr[attr->type].multiple) + { + LIST_FOR_EACH_ENTRY( attr_existing, list, attr_t, entry ) + { + if (attr_existing->type != attr->type) continue; + warning_at( &attr->where, "duplicate attribute %s\n", get_attr_display_name( attr->type ) ); + /* use the last attribute, like MIDL does */ + list_remove( &attr_existing->entry ); + break; + } + } + list_add_tail( list, &attr->entry ); + return list; +} + +attr_list_t *append_attr_list( attr_list_t *new_list, attr_list_t *old_list ) +{ + struct list *entry; + + if (!old_list) return new_list; + + while ((entry = list_head( old_list ))) + { + attr_t *attr = LIST_ENTRY( entry, attr_t, entry ); + list_remove( entry ); + new_list = append_attr( new_list, attr ); + } + return new_list; +} + +attr_list_t *append_attribs( attr_list_t *l1, attr_list_t *l2 ) +{ + if (!l2) return l1; + if (!l1 || l1 == l2) return l2; + list_move_tail( l1, l2 ); + return l1; +} + +attr_list_t *map_attrs( const attr_list_t *list, map_attrs_filter_t filter ) +{ + attr_list_t *new_list; + const attr_t *attr; + attr_t *new_attr; + + if (!list) return NULL; + + new_list = xmalloc( sizeof(*list) ); + list_init( new_list ); + LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry ) + { + if (filter && !filter( new_list, attr )) continue; + new_attr = xmalloc( sizeof(*new_attr) ); + *new_attr = *attr; + list_add_tail( new_list, &new_attr->entry ); + } + return new_list; +} + +attr_list_t *move_attr( attr_list_t *dst, attr_list_t *src, enum attr_type type ) +{ + attr_t *attr; + if (!src) return dst; + LIST_FOR_EACH_ENTRY( attr, src, attr_t, entry ) + { + if (attr->type == type) + { + list_remove( &attr->entry ); + return append_attr( dst, attr ); + } + } + return dst; +} + +attr_list_t *check_apicontract_attrs( const char *name, attr_list_t *attrs ) +{ + const attr_t *attr; + if (!attrs) return NULL; + LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry ) + { + if (!allowed_attr[attr->type].on_apicontract) + error_at( &attr->where, "inapplicable attribute %s for apicontract %s\n", + allowed_attr[attr->type].display_name, name ); + } + return attrs; +} + +attr_list_t *check_coclass_attrs( const char *name, attr_list_t *attrs ) +{ + const attr_t *attr; + if (!attrs) return NULL; + LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry ) + { + if (!allowed_attr[attr->type].on_coclass) + error_at( &attr->where, "inapplicable attribute %s for coclass %s\n", + allowed_attr[attr->type].display_name, name ); + } + return attrs; +} + +attr_list_t *check_dispiface_attrs( const char *name, attr_list_t *attrs ) +{ + const attr_t *attr; + if (!attrs) return NULL; + LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry ) + { + if (!allowed_attr[attr->type].on_dispinterface) + error_at( &attr->where, "inapplicable attribute %s for dispinterface %s\n", + allowed_attr[attr->type].display_name, name ); + } + return attrs; +} + +attr_list_t *check_enum_attrs( attr_list_t *attrs ) +{ + const attr_t *attr; + if (!attrs) return NULL; + LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry ) + { + if (!allowed_attr[attr->type].on_enum) + error_at( &attr->where, "inapplicable attribute %s for enum\n", + allowed_attr[attr->type].display_name ); + } + return attrs; +} + +attr_list_t *check_enum_member_attrs( attr_list_t *attrs ) +{ + const attr_t *attr; + if (!attrs) return NULL; + LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry ) + { + if (!allowed_attr[attr->type].on_enum_member) + error_at( &attr->where, "inapplicable attribute %s for enum member\n", + allowed_attr[attr->type].display_name ); + } + return attrs; +} + +attr_list_t *check_field_attrs( const char *name, attr_list_t *attrs ) +{ + const attr_t *attr; + if (!attrs) return NULL; + LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry ) + { + if (!allowed_attr[attr->type].on_field) + error_at( &attr->where, "inapplicable attribute %s for field %s\n", + allowed_attr[attr->type].display_name, name ); + } + return attrs; +} + +attr_list_t *check_function_attrs( const char *name, attr_list_t *attrs ) +{ + const attr_t *attr; + if (!attrs) return NULL; + LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry ) + { + if (!allowed_attr[attr->type].on_function) + error_at( &attr->where, "inapplicable attribute %s for function %s\n", + allowed_attr[attr->type].display_name, name ); + } + return attrs; +} + +attr_list_t *check_interface_attrs( const char *name, attr_list_t *attrs ) +{ + const attr_t *attr; + if (!attrs) return NULL; + LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry ) + { + if (!allowed_attr[attr->type].on_interface) + error_at( &attr->where, "inapplicable attribute %s for interface %s\n", + allowed_attr[attr->type].display_name, name ); + if (attr->type == ATTR_IMPLICIT_HANDLE) + { + const var_t *var = attr->u.pval; + if (type_get_type( var->declspec.type ) == TYPE_BASIC && + type_basic_get_type( var->declspec.type ) == TYPE_BASIC_HANDLE) + continue; + if (is_aliaschain_attr( var->declspec.type, ATTR_HANDLE )) continue; + error_at( &attr->where, "attribute %s requires a handle type in interface %s\n", + allowed_attr[attr->type].display_name, name ); + } + } + return attrs; +} + +attr_list_t *check_library_attrs( const char *name, attr_list_t *attrs ) +{ + const attr_t *attr; + if (!attrs) return NULL; + LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry ) + { + if (!allowed_attr[attr->type].on_library) + error_at( &attr->where, "inapplicable attribute %s for library %s\n", + allowed_attr[attr->type].display_name, name ); + } + return attrs; +} + +attr_list_t *check_module_attrs( const char *name, attr_list_t *attrs ) +{ + const attr_t *attr; + if (!attrs) return NULL; + LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry ) + { + if (!allowed_attr[attr->type].on_module) + error_at( &attr->where, "inapplicable attribute %s for module %s\n", + allowed_attr[attr->type].display_name, name ); + } + return attrs; +} + +attr_list_t *check_runtimeclass_attrs( const char *name, attr_list_t *attrs ) +{ + const attr_t *attr; + if (!attrs) return NULL; + LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry ) + { + if (!allowed_attr[attr->type].on_runtimeclass) + error_at( &attr->where, "inapplicable attribute %s for runtimeclass %s\n", + allowed_attr[attr->type].display_name, name ); + } + return attrs; +} + +attr_list_t *check_struct_attrs( attr_list_t *attrs ) +{ + int mask = winrt_mode ? 3 : 1; + const attr_t *attr; + if (!attrs) return NULL; + LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry ) + { + if (!(allowed_attr[attr->type].on_struct & mask)) + error_at( &attr->where, "inapplicable attribute %s for struct\n", + allowed_attr[attr->type].display_name ); + } + return attrs; +} + +attr_list_t *check_typedef_attrs( attr_list_t *attrs ) +{ + const attr_t *attr; + if (!attrs) return NULL; + LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry ) + { + if (!allowed_attr[attr->type].on_type) + error_at( &attr->where, "inapplicable attribute %s for typedef\n", + allowed_attr[attr->type].display_name ); + } + return attrs; +} + +attr_list_t *check_union_attrs( attr_list_t *attrs ) +{ + const attr_t *attr; + if (!attrs) return NULL; + LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry ) + { + if (!allowed_attr[attr->type].on_union) + error_at( &attr->where, "inapplicable attribute %s for union\n", + allowed_attr[attr->type].display_name ); + } + return attrs; +} + +void check_arg_attrs( const var_t *arg ) +{ + const attr_t *attr; + if (!arg->attrs) return; + LIST_FOR_EACH_ENTRY( attr, arg->attrs, const attr_t, entry ) + { + if (!allowed_attr[attr->type].on_arg) + error_at( &attr->where, "inapplicable attribute %s for argument %s\n", + allowed_attr[attr->type].display_name, arg->name ); + } +} diff --git a/sdk/tools/widl/client.c b/sdk/tools/widl/client.c index 30b0dce5b8a..795e3ba2104 100644 --- a/sdk/tools/widl/client.c +++ b/sdk/tools/widl/client.c @@ -19,13 +19,9 @@ */ #include "config.h" -#include "wine/port.h" - + #include #include -#ifdef HAVE_UNISTD_H -# include -#endif #include #include @@ -52,17 +48,16 @@ static void print_client( const char *format, ... ) static void write_client_func_decl( const type_t *iface, const var_t *func ) { - const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV); - const var_list_t *args = type_get_function_args(func->type); - type_t *rettype = type_function_get_rettype(func->type); + const char *callconv = get_attrp(func->declspec.type->attrs, ATTR_CALLCONV); + const var_list_t *args = type_function_get_args(func->declspec.type); + const decl_spec_t *rettype = type_function_get_ret(func->declspec.type); if (!callconv) callconv = "__cdecl"; write_type_decl_left(client, rettype); fprintf(client, " %s ", callconv); fprintf(client, "%s%s(\n", prefix_client, get_name(func)); indent++; - if (args) - write_args(client, args, iface->name, 0, TRUE); + if (args) write_args(client, args, iface->name, 0, TRUE, NAME_DEFAULT); else print_client("void"); fprintf(client, ")\n"); @@ -74,9 +69,9 @@ static void write_function_stub( const type_t *iface, const var_t *func, { unsigned char explicit_fc, implicit_fc; int has_full_pointer = is_full_pointer_function(func); - var_t *retval = type_function_get_retval(func->type); + var_t *retval = type_function_get_retval(func->declspec.type); const var_t *handle_var = get_func_handle_var( iface, func, &explicit_fc, &implicit_fc ); - int has_ret = !is_void(retval->type); + int has_ret = !is_void(retval->declspec.type); if (is_interpreted_func( iface, func )) { @@ -97,7 +92,7 @@ static void write_function_stub( const type_t *iface, const var_t *func, print_client("RPC_BINDING_HANDLE _Handle;\n"); } - if (has_ret && decl_indirect(retval->type)) + if (has_ret && decl_indirect(retval->declspec.type)) { print_client("void *_p_%s;\n", retval->name); } @@ -111,6 +106,7 @@ static void write_function_stub( const type_t *iface, const var_t *func, if (has_full_pointer) write_full_pointer_free(client, indent, func); + if (interpreted_mode) print_client("NdrCorrelationFree(&__frame->_StubMsg);\n"); print_client("NdrFreeBuffer(&__frame->_StubMsg);\n"); if (explicit_fc == FC_BIND_GENERIC) @@ -136,9 +132,10 @@ static void write_function_stub( const type_t *iface, const var_t *func, if (has_ret) { print_client("%s", ""); - write_type_decl(client, retval->type, retval->name); + write_type_decl(client, &retval->declspec, retval->name); fprintf(client, ";\n"); } + if (interpreted_mode) print_client("ULONG _NdrCorrCache[256];\n"); print_client("RPC_MESSAGE _RpcMessage;\n"); if (handle_var) @@ -147,7 +144,7 @@ static void write_function_stub( const type_t *iface, const var_t *func, if (explicit_fc == FC_BIND_GENERIC) print_client("__frame->%s = %s;\n", handle_var->name, handle_var->name ); } - if (has_ret && decl_indirect(retval->type)) + if (has_ret && decl_indirect(retval->declspec.type)) { print_client("__frame->_p_%s = &%s;\n", retval->name, retval->name); } @@ -194,7 +191,7 @@ static void write_function_stub( const type_t *iface, const var_t *func, /* if the context_handle attribute appears in the chain of types * without pointers being followed, then the context handle must * be direct, otherwise it is a pointer */ - int is_ch_ptr = !is_aliaschain_attr(handle_var->type, ATTR_CONTEXTHANDLE); + int is_ch_ptr = !is_aliaschain_attr(handle_var->declspec.type, ATTR_CONTEXTHANDLE); print_client("if (%s%s != 0)\n", is_ch_ptr ? "*" : "", handle_var->name); indent++; print_client("__frame->_Handle = NDRCContextBinding(%s%s);\n", @@ -218,6 +215,8 @@ static void write_function_stub( const type_t *iface, const var_t *func, } break; } + if (interpreted_mode) + print_client( "NdrCorrelationInitialize(&__frame->_StubMsg, _NdrCorrCache, sizeof(_NdrCorrCache), 0);\n" ); write_remoting_arguments(client, indent, func, "", PASS_IN, PHASE_BUFFERSIZE); @@ -257,9 +256,9 @@ static void write_function_stub( const type_t *iface, const var_t *func, /* unmarshal return value */ if (has_ret) { - if (decl_indirect(retval->type)) + if (decl_indirect(retval->declspec.type)) print_client("MIDL_memset(&%s, 0, sizeof(%s));\n", retval->name, retval->name); - else if (is_ptr(retval->type) || is_array(retval->type)) + else if (is_ptr(retval->declspec.type) || is_array(retval->declspec.type)) print_client("%s = 0;\n", retval->name); write_remoting_arguments(client, indent, func, "", PASS_RETURN, PHASE_UNMARSHAL); } @@ -290,8 +289,7 @@ static void write_function_stub( const type_t *iface, const var_t *func, static void write_serialize_function(FILE *file, const type_t *type, const type_t *iface, const char *func_name, const char *ret_type) { - enum stub_mode mode = get_stub_mode(); - static int emited_pickling_info; + static int emitted_pickling_info; if (iface && !type->typestring_offset) { @@ -301,7 +299,7 @@ static void write_serialize_function(FILE *file, const type_t *type, const type_ return; } - if (!emited_pickling_info && iface && mode != MODE_Os) + if (!emitted_pickling_info && iface && interpreted_mode) { fprintf(file, "static const MIDL_TYPE_PICKLING_INFO __MIDL_TypePicklingInfo =\n"); fprintf(file, "{\n"); @@ -312,7 +310,7 @@ static void write_serialize_function(FILE *file, const type_t *type, const type_ fprintf(file, " 0\n"); fprintf(file, "};\n"); fprintf(file, "\n"); - emited_pickling_info = 1; + emitted_pickling_info = 1; } /* FIXME: Assuming explicit handle */ @@ -323,9 +321,9 @@ static void write_serialize_function(FILE *file, const type_t *type, const type_ fprintf(file, "{\n"); fprintf(file, " %sNdrMesType%s%s(\n", ret_type ? "return " : "", func_name, - mode != MODE_Os ? "2" : ""); + interpreted_mode ? "2" : ""); fprintf(file, " IDL_handle,\n"); - if (mode != MODE_Os) + if (interpreted_mode) fprintf(file, " (MIDL_TYPE_PICKLING_INFO*)&__MIDL_TypePicklingInfo,\n"); fprintf(file, " &%s_StubDesc,\n", iface->name); fprintf(file, " (PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u],\n", @@ -365,8 +363,8 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset) case STMT_DECLARATION: { const var_t *func = stmt->u.var; - if (stmt->u.var->stgclass != STG_NONE - || type_get_type_detect_alias(stmt->u.var->type) != TYPE_FUNCTION) + if (stmt->u.var->declspec.stgclass != STG_NONE + || type_get_type_detect_alias(stmt->u.var->declspec.type) != TYPE_FUNCTION) continue; write_function_stub( iface, func, method_count++, *proc_offset ); *proc_offset += get_size_procformatstring_func( iface, func ); @@ -374,9 +372,9 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset) } case STMT_TYPEDEF: { - const type_list_t *type_entry; - for (type_entry = stmt->u.type_list; type_entry; type_entry = type_entry->next) - write_serialize_functions(client, type_entry->type, iface); + typeref_t *ref; + if (stmt->u.type_list) LIST_FOR_EACH_ENTRY(ref, stmt->u.type_list, typeref_t, entry) + write_serialize_functions(client, ref->type, iface); break; } default: @@ -423,9 +421,9 @@ static void write_stubdescriptor(type_t *iface, int expr_eval_routines) print_client("0,\n"); print_client("__MIDL_TypeFormatString.Format,\n"); print_client("1, /* -error bounds_check flag */\n"); - print_client("0x%x, /* Ndr library version */\n", get_stub_mode() == MODE_Oif ? 0x50002 : 0x10001); + print_client("0x%x, /* Ndr library version */\n", interpreted_mode ? 0x50002 : 0x10001); print_client("0,\n"); - print_client("0x50100a4, /* MIDL Version 5.1.164 */\n"); + print_client("0x50200ca, /* MIDL Version 5.2.202 */\n"); print_client("0,\n"); print_client("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines"); print_client("0, /* notify & notify_flag routine table */\n"); @@ -442,7 +440,7 @@ static void write_stubdescriptor(type_t *iface, int expr_eval_routines) static void write_clientinterfacedecl(type_t *iface) { unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION); - const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); + const struct uuid *uuid = get_attrp(iface->attrs, ATTR_UUID); const str_list_t *endpoints = get_attrp(iface->attrs, ATTR_ENDPOINT); if (endpoints) write_endpoints( client, iface->name, endpoints ); @@ -473,10 +471,10 @@ static void write_clientinterfacedecl(type_t *iface) indent--; print_client("};\n"); if (old_names) - print_client("RPC_IF_HANDLE %s_ClientIfHandle DECLSPEC_HIDDEN = (RPC_IF_HANDLE)& %s___RpcClientInterface;\n", + print_client("RPC_IF_HANDLE %s_ClientIfHandle = (RPC_IF_HANDLE)& %s___RpcClientInterface;\n", iface->name, iface->name); else - print_client("RPC_IF_HANDLE %s%s_v%d_%d_c_ifspec DECLSPEC_HIDDEN = (RPC_IF_HANDLE)& %s___RpcClientInterface;\n", + print_client("RPC_IF_HANDLE %s%s_v%d_%d_c_ifspec = (RPC_IF_HANDLE)& %s___RpcClientInterface;\n", prefix_client, iface->name, MAJORVERSION(ver), MINORVERSION(ver), iface->name); fprintf(client, "\n"); } @@ -488,7 +486,7 @@ static void write_implicithandledecl(type_t *iface) if (implicit_handle) { - write_type_decl( client, implicit_handle->type, implicit_handle->name ); + write_type_decl(client, &implicit_handle->declspec, implicit_handle->name); fprintf(client, ";\n\n"); } } @@ -505,10 +503,6 @@ static void init_client(void) print_client( "\n"); print_client("#include \"%s\"\n", header_name); print_client( "\n"); - print_client( "#ifndef DECLSPEC_HIDDEN\n"); - print_client( "#define DECLSPEC_HIDDEN\n"); - print_client( "#endif\n"); - print_client( "\n"); } @@ -532,19 +526,19 @@ static void write_client_ifaces(const statement_list_t *stmts, int expr_eval_rou LIST_FOR_EACH_ENTRY(stmt2, type_iface_get_stmts(iface), const statement_t, entry) { - if (stmt2->type == STMT_DECLARATION && stmt2->u.var->stgclass == STG_NONE && - type_get_type_detect_alias(stmt2->u.var->type) == TYPE_FUNCTION) + if (stmt2->type == STMT_DECLARATION && stmt2->u.var->declspec.stgclass == STG_NONE && + type_get_type_detect_alias(stmt2->u.var->declspec.type) == TYPE_FUNCTION) { needs_stub = 1; break; } if (stmt2->type == STMT_TYPEDEF) { - const type_list_t *type_entry; - for (type_entry = stmt2->u.type_list; type_entry; type_entry = type_entry->next) + typeref_t *ref; + if (stmt2->u.type_list) LIST_FOR_EACH_ENTRY(ref, stmt2->u.type_list, typeref_t, entry) { - if (is_attr(type_entry->type->attrs, ATTR_ENCODE) - || is_attr(type_entry->type->attrs, ATTR_DECODE)) + if (is_attr(ref->type->attrs, ATTR_ENCODE) + || is_attr(ref->type->attrs, ATTR_DECODE)) { needs_stub = 1; break; diff --git a/sdk/tools/widl/expr.c b/sdk/tools/widl/expr.c index 2ed4aff6ad3..be818de2e83 100644 --- a/sdk/tools/widl/expr.c +++ b/sdk/tools/widl/expr.c @@ -112,28 +112,24 @@ static int is_float_type(const type_t *type) expr_t *make_expr(enum expr_type type) { expr_t *e = xmalloc(sizeof(expr_t)); + memset(e, 0, sizeof(*e)); e->type = type; - e->ref = NULL; - e->u.lval = 0; - e->is_const = FALSE; - e->cval = 0; return e; } -expr_t *make_exprl(enum expr_type type, int val) +expr_t *make_exprl(enum expr_type type, const struct integer *integer) { expr_t *e = xmalloc(sizeof(expr_t)); + memset(e, 0, sizeof(*e)); e->type = type; - e->ref = NULL; - e->u.lval = val; - e->is_const = FALSE; + e->u.integer = *integer; /* check for numeric constant */ - if (type == EXPR_NUM || type == EXPR_HEXNUM || type == EXPR_TRUEFALSE) + if (type == EXPR_NUM || type == EXPR_TRUEFALSE) { /* make sure true/false value is valid */ - assert(type != EXPR_TRUEFALSE || val == 0 || val == 1); + assert(type != EXPR_TRUEFALSE || integer->value == 0 || integer->value == 1); e->is_const = TRUE; - e->cval = val; + e->cval = integer->value; } return e; } @@ -194,15 +190,15 @@ expr_t *make_exprt(enum expr_type type, var_t *var, expr_t *expr) expr_t *e; type_t *tref; - if (var->stgclass != STG_NONE && var->stgclass != STG_REGISTER) + if (var->declspec.stgclass != STG_NONE && var->declspec.stgclass != STG_REGISTER) error_loc("invalid storage class for type expression\n"); - tref = var->type; + tref = var->declspec.type; e = xmalloc(sizeof(expr_t)); e->type = type; e->ref = expr; - e->u.tref = tref; + e->u.tref = var->declspec; e->is_const = FALSE; if (type == EXPR_SIZEOF) { @@ -252,10 +248,9 @@ expr_t *make_expr1(enum expr_type type, expr_t *expr) { expr_t *e; e = xmalloc(sizeof(expr_t)); + memset(e, 0, sizeof(*e)); e->type = type; e->ref = expr; - e->u.lval = 0; - e->is_const = FALSE; /* check for compile-time optimization */ if (expr->is_const) { @@ -406,29 +401,25 @@ struct expression_type static void check_scalar_type(const struct expr_loc *expr_loc, const type_t *cont_type, const type_t *type) { - if (!cont_type || (!is_integer_type(type) && !is_ptr(type) && - !is_float_type(type))) - error_loc_info(&expr_loc->v->loc_info, "scalar type required in expression%s%s\n", - expr_loc->attr ? " for attribute " : "", - expr_loc->attr ? expr_loc->attr : ""); + if (!cont_type || (!is_integer_type( type ) && !is_ptr( type ) && !is_float_type( type ))) + error_at( &expr_loc->v->where, "scalar type required in expression%s%s\n", + expr_loc->attr ? " for attribute " : "", expr_loc->attr ? expr_loc->attr : "" ); } static void check_arithmetic_type(const struct expr_loc *expr_loc, const type_t *cont_type, const type_t *type) { - if (!cont_type || (!is_integer_type(type) && !is_float_type(type))) - error_loc_info(&expr_loc->v->loc_info, "arithmetic type required in expression%s%s\n", - expr_loc->attr ? " for attribute " : "", - expr_loc->attr ? expr_loc->attr : ""); + if (!cont_type || (!is_integer_type( type ) && !is_float_type( type ))) + error_at( &expr_loc->v->where, "arithmetic type required in expression%s%s\n", + expr_loc->attr ? " for attribute " : "", expr_loc->attr ? expr_loc->attr : "" ); } static void check_integer_type(const struct expr_loc *expr_loc, const type_t *cont_type, const type_t *type) { - if (!cont_type || !is_integer_type(type)) - error_loc_info(&expr_loc->v->loc_info, "integer type required in expression%s%s\n", - expr_loc->attr ? " for attribute " : "", - expr_loc->attr ? expr_loc->attr : ""); + if (!cont_type || !is_integer_type( type )) + error_at( &expr_loc->v->where, "integer type required in expression%s%s\n", + expr_loc->attr ? " for attribute " : "", expr_loc->attr ? expr_loc->attr : "" ); } static type_t *find_identifier(const char *identifier, const type_t *cont_type, int *found_in_cont_type) @@ -462,6 +453,11 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type, case TYPE_POINTER: case TYPE_ARRAY: case TYPE_BITFIELD: + case TYPE_APICONTRACT: + case TYPE_RUNTIMECLASS: + case TYPE_PARAMETERIZED_TYPE: + case TYPE_PARAMETER: + case TYPE_DELEGATE: /* nothing to do */ break; case TYPE_ALIAS: @@ -474,7 +470,7 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type, if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) if (field->name && !strcmp(identifier, field->name)) { - type = field->type; + type = field->declspec.type; *found_in_cont_type = 1; break; } @@ -482,7 +478,7 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type, if (!type) { var_t *const_var = find_const(identifier, 0); - if (const_var) type = const_var->type; + if (const_var) type = const_var->declspec.type; } return type; @@ -513,19 +509,18 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc { case EXPR_VOID: break; - case EXPR_HEXNUM: case EXPR_NUM: case EXPR_TRUEFALSE: result.is_temporary = FALSE; - result.type = type_new_int(TYPE_BASIC_INT, 0); + result.type = type_new_int(e->u.integer.is_long ? TYPE_BASIC_LONG : TYPE_BASIC_INT, e->u.integer.is_unsigned); break; case EXPR_STRLIT: result.is_temporary = TRUE; - result.type = type_new_pointer(FC_UP, type_new_int(TYPE_BASIC_CHAR, 0), NULL); + result.type = type_new_pointer(type_new_int(TYPE_BASIC_CHAR, 0)); break; case EXPR_WSTRLIT: result.is_temporary = TRUE; - result.type = type_new_pointer(FC_UP, type_new_int(TYPE_BASIC_WCHAR, 0), NULL); + result.type = type_new_pointer(type_new_int(TYPE_BASIC_WCHAR, 0)); break; case EXPR_CHARCONST: result.is_temporary = TRUE; @@ -542,11 +537,8 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc result.is_temporary = FALSE; result.type = find_identifier(e->u.sval, cont_type, &found_in_cont_type); if (!result.type) - { - error_loc_info(&expr_loc->v->loc_info, "identifier %s cannot be resolved in expression%s%s\n", - e->u.sval, expr_loc->attr ? " for attribute " : "", - expr_loc->attr ? expr_loc->attr : ""); - } + error_at( &expr_loc->v->where, "identifier %s cannot be resolved in expression%s%s\n", e->u.sval, + expr_loc->attr ? " for attribute " : "", expr_loc->attr ? expr_loc->attr : "" ); break; } case EXPR_LOGNOT: @@ -570,28 +562,26 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc case EXPR_ADDRESSOF: result = resolve_expression(expr_loc, cont_type, e->ref); if (!result.is_variable) - error_loc_info(&expr_loc->v->loc_info, "address-of operator applied to non-variable type in expression%s%s\n", - expr_loc->attr ? " for attribute " : "", - expr_loc->attr ? expr_loc->attr : ""); + error_at( &expr_loc->v->where, "address-of operator applied to non-variable type in expression%s%s\n", + expr_loc->attr ? " for attribute " : "", expr_loc->attr ? expr_loc->attr : "" ); result.is_variable = FALSE; result.is_temporary = TRUE; - result.type = type_new_pointer(FC_UP, result.type, NULL); + result.type = type_new_pointer(result.type); break; case EXPR_PPTR: result = resolve_expression(expr_loc, cont_type, e->ref); if (result.type && is_ptr(result.type)) - result.type = type_pointer_get_ref(result.type); + result.type = type_pointer_get_ref_type(result.type); else if(result.type && is_array(result.type) && type_array_is_decl_as_ptr(result.type)) - result.type = type_array_get_element(result.type); + result.type = type_array_get_element_type(result.type); else - error_loc_info(&expr_loc->v->loc_info, "dereference operator applied to non-pointer type in expression%s%s\n", - expr_loc->attr ? " for attribute " : "", - expr_loc->attr ? expr_loc->attr : ""); + error_at( &expr_loc->v->where, "dereference operator applied to non-pointer type in expression%s%s\n", + expr_loc->attr ? " for attribute " : "", expr_loc->attr ? expr_loc->attr : "" ); break; case EXPR_CAST: result = resolve_expression(expr_loc, cont_type, e->ref); - result.type = e->u.tref; + result.type = e->u.tref.type; break; case EXPR_SIZEOF: result.is_temporary = FALSE; @@ -640,9 +630,8 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc if (result.type && is_valid_member_operand(result.type)) result = resolve_expression(expr_loc, result.type, e->u.ext); else - error_loc_info(&expr_loc->v->loc_info, "'.' or '->' operator applied to a type that isn't a structure, union or enumeration in expression%s%s\n", - expr_loc->attr ? " for attribute " : "", - expr_loc->attr ? expr_loc->attr : ""); + error_at( &expr_loc->v->where, "'.' or '->' operator applied to a type that isn't a structure, union or enumeration in expression%s%s\n", + expr_loc->attr ? " for attribute " : "", expr_loc->attr ? expr_loc->attr : "" ); break; case EXPR_COND: { @@ -653,8 +642,8 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc result_third = resolve_expression(expr_loc, cont_type, e->ext2); check_scalar_type(expr_loc, cont_type, result_second.type); check_scalar_type(expr_loc, cont_type, result_third.type); - if (!is_ptr(result_second.type) ^ !is_ptr(result_third.type)) - error_loc_info(&expr_loc->v->loc_info, "type mismatch in ?: expression\n" ); + if (!is_ptr( result_second.type ) ^ !is_ptr( result_third.type )) + error_at( &expr_loc->v->where, "type mismatch in ?: expression\n" ); /* FIXME: determine the correct return type */ result = result_second; result.is_variable = FALSE; @@ -665,17 +654,17 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc if (result.type && is_array(result.type)) { struct expression_type index_result; - result.type = type_array_get_element(result.type); + result.type = type_array_get_element_type(result.type); index_result = resolve_expression(expr_loc, cont_type /* FIXME */, e->u.ext); - if (!index_result.type || !is_integer_type(index_result.type)) - error_loc_info(&expr_loc->v->loc_info, "array subscript not of integral type in expression%s%s\n", - expr_loc->attr ? " for attribute " : "", - expr_loc->attr ? expr_loc->attr : ""); + if (!index_result.type || !is_integer_type( index_result.type )) + error_at( &expr_loc->v->where, "array subscript not of integral type in expression%s%s\n", + expr_loc->attr ? " for attribute " : "", expr_loc->attr ? expr_loc->attr : "" ); } else - error_loc_info(&expr_loc->v->loc_info, "array subscript operator applied to non-array type in expression%s%s\n", - expr_loc->attr ? " for attribute " : "", - expr_loc->attr ? expr_loc->attr : ""); + { + error_at( &expr_loc->v->where, "array subscript operator applied to non-array type in expression%s%s\n", + expr_loc->attr ? " for attribute " : "", expr_loc->attr ? expr_loc->attr : "" ); + } break; } return result; @@ -697,16 +686,20 @@ void write_expr(FILE *h, const expr_t *e, int brackets, case EXPR_VOID: break; case EXPR_NUM: - fprintf(h, "%u", e->u.lval); - break; - case EXPR_HEXNUM: - fprintf(h, "0x%x", e->u.lval); + if (e->u.integer.is_hex) + fprintf(h, "0x%x", e->u.integer.value); + else + fprintf(h, "%u", e->u.integer.value); + if (e->u.integer.is_unsigned) + fprintf(h, "u"); + if (e->u.integer.is_long) + fprintf(h, "l"); break; case EXPR_DOUBLE: fprintf(h, "%#.15g", e->u.dval); break; case EXPR_TRUEFALSE: - if (e->u.lval == 0) + if (e->u.integer.value == 0) fprintf(h, "FALSE"); else fprintf(h, "TRUE"); @@ -759,13 +752,13 @@ void write_expr(FILE *h, const expr_t *e, int brackets, break; case EXPR_CAST: fprintf(h, "("); - write_type_decl(h, e->u.tref, NULL); + write_type_decl(h, &e->u.tref, NULL); fprintf(h, ")"); write_expr(h, e->ref, 1, toplevel, toplevel_prefix, cont_type, local_var_prefix); break; case EXPR_SIZEOF: fprintf(h, "sizeof("); - write_type_decl(h, e->u.tref, NULL); + write_type_decl(h, &e->u.tref, NULL); fprintf(h, ")"); break; case EXPR_SHL: @@ -874,9 +867,8 @@ int compare_expr(const expr_t *a, const expr_t *b) switch (a->type) { case EXPR_NUM: - case EXPR_HEXNUM: case EXPR_TRUEFALSE: - return a->u.lval - b->u.lval; + return a->u.integer.value - b->u.integer.value; case EXPR_DOUBLE: return a->u.dval - b->u.dval; case EXPR_IDENTIFIER: @@ -917,7 +909,7 @@ int compare_expr(const expr_t *a, const expr_t *b) return ret; return compare_expr(a->u.ext, b->u.ext); case EXPR_CAST: - ret = compare_type(a->u.tref, b->u.tref); + ret = compare_type(a->u.tref.type, b->u.tref.type); if (ret != 0) return ret; /* Fall through. */ @@ -929,7 +921,7 @@ int compare_expr(const expr_t *a, const expr_t *b) case EXPR_POS: return compare_expr(a->ref, b->ref); case EXPR_SIZEOF: - return compare_type(a->u.tref, b->u.tref); + return compare_type(a->u.tref.type, b->u.tref.type); case EXPR_VOID: return 0; } diff --git a/sdk/tools/widl/expr.h b/sdk/tools/widl/expr.h index 7b0e1b2c7ba..89c0acf5491 100644 --- a/sdk/tools/widl/expr.h +++ b/sdk/tools/widl/expr.h @@ -26,7 +26,7 @@ struct expr_loc }; extern expr_t *make_expr(enum expr_type type); -extern expr_t *make_exprl(enum expr_type type, int val); +extern expr_t *make_exprl(enum expr_type type, const struct integer *integer); extern expr_t *make_exprd(enum expr_type type, double val); extern expr_t *make_exprs(enum expr_type type, char *val); extern expr_t *make_exprt(enum expr_type type, var_t *var, expr_t *expr); diff --git a/sdk/tools/widl/hash.c b/sdk/tools/widl/hash.c index 249c824e9e0..74f93ee81ce 100644 --- a/sdk/tools/widl/hash.c +++ b/sdk/tools/widl/hash.c @@ -23,6 +23,7 @@ #ifdef __REACTOS__ #include +#include #else #include "windef.h" #include "winbase.h" @@ -507,10 +508,10 @@ static const unsigned char Lookup_224[128 * 3] = { * skind and lcid, while the low word is based on a repeated string * hash of skind/str. */ -unsigned int lhash_val_of_name_sys( syskind_t skind, LCID lcid, LPCSTR lpStr) +unsigned int lhash_val_of_name_sys( syskind_t skind, int lcid, const char *lpStr) { - ULONG nOffset, nMask = skind == SYS_MAC ? 1 : 0; - ULONG nHiWord, nLoWord = 0x0deadbee; + unsigned int nOffset, nMask = skind == SYS_MAC ? 1 : 0; + unsigned int nHiWord, nLoWord = 0x0deadbee; const unsigned char *str = (const unsigned char *)lpStr, *pnLookup = NULL; if (!str) @@ -519,59 +520,6 @@ unsigned int lhash_val_of_name_sys( syskind_t skind, LCID lcid, LPCSTR lpStr) switch (PRIMARYLANGID(LANGIDFROMLCID(lcid))) { default: - fprintf(stderr, "Unknown lcid %x, 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_MALTESE: case LANG_IRISH: - case LANG_SAMI: case LANG_UPPER_SORBIAN: case LANG_TSWANA: - case LANG_XHOSA: case LANG_ZULU: case LANG_WELSH: - case LANG_BRETON: case LANG_SCOTTISH_GAELIC: case LANG_NEUTRAL: -/* some languages not in all windows versions or ReactOS */ -#ifdef LANG_MANX_GAELIC - case LANG_MANX_GAELIC: -#endif -#ifdef LANG_TAJIK - case LANG_TAJIK: -#endif -#ifdef LANG_ROMANSH - case LANG_ROMANSH: -#endif -#ifdef LANG_SUTU - case LANG_SUTU: -#endif -#ifdef LANG_TSONGA - case LANG_TSONGA: -#endif -#ifdef LANG_VENDA - case LANG_VENDA: -#endif -#ifdef LANG_ESPERANTO - case LANG_ESPERANTO: -#endif -#ifdef LANG_WALON - case LANG_WALON: -#endif -#ifdef LANG_CORNISH - case LANG_CORNISH: -#endif nOffset = 16; pnLookup = Lookup_16; break; @@ -643,3 +591,136 @@ unsigned int lhash_val_of_name_sys( syskind_t skind, LCID lcid, LPCSTR lpStr) return nHiWord | nLoWord; } + +/* SHA1 algorithm + * + * Based on public domain SHA code by Steve Reid + * Copied and adapted from ntdll.A_SHAInit / ntdll.A_SHAUpdate / ntdll.A_SHAFinal + */ + +#ifdef WORDS_BIGENDIAN +#define DWORD2BE(x) (x) +#else +#define DWORD2BE(x) ((((x) >> 24) & 0xff) | (((x) >> 8) & 0xff00) | (((x) << 8) & 0xff0000) | (((x) << 24) & 0xff000000)) +#endif + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) +#define blk0(i) (block[i] = DWORD2BE(block[i])) +#define blk1(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15]^block[(i+2)&15]^block[i&15],1)) +#define f1(x,y,z) (z^(x&(y^z))) +#define f2(x,y,z) (x^y^z) +#define f3(x,y,z) ((x&y)|(z&(x|y))) +#define f4(x,y,z) (x^y^z) +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=f1(w,x,y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=f1(w,x,y)+blk1(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=f2(w,x,y)+blk1(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=f3(w,x,y)+blk1(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=f4(w,x,y)+blk1(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + +/* Hash a single 512-bit block. This is the core of the algorithm. */ +static void sha1_transform(struct sha1_context *ctx) +{ + unsigned int a, b, c, d, e, *block = (unsigned int *)ctx->buffer; + + /* Copy ctx->state[] to working variables */ + a = ctx->state[0]; + b = ctx->state[1]; + c = ctx->state[2]; + d = ctx->state[3]; + e = ctx->state[4]; + + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + + /* Add the working variables back into ctx->state[] */ + ctx->state[0] += a; + ctx->state[1] += b; + ctx->state[2] += c; + ctx->state[3] += d; + ctx->state[4] += e; + + /* Wipe variables */ + a = b = c = d = e = 0; +} + +void sha1_init(struct sha1_context *ctx) +{ + /* SHA1 initialization constants */ + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + ctx->count[0] = 0; + ctx->count[1] = 0; +} + +void sha1_update(struct sha1_context *ctx, const char *data, size_t data_size) +{ + size_t buffer_size; + + buffer_size = ctx->count[1] & 63; + ctx->count[1] += data_size; + if (ctx->count[1] < data_size) ctx->count[0]++; + ctx->count[0] += (data_size >> 29); + + if (buffer_size + data_size < 64) + memcpy(&ctx->buffer[buffer_size], data, data_size); + else + { + while (buffer_size + data_size >= 64) + { + memcpy(ctx->buffer + buffer_size, data, 64 - buffer_size); + data += 64 - buffer_size; + data_size -= 64 - buffer_size; + sha1_transform(ctx); + buffer_size = 0; + } + memcpy(ctx->buffer + buffer_size, data, data_size); + } +} + +void sha1_finalize(struct sha1_context *ctx, unsigned int result[5]) +{ + unsigned int *count, length_hi, length_lo, i; + size_t pad_size, buffer_size; + char pad[72]; + + buffer_size = ctx->count[1] & 63; + if (buffer_size >= 56) pad_size = 56 + 64 - buffer_size; + else pad_size = 56 - buffer_size; + + length_hi = (ctx->count[0] << 3) | (ctx->count[1] >> (32 - 3)); + length_lo = (ctx->count[1] << 3); + + memset(pad + 1, 0, pad_size - 1); + pad[0] = 0x80; + count = (unsigned int*)(pad + pad_size); + count[0] = DWORD2BE(length_hi); + count[1] = DWORD2BE(length_lo); + sha1_update(ctx, pad, pad_size + 8); + + for (i = 0; i < 5; i++) result[i] = DWORD2BE(ctx->state[i]); + + sha1_init(ctx); +} diff --git a/sdk/tools/widl/hash.h b/sdk/tools/widl/hash.h index 3c2fd2914bf..a71b095e5fe 100644 --- a/sdk/tools/widl/hash.h +++ b/sdk/tools/widl/hash.h @@ -22,6 +22,17 @@ #ifndef __WIDL_HASH_H #define __WIDL_HASH_H -extern unsigned int lhash_val_of_name_sys( syskind_t skind, LCID lcid, LPCSTR lpStr); +extern unsigned int lhash_val_of_name_sys( syskind_t skind, int lcid, const char *lpStr); + +struct sha1_context +{ + unsigned int state[5]; + unsigned int count[2]; + char buffer[64]; +}; + +void sha1_init(struct sha1_context *ctx); +void sha1_update(struct sha1_context *ctx, const char *data, size_t data_size); +void sha1_finalize(struct sha1_context *ctx, unsigned int hash[5]); #endif diff --git a/sdk/tools/widl/header.c b/sdk/tools/widl/header.c index 7c607c0a965..38036bfbb2a 100644 --- a/sdk/tools/widl/header.c +++ b/sdk/tools/widl/header.c @@ -23,9 +23,6 @@ #include #include #include -#ifdef HAVE_UNISTD_H -# include -#endif #include #include @@ -43,7 +40,12 @@ user_type_list_t user_type_list = LIST_INIT(user_type_list); context_handle_list_t context_handle_list = LIST_INIT(context_handle_list); generic_handle_list_t generic_handle_list = LIST_INIT(generic_handle_list); -static void write_type_def_or_decl(FILE *f, type_t *t, int field, const char *name); +static void write_type_v(FILE *f, const decl_spec_t *t, int is_field, bool define, const char *name, enum name_type name_type); + +static void write_apicontract_guard_start(FILE *header, const expr_t *expr); +static void write_apicontract_guard_end(FILE *header, const expr_t *expr); + +static void write_widl_using_macros(FILE *header, type_t *iface); static void indent(FILE *h, int delta) { @@ -63,64 +65,26 @@ static void write_line(FILE *f, int delta, const char *fmt, ...) fprintf(f, "\n"); } -int is_ptrchain_attr(const var_t *var, enum attr_type t) +static char *format_parameterized_type_args(const type_t *type, const char *prefix, const char *suffix) { - if (is_attr(var->attrs, t)) - return 1; - else + typeref_list_t *params; + typeref_t *ref; + size_t len = 0, pos = 0; + char *buf = NULL; + + params = type->details.parameterized.params; + if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry) { - type_t *type = var->type; - for (;;) - { - if (is_attr(type->attrs, t)) - return 1; - else if (type_is_alias(type)) - type = type_alias_get_aliasee(type); - else if (is_ptr(type)) - type = type_pointer_get_ref(type); - else return 0; - } + assert(ref->type->type_type != TYPE_POINTER); + pos += strappend(&buf, &len, pos, "%s%s%s", prefix, ref->type->name, suffix); + if (list_next(params, &ref->entry)) pos += strappend(&buf, &len, pos, ", "); } + + if (!buf) return xstrdup(""); + return buf; } -int is_aliaschain_attr(const type_t *type, enum attr_type attr) -{ - const type_t *t = type; - for (;;) - { - if (is_attr(t->attrs, attr)) - return 1; - else if (type_is_alias(t)) - t = type_alias_get_aliasee(t); - else return 0; - } -} - -int is_attr(const attr_list_t *list, enum attr_type t) -{ - const attr_t *attr; - if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry ) - if (attr->type == t) return 1; - return 0; -} - -void *get_attrp(const attr_list_t *list, enum attr_type t) -{ - const attr_t *attr; - if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry ) - if (attr->type == t) return attr->u.pval; - return NULL; -} - -unsigned int get_attrv(const attr_list_t *list, enum attr_type t) -{ - const attr_t *attr; - if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry ) - if (attr->type == t) return attr->u.ival; - return 0; -} - -static void write_guid(FILE *f, const char *guid_prefix, const char *name, const UUID *uuid) +static void write_guid(FILE *f, const char *guid_prefix, const char *name, const struct uuid *uuid) { if (!uuid) return; fprintf(f, "DEFINE_GUID(%s_%s, 0x%08x, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x," @@ -130,24 +94,22 @@ static void write_guid(FILE *f, const char *guid_prefix, const char *name, const uuid->Data4[6], uuid->Data4[7]); } -static void write_uuid_decl(FILE *f, type_t *type, const UUID *uuid) +static void write_uuid_decl(FILE *f, type_t *type, const struct uuid *uuid) { - char *name = format_namespace(type->namespace, "", "::", type->name); fprintf(f, "#ifdef __CRT_UUID_DECL\n"); fprintf(f, "__CRT_UUID_DECL(%s, 0x%08x, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x," "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", - name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1], + type->c_name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], uuid->Data4[7]); fprintf(f, "#endif\n"); - free(name); } -static const char *uuid_string(const UUID *uuid) +static const char *uuid_string(const struct uuid *uuid) { static char buf[37]; - sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + snprintf(buf, sizeof(buf), "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], uuid->Data4[7]); @@ -170,31 +132,33 @@ static void write_namespace_end(FILE *header, struct namespace *namespace) { if(is_global_namespace(namespace)) { if(use_abi_namespace) - write_line(header, -1, "}", namespace->name); + write_line(header, -1, "}"); return; } - write_line(header, -1, "}", namespace->name); + write_line(header, -1, "}"); write_namespace_end(header, namespace->parent); } const char *get_name(const var_t *v) { - static char buffer[256]; - + static char *buffer; + free( buffer ); + if (is_attr( v->attrs, ATTR_EVENTADD )) + return buffer = strmake( "add_%s", v->name ); + if (is_attr( v->attrs, ATTR_EVENTREMOVE )) + return buffer = strmake( "remove_%s", v->name ); if (is_attr( v->attrs, ATTR_PROPGET )) - strcpy( buffer, "get_" ); - else if (is_attr( v->attrs, ATTR_PROPPUT )) - strcpy( buffer, "put_" ); - else if (is_attr( v->attrs, ATTR_PROPPUTREF )) - strcpy( buffer, "putref_" ); - else - buffer[0] = 0; - strcat( buffer, v->name ); - return buffer; + return buffer = strmake( "get_%s", v->name ); + if (is_attr( v->attrs, ATTR_PROPPUT )) + return buffer = strmake( "put_%s", v->name ); + if (is_attr( v->attrs, ATTR_PROPPUTREF )) + return buffer = strmake( "putref_%s", v->name ); + buffer = NULL; + return v->name; } -static void write_fields(FILE *h, var_list_t *fields) +static void write_fields(FILE *h, var_list_t *fields, enum name_type name_type) { unsigned nameless_struct_cnt = 0, nameless_struct_i = 0, nameless_union_cnt = 0, nameless_union_i = 0; const char *name; @@ -204,9 +168,9 @@ static void write_fields(FILE *h, var_list_t *fields) if (!fields) return; LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) { - if (!v || !v->type) continue; + if (!v->declspec.type) continue; - switch(type_get_type_detect_alias(v->type)) { + switch(type_get_type_detect_alias(v->declspec.type)) { case TYPE_STRUCT: case TYPE_ENCAPSULATED_UNION: nameless_struct_cnt++; @@ -220,12 +184,14 @@ static void write_fields(FILE *h, var_list_t *fields) } LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) { - if (!v || !v->type) continue; + expr_t *contract = get_attrp(v->attrs, ATTR_CONTRACT); + if (!v->declspec.type) continue; + if (contract) write_apicontract_guard_start(h, contract); indent(h, 0); name = v->name; - switch(type_get_type_detect_alias(v->type)) { + switch(type_get_type_detect_alias(v->declspec.type)) { case TYPE_STRUCT: case TYPE_ENCAPSULATED_UNION: if(!v->name) { @@ -233,7 +199,7 @@ static void write_fields(FILE *h, var_list_t *fields) if(nameless_struct_cnt == 1) { name = "__C89_NAMELESSSTRUCTNAME"; }else if(nameless_struct_i < 5 /* # of supporting macros */) { - sprintf(buf, "__C89_NAMELESSSTRUCTNAME%d", ++nameless_struct_i); + snprintf(buf, sizeof(buf), "__C89_NAMELESSSTRUCTNAME%d", ++nameless_struct_i); name = buf; } } @@ -244,7 +210,7 @@ static void write_fields(FILE *h, var_list_t *fields) if(nameless_union_cnt == 1) { name = "__C89_NAMELESSUNIONNAME"; }else if(nameless_union_i < 8 /* # of supporting macros */ ) { - sprintf(buf, "__C89_NAMELESSUNIONNAME%d", ++nameless_union_i); + snprintf(buf, sizeof(buf), "__C89_NAMELESSUNIONNAME%d", ++nameless_union_i); name = buf; } } @@ -252,8 +218,9 @@ static void write_fields(FILE *h, var_list_t *fields) default: ; } - write_type_def_or_decl(h, v->type, TRUE, name); + write_type_v(h, &v->declspec, TRUE, v->is_defined, name, name_type); fprintf(h, ";\n"); + if (contract) write_apicontract_guard_end(h, contract); } } @@ -263,6 +230,8 @@ static void write_enums(FILE *h, var_list_t *enums, const char *enum_name) if (!enums) return; LIST_FOR_EACH_ENTRY( v, enums, var_t, entry ) { + expr_t *contract = get_attrp(v->attrs, ATTR_CONTRACT); + if (contract) write_apicontract_guard_start(h, contract); if (v->name) { indent(h, 0); if(!enum_name) @@ -275,8 +244,9 @@ static void write_enums(FILE *h, var_list_t *enums, const char *enum_name) } } if (list_next( enums, &v->entry )) fprintf(h, ",\n"); + else fprintf(h, "\n"); + if (contract) write_apicontract_guard_end(h, contract); } - fprintf(h, "\n"); } int needs_space_after(type_t *t) @@ -285,33 +255,55 @@ int needs_space_after(type_t *t) (!is_ptr(t) && (!is_array(t) || !type_array_is_decl_as_ptr(t) || t->name))); } +static int decl_needs_parens(const type_t *t) +{ + if (type_is_alias(t)) + return FALSE; + if (is_array(t) && !type_array_is_decl_as_ptr(t)) + return TRUE; + return is_func(t); +} + static void write_pointer_left(FILE *h, type_t *ref) { if (needs_space_after(ref)) fprintf(h, " "); - if (!type_is_alias(ref) && is_array(ref) && !type_array_is_decl_as_ptr(ref)) + if (decl_needs_parens(ref)) fprintf(h, "("); + if (type_get_type_detect_alias(ref) == TYPE_FUNCTION) + { + const char *callconv = get_attrp(ref->attrs, ATTR_CALLCONV); + if (!callconv && is_object_interface) callconv = "STDMETHODCALLTYPE"; + if (callconv) fprintf(h, "%s ", callconv); + } fprintf(h, "*"); } -void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly) +void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, bool define, int write_callconv) { - const char *name; + type_t *t = ds->type; + const char *decl_name, *name; + char *args; if (!h) return; + decl_name = type_get_decl_name(t, name_type); name = type_get_name(t, name_type); - if (is_attr(t->attrs, ATTR_CONST) && - (type_is_alias(t) || !is_ptr(t))) + if (ds->func_specifier & FUNCTION_SPECIFIER_INLINE) + fprintf(h, "inline "); + + if ((ds->qualifier & TYPE_QUALIFIER_CONST) && (type_is_alias(t) || !is_ptr(t))) fprintf(h, "const "); - if (type_is_alias(t)) fprintf(h, "%s", t->name); + if (type_is_alias(t)) fprintf(h, "%s", name); else { switch (type_get_type_detect_alias(t)) { case TYPE_ENUM: - if (!declonly && t->defined && !t->written) { - if (name) fprintf(h, "enum %s {\n", name); + if (!define) fprintf(h, "enum %s", decl_name ? decl_name : ""); + else if (!t->written) { + assert(t->defined); + if (decl_name) fprintf(h, "enum %s {\n", decl_name); else fprintf(h, "enum {\n"); t->written = TRUE; indentation++; @@ -319,41 +311,48 @@ void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly) indent(h, -1); fprintf(h, "}"); } + else if (winrt_mode && name_type == NAME_DEFAULT && name) fprintf(h, "%s", name); else fprintf(h, "enum %s", name ? name : ""); break; case TYPE_STRUCT: case TYPE_ENCAPSULATED_UNION: - if (!declonly && t->defined && !t->written) { - if (name) fprintf(h, "struct %s {\n", name); + if (!define) fprintf(h, "struct %s", decl_name ? decl_name : ""); + else if (!t->written) { + assert(t->defined); + if (decl_name) fprintf(h, "struct %s {\n", decl_name); else fprintf(h, "struct {\n"); t->written = TRUE; indentation++; if (type_get_type(t) != TYPE_STRUCT) - write_fields(h, type_encapsulated_union_get_fields(t)); + write_fields(h, type_encapsulated_union_get_fields(t), name_type); else - write_fields(h, type_struct_get_fields(t)); + write_fields(h, type_struct_get_fields(t), name_type); indent(h, -1); fprintf(h, "}"); } + else if (winrt_mode && name_type == NAME_DEFAULT && name) fprintf(h, "%s", name); else fprintf(h, "struct %s", name ? name : ""); break; case TYPE_UNION: - if (!declonly && t->defined && !t->written) { - if (t->name) fprintf(h, "union %s {\n", t->name); + if (!define) fprintf(h, "union %s", decl_name ? decl_name : ""); + else if (!t->written) { + assert(t->defined); + if (decl_name) fprintf(h, "union %s {\n", decl_name); else fprintf(h, "union {\n"); t->written = TRUE; indentation++; - write_fields(h, type_union_get_cases(t)); + write_fields(h, type_union_get_cases(t), name_type); indent(h, -1); fprintf(h, "}"); } - else fprintf(h, "union %s", t->name ? t->name : ""); + else if (winrt_mode && name_type == NAME_DEFAULT && name) fprintf(h, "%s", name); + else fprintf(h, "union %s", name ? name : ""); break; case TYPE_POINTER: { - write_type_left(h, type_pointer_get_ref(t), name_type, declonly); - write_pointer_left(h, type_pointer_get_ref(t)); - if (is_attr(t->attrs, ATTR_CONST)) fprintf(h, "const "); + write_type_left(h, type_pointer_get_ref(t), name_type, define, FALSE); + write_pointer_left(h, type_pointer_get_ref_type(t)); + if (ds->qualifier & TYPE_QUALIFIER_CONST) fprintf(h, "const "); break; } case TYPE_ARRAY: @@ -361,11 +360,27 @@ void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly) fprintf(h, "%s", t->name); else { - write_type_left(h, type_array_get_element(t), name_type, declonly); + write_type_left(h, type_array_get_element(t), name_type, define, !type_array_is_decl_as_ptr(t)); if (type_array_is_decl_as_ptr(t)) - write_pointer_left(h, type_array_get_element(t)); + write_pointer_left(h, type_array_get_element_type(t)); } break; + case TYPE_FUNCTION: + { + write_type_left(h, type_function_get_ret(t), name_type, define, TRUE); + + /* A pointer to a function has to write the calling convention inside + * the parentheses. There's no way to handle that here, so we have to + * use an extra parameter to tell us whether to write the calling + * convention or not. */ + if (write_callconv) + { + const char *callconv = get_attrp(t->attrs, ATTR_CALLCONV); + if (!callconv && is_object_interface) callconv = "STDMETHODCALLTYPE"; + if (callconv) fprintf(h, " %s ", callconv); + } + break; + } case TYPE_BASIC: if (type_basic_get_type(t) != TYPE_BASIC_INT32 && type_basic_get_type(t) != TYPE_BASIC_INT64 && @@ -417,19 +432,43 @@ void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly) case TYPE_INTERFACE: case TYPE_MODULE: case TYPE_COCLASS: - fprintf(h, "%s", t->name); + fprintf(h, "%s", type_get_name(t, name_type)); + break; + case TYPE_RUNTIMECLASS: + fprintf(h, "%s", type_get_name(type_runtimeclass_get_default_iface(t, TRUE), name_type)); + break; + case TYPE_DELEGATE: + fprintf(h, "%s", type_get_name(type_delegate_get_iface(t), name_type)); break; case TYPE_VOID: fprintf(h, "void"); break; case TYPE_BITFIELD: - write_type_left(h, type_bitfield_get_field(t), name_type, declonly); + { + const decl_spec_t ds = {.type = type_bitfield_get_field(t)}; + write_type_left(h, &ds, name_type, define, TRUE); break; + } case TYPE_ALIAS: - case TYPE_FUNCTION: /* handled elsewhere */ assert(0); break; + case TYPE_PARAMETERIZED_TYPE: + { + type_t *iface = type_parameterized_type_get_real_type(t); + if (type_get_type(iface) == TYPE_DELEGATE) iface = type_delegate_get_iface(iface); + args = format_parameterized_type_args(t, "", "_logical"); + fprintf(h, "%s<%s>", iface->name, args); + free(args); + break; + } + case TYPE_PARAMETER: + fprintf(h, "%s_abi", t->name); + break; + case TYPE_APICONTRACT: + /* shouldn't be here */ + assert(0); + break; } } } @@ -443,10 +482,10 @@ void write_type_right(FILE *h, type_t *t, int is_field) { case TYPE_ARRAY: { - type_t *elem = type_array_get_element(t); + type_t *elem = type_array_get_element_type(t); if (type_array_is_decl_as_ptr(t)) { - if (!type_is_alias(elem) && is_array(elem) && !type_array_is_decl_as_ptr(elem)) + if (decl_needs_parens(elem)) fprintf(h, ")"); } else @@ -459,10 +498,21 @@ void write_type_right(FILE *h, type_t *t, int is_field) write_type_right(h, elem, FALSE); break; } + case TYPE_FUNCTION: + { + const var_list_t *args = type_function_get_args(t); + fputc('(', h); + if (args) write_args(h, args, NULL, 0, FALSE, NAME_DEFAULT); + else + fprintf(h, "void"); + fputc(')', h); + write_type_right(h, type_function_get_rettype(t), FALSE); + break; + } case TYPE_POINTER: { - type_t *ref = type_pointer_get_ref(t); - if (!type_is_alias(ref) && is_array(ref) && !type_array_is_decl_as_ptr(ref)) + type_t *ref = type_pointer_get_ref_type(t); + if (decl_needs_parens(ref)) fprintf(h, ")"); write_type_right(h, ref, FALSE); break; @@ -479,93 +529,70 @@ void write_type_right(FILE *h, type_t *t, int is_field) case TYPE_ALIAS: case TYPE_MODULE: case TYPE_COCLASS: - case TYPE_FUNCTION: case TYPE_INTERFACE: + case TYPE_RUNTIMECLASS: + case TYPE_DELEGATE: + case TYPE_PARAMETERIZED_TYPE: + case TYPE_PARAMETER: + break; + case TYPE_APICONTRACT: + /* not supposed to be here */ + assert(0); break; } } -static void write_type_v(FILE *h, type_t *t, int is_field, int declonly, const char *name) +static void write_type_v(FILE *h, const decl_spec_t *ds, int is_field, bool define, const char *name, enum name_type name_type) { - type_t *pt = NULL; - int ptr_level = 0; + type_t *t = ds->type; - if (!h) return; + if (!h) return; - if (t) { - for (pt = t; is_ptr(pt); pt = type_pointer_get_ref(pt), ptr_level++) - ; + if (t) write_type_left(h, ds, name_type, define, TRUE); - if (type_get_type_detect_alias(pt) == TYPE_FUNCTION) { - int i; - const char *callconv = get_attrp(pt->attrs, ATTR_CALLCONV); - if (!callconv && is_object_interface) callconv = "STDMETHODCALLTYPE"; - if (is_attr(pt->attrs, ATTR_INLINE)) fprintf(h, "inline "); - write_type_left(h, type_function_get_rettype(pt), NAME_DEFAULT, declonly); - fputc(' ', h); - if (ptr_level) fputc('(', h); - if (callconv) fprintf(h, "%s ", callconv); - for (i = 0; i < ptr_level; i++) - fputc('*', h); - } else - write_type_left(h, t, NAME_DEFAULT, declonly); - } + if (name) fprintf(h, "%s%s", !t || needs_space_after(t) ? " " : "", name ); - if (name) fprintf(h, "%s%s", !t || needs_space_after(t) ? " " : "", name ); - - if (t) { - if (type_get_type_detect_alias(pt) == TYPE_FUNCTION) { - const var_list_t *args = type_function_get_args(pt); - - if (ptr_level) fputc(')', h); - fputc('(', h); - if (args) - write_args(h, args, NULL, 0, FALSE); - else - fprintf(h, "void"); - fputc(')', h); - } else - write_type_right(h, t, is_field); - } + if (t) + write_type_right(h, t, is_field); } -static void write_type_def_or_decl(FILE *f, type_t *t, int field, const char *name) -{ - write_type_v(f, t, field, FALSE, name); -} - -static void write_type_definition(FILE *f, type_t *t) +static void write_type_definition(FILE *f, type_t *t, bool define) { int in_namespace = t->namespace && !is_global_namespace(t->namespace); int save_written = t->written; + decl_spec_t ds = {.type = t}; + expr_t *contract = get_attrp(t->attrs, ATTR_CONTRACT); + if (contract) write_apicontract_guard_start(f, contract); if(in_namespace) { fprintf(f, "#ifdef __cplusplus\n"); fprintf(f, "} /* extern \"C\" */\n"); write_namespace_start(f, t->namespace); } indent(f, 0); - write_type_left(f, t, NAME_DEFAULT, FALSE); + write_type_left(f, &ds, NAME_DEFAULT, define, TRUE); fprintf(f, ";\n"); if(in_namespace) { t->written = save_written; write_namespace_end(f, t->namespace); fprintf(f, "extern \"C\" {\n"); fprintf(f, "#else\n"); - write_type_left(f, t, NAME_C, FALSE); + write_type_left(f, &ds, NAME_C, define, TRUE); fprintf(f, ";\n"); + if (winrt_mode) write_widl_using_macros(f, t); fprintf(f, "#endif\n\n"); } + if (contract) write_apicontract_guard_end(f, contract); } -void write_type_decl(FILE *f, type_t *t, const char *name) +void write_type_decl(FILE *f, const decl_spec_t *t, const char *name) { - write_type_v(f, t, FALSE, TRUE, name); + write_type_v(f, t, FALSE, false, name, NAME_DEFAULT); } -void write_type_decl_left(FILE *f, type_t *t) +void write_type_decl_left(FILE *f, const decl_spec_t *ds) { - write_type_left(f, t, NAME_DEFAULT, TRUE); + write_type_left(f, ds, NAME_DEFAULT, false, TRUE); } static int user_type_registered(const char *name) @@ -602,8 +629,8 @@ unsigned int get_context_handle_offset( const type_t *type ) while (!is_attr( type->attrs, ATTR_CONTEXTHANDLE )) { - if (type_is_alias( type )) type = type_alias_get_aliasee( type ); - else if (is_ptr( type )) type = type_pointer_get_ref( type ); + if (type_is_alias( type )) type = type_alias_get_aliasee_type( type ); + else if (is_ptr( type )) type = type_pointer_get_ref_type( type ); else error( "internal error: %s is not a context handle\n", type->name ); } LIST_FOR_EACH_ENTRY( ch, &context_handle_list, context_handle_t, entry ) @@ -622,8 +649,8 @@ unsigned int get_generic_handle_offset( const type_t *type ) while (!is_attr( type->attrs, ATTR_HANDLE )) { - if (type_is_alias( type )) type = type_alias_get_aliasee( type ); - else if (is_ptr( type )) type = type_pointer_get_ref( type ); + if (type_is_alias( type )) type = type_alias_get_aliasee_type( type ); + else if (is_ptr( type )) type = type_pointer_get_ref_type( type ); else error( "internal error: %s is not a generic handle\n", type->name ); } LIST_FOR_EACH_ENTRY( gh, &generic_handle_list, generic_handle_t, entry ) @@ -637,82 +664,77 @@ unsigned int get_generic_handle_offset( const type_t *type ) /* check for types which require additional prototypes to be generated in the * header */ -void check_for_additional_prototype_types(const var_list_t *list) +void check_for_additional_prototype_types(type_t *type) { - const var_t *v; - - if (!list) return; - LIST_FOR_EACH_ENTRY( v, list, const var_t, entry ) - { - type_t *type = v->type; - if (!type) continue; - for (;;) { - const char *name = type->name; - if (type->user_types_registered) break; - type->user_types_registered = 1; - if (is_attr(type->attrs, ATTR_CONTEXTHANDLE)) { - if (!context_handle_registered(name)) - { - context_handle_t *ch = xmalloc(sizeof(*ch)); - ch->name = xstrdup(name); - list_add_tail(&context_handle_list, &ch->entry); - } - /* don't carry on parsing fields within this type */ - break; - } - if ((type_get_type(type) != TYPE_BASIC || - type_basic_get_type(type) != TYPE_BASIC_HANDLE) && - is_attr(type->attrs, ATTR_HANDLE)) { - if (!generic_handle_registered(name)) - { - generic_handle_t *gh = xmalloc(sizeof(*gh)); - gh->name = xstrdup(name); - list_add_tail(&generic_handle_list, &gh->entry); - } - /* don't carry on parsing fields within this type */ - break; - } - if (is_attr(type->attrs, ATTR_WIREMARSHAL)) { - if (!user_type_registered(name)) - { - user_type_t *ut = xmalloc(sizeof *ut); - ut->name = xstrdup(name); - list_add_tail(&user_type_list, &ut->entry); - } - /* don't carry on parsing fields within this type as we are already - * using a wire marshaled type */ - break; - } - else if (type_is_complete(type)) + if (!type) return; + for (;;) { + const char *name = type->name; + if (type->user_types_registered) break; + type->user_types_registered = 1; + if (is_attr(type->attrs, ATTR_CONTEXTHANDLE)) { + if (!context_handle_registered(name)) { - var_list_t *vars; - switch (type_get_type_detect_alias(type)) - { - case TYPE_ENUM: - vars = type_enum_get_values(type); - break; - case TYPE_STRUCT: - vars = type_struct_get_fields(type); - break; - case TYPE_UNION: - vars = type_union_get_cases(type); - break; - default: - vars = NULL; - break; - } - check_for_additional_prototype_types(vars); + context_handle_t *ch = xmalloc(sizeof(*ch)); + ch->name = xstrdup(name); + list_add_tail(&context_handle_list, &ch->entry); } - - if (type_is_alias(type)) - type = type_alias_get_aliasee(type); - else if (is_ptr(type)) - type = type_pointer_get_ref(type); - else if (is_array(type)) - type = type_array_get_element(type); - else - break; + /* don't carry on parsing fields within this type */ + break; } + if ((type_get_type(type) != TYPE_BASIC || + type_basic_get_type(type) != TYPE_BASIC_HANDLE) && + is_attr(type->attrs, ATTR_HANDLE)) { + if (!generic_handle_registered(name)) + { + generic_handle_t *gh = xmalloc(sizeof(*gh)); + gh->name = xstrdup(name); + list_add_tail(&generic_handle_list, &gh->entry); + } + /* don't carry on parsing fields within this type */ + break; + } + if (is_attr(type->attrs, ATTR_WIREMARSHAL)) { + if (!user_type_registered(name)) + { + user_type_t *ut = xmalloc(sizeof *ut); + ut->name = xstrdup(name); + list_add_tail(&user_type_list, &ut->entry); + } + /* don't carry on parsing fields within this type as we are already + * using a wire marshaled type */ + break; + } + else if (type_is_complete(type)) + { + var_list_t *vars; + const var_t *v; + switch (type_get_type_detect_alias(type)) + { + case TYPE_ENUM: + vars = type_enum_get_values(type); + break; + case TYPE_STRUCT: + vars = type_struct_get_fields(type); + break; + case TYPE_UNION: + vars = type_union_get_cases(type); + break; + default: + vars = NULL; + break; + } + if (vars) LIST_FOR_EACH_ENTRY( v, vars, const var_t, entry ) + check_for_additional_prototype_types(v->declspec.type); + } + + if (type_is_alias(type)) + type = type_alias_get_aliasee_type(type); + else if (is_ptr(type)) + type = type_pointer_get_ref_type(type); + else if (is_array(type)) + type = type_array_get_element_type(type); + else + break; } } @@ -732,7 +754,7 @@ static int for_each_serializable(const statement_list_t *stmts, FILE *header, { statement_t *stmt, *iface_stmt; statement_list_t *iface_stmts; - const type_list_t *type_entry; + typeref_t *ref; if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, statement_t, entry ) { @@ -743,12 +765,12 @@ static int for_each_serializable(const statement_list_t *stmts, FILE *header, if (iface_stmts) LIST_FOR_EACH_ENTRY( iface_stmt, iface_stmts, statement_t, entry ) { if (iface_stmt->type != STMT_TYPEDEF) continue; - for (type_entry = iface_stmt->u.type_list; type_entry; type_entry = type_entry->next) + if (iface_stmt->u.type_list) LIST_FOR_EACH_ENTRY(ref, iface_stmt->u.type_list, typeref_t, entry) { - if (!is_attr(type_entry->type->attrs, ATTR_ENCODE) - && !is_attr(type_entry->type->attrs, ATTR_DECODE)) + if (!is_attr(ref->type->attrs, ATTR_ENCODE) + && !is_attr(ref->type->attrs, ATTR_DECODE)) continue; - if (!proc(header, type_entry->type)) + if (!proc(header, ref->type)) return 0; } } @@ -791,26 +813,48 @@ static void write_generic_handle_routines(FILE *header) } } -static void write_typedef(FILE *header, type_t *type) +static void write_typedef(FILE *header, type_t *type, bool define) { - fprintf(header, "typedef "); - write_type_def_or_decl(header, type_alias_get_aliasee(type), FALSE, type->name); - fprintf(header, ";\n"); + type_t *t = type_alias_get_aliasee_type(type), *root = type_pointer_get_root_type(t); + if (winrt_mode && root->namespace && !is_global_namespace(root->namespace)) + { + fprintf(header, "#ifndef __cplusplus\n"); + fprintf(header, "typedef "); + write_type_v(header, type_alias_get_aliasee(type), FALSE, define, type->c_name, NAME_C); + fprintf(header, ";\n"); + if (type_get_type_detect_alias(t) != TYPE_ENUM) + { + fprintf(header, "#else /* __cplusplus */\n"); + if (t->namespace && !is_global_namespace(t->namespace)) write_namespace_start(header, t->namespace); + indent(header, 0); + fprintf(header, "typedef "); + write_type_v(header, type_alias_get_aliasee(type), FALSE, false, type->name, NAME_DEFAULT); + fprintf(header, ";\n"); + if (t->namespace && !is_global_namespace(t->namespace)) write_namespace_end(header, t->namespace); + } + fprintf(header, "#endif /* __cplusplus */\n\n"); + } + else + { + fprintf(header, "typedef "); + write_type_v(header, type_alias_get_aliasee(type), FALSE, define, type->name, NAME_DEFAULT); + fprintf(header, ";\n"); + } } int is_const_decl(const var_t *var) { - const type_t *t; + const decl_spec_t *t; /* strangely, MIDL accepts a const attribute on any pointer in the * declaration to mean that data isn't being instantiated. this appears * to be a bug, but there is no benefit to being incompatible with MIDL, * so we'll do the same thing */ - for (t = var->type; ; ) + for (t = &var->declspec; ; ) { - if (is_attr(t->attrs, ATTR_CONST)) + if (t->qualifier & TYPE_QUALIFIER_CONST) return TRUE; - else if (is_ptr(t)) - t = type_pointer_get_ref(t); + else if (is_ptr(t->type)) + t = type_pointer_get_ref(t->type); else break; } return FALSE; @@ -826,7 +870,7 @@ static void write_declaration(FILE *header, const var_t *v) } else { - switch (v->stgclass) + switch (v->declspec.stgclass) { case STG_NONE: case STG_REGISTER: /* ignored */ @@ -838,14 +882,14 @@ static void write_declaration(FILE *header, const var_t *v) fprintf(header, "extern "); break; } - write_type_def_or_decl(header, v->type, FALSE, v->name); + write_type_v(header, &v->declspec, FALSE, v->is_defined, v->name, NAME_DEFAULT); fprintf(header, ";\n\n"); } } static void write_library(FILE *header, const typelib_t *typelib) { - const UUID *uuid = get_attrp(typelib->attrs, ATTR_UUID); + const struct uuid *uuid = get_attrp(typelib->attrs, ATTR_UUID); fprintf(header, "\n"); write_guid(header, "LIBID", typelib->name, uuid); fprintf(header, "\n"); @@ -855,9 +899,9 @@ static void write_library(FILE *header, const typelib_t *typelib) const type_t* get_explicit_generic_handle_type(const var_t* var) { const type_t *t; - for (t = var->type; + for (t = var->declspec.type; is_ptr(t) || type_is_alias(t); - t = type_is_alias(t) ? type_alias_get_aliasee(t) : type_pointer_get_ref(t)) + t = type_is_alias(t) ? type_alias_get_aliasee_type(t) : type_pointer_get_ref_type(t)) if ((type_get_type_detect_alias(t) != TYPE_BASIC || type_basic_get_type(t) != TYPE_BASIC_HANDLE) && is_attr(t->attrs, ATTR_HANDLE)) return t; @@ -868,13 +912,13 @@ const var_t *get_func_handle_var( const type_t *iface, const var_t *func, unsigned char *explicit_fc, unsigned char *implicit_fc ) { const var_t *var; - const var_list_t *args = type_get_function_args( func->type ); + const var_list_t *args = type_function_get_args( func->declspec.type ); *explicit_fc = *implicit_fc = 0; if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry ) { if (!is_attr( var->attrs, ATTR_IN ) && is_attr( var->attrs, ATTR_OUT )) continue; - if (type_get_type( var->type ) == TYPE_BASIC && type_basic_get_type( var->type ) == TYPE_BASIC_HANDLE) + if (type_get_type( var->declspec.type ) == TYPE_BASIC && type_basic_get_type( var->declspec.type ) == TYPE_BASIC_HANDLE) { *explicit_fc = FC_BIND_PRIMITIVE; return var; @@ -884,7 +928,7 @@ const var_t *get_func_handle_var( const type_t *iface, const var_t *func, *explicit_fc = FC_BIND_GENERIC; return var; } - if (is_context_handle( var->type )) + if (is_context_handle( var->declspec.type )) { *explicit_fc = FC_BIND_CONTEXT; return var; @@ -893,8 +937,8 @@ const var_t *get_func_handle_var( const type_t *iface, const var_t *func, if ((var = get_attrp( iface->attrs, ATTR_IMPLICIT_HANDLE ))) { - if (type_get_type( var->type ) == TYPE_BASIC && - type_basic_get_type( var->type ) == TYPE_BASIC_HANDLE) + if (type_get_type( var->declspec.type ) == TYPE_BASIC && + type_basic_get_type( var->declspec.type ) == TYPE_BASIC_HANDLE) *implicit_fc = FC_BIND_PRIMITIVE; else *implicit_fc = FC_BIND_GENERIC; @@ -909,13 +953,13 @@ int has_out_arg_or_return(const var_t *func) { const var_t *var; - if (!is_void(type_function_get_rettype(func->type))) + if (!is_void(type_function_get_rettype(func->declspec.type))) return 1; - if (!type_get_function_args(func->type)) + if (!type_function_get_args(func->declspec.type)) return 0; - LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) + LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry ) if (is_attr(var->attrs, ATTR_OUT)) return 1; @@ -928,7 +972,7 @@ int has_out_arg_or_return(const var_t *func) int is_object(const type_t *iface) { const attr_t *attr; - if (type_is_defined(iface) && type_iface_get_inherit(iface)) + if (type_is_defined(iface) && (type_get_type(iface) == TYPE_DELEGATE || type_iface_get_inherit(iface))) return 1; if (iface->attrs) LIST_FOR_EACH_ENTRY( attr, iface->attrs, const attr_t, entry ) if (attr->type == ATTR_OBJECT || attr->type == ATTR_ODL) return 1; @@ -995,18 +1039,19 @@ static int is_override_method(const type_t *iface, const type_t *child, const va static int is_aggregate_return(const var_t *func) { - enum type_type type = type_get_type(type_function_get_rettype(func->type)); + enum type_type type = type_get_type(type_function_get_rettype(func->declspec.type)); return type == TYPE_STRUCT || type == TYPE_UNION || - type == TYPE_COCLASS || type == TYPE_INTERFACE; + type == TYPE_COCLASS || type == TYPE_INTERFACE || + type == TYPE_RUNTIMECLASS; } static char *get_vtbl_entry_name(const type_t *iface, const var_t *func) { static char buff[255]; if (is_inherited_method(iface, func)) - sprintf(buff, "%s_%s", iface->name, get_name(func)); + snprintf(buff, sizeof(buff), "%s_%s", iface->name, get_name(func)); else - sprintf(buff, "%s", get_name(func)); + snprintf(buff, sizeof(buff), "%s", get_name(func)); return buff; } @@ -1035,8 +1080,8 @@ static void write_method_macro(FILE *header, const type_t *iface, const type_t * const var_t *arg; fprintf(header, "#define %s_%s(This", name, get_name(func)); - if (type_get_function_args(func->type)) - LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry ) + if (type_function_get_args(func->declspec.type)) + LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), const var_t, entry ) fprintf(header, ",%s", arg->name); fprintf(header, ") "); @@ -1047,15 +1092,15 @@ static void write_method_macro(FILE *header, const type_t *iface, const type_t * } fprintf(header, "(This)->lpVtbl->%s(This", get_vtbl_entry_name(iface, func)); - if (type_get_function_args(func->type)) - LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry ) + if (type_function_get_args(func->declspec.type)) + LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), const var_t, entry ) fprintf(header, ",%s", arg->name); fprintf(header, ")\n"); } } } -void write_args(FILE *h, const var_list_t *args, const char *name, int method, int do_indent) +void write_args(FILE *h, const var_list_t *args, const char *name, int method, int do_indent, enum name_type name_type) { const var_t *arg; int count = 0; @@ -1078,7 +1123,10 @@ void write_args(FILE *h, const var_list_t *args, const char *name, int method, i } else fprintf(h, ","); } - write_type_decl(h, arg->type, arg->name); + /* In theory we should be writing the definition using write_type_v(..., arg->define), + * but that causes redefinition in e.g. proxy files. In fact MIDL disallows + * defining UDTs inside of an argument list. */ + write_type_v(h, &arg->declspec, FALSE, false, arg->name, name_type); if (method == 2) { const expr_t *expr = get_attrp(arg->attrs, ATTR_DEFAULTVALUE); if (expr) { @@ -1090,7 +1138,7 @@ void write_args(FILE *h, const var_list_t *args, const char *name, int method, i expr_t bstr; /* Fixup the expression type for a BSTR like midl does. */ - if (get_type_vt(arg->type) == VT_BSTR && expr->type == EXPR_STRLIT) + if (get_type_vt(arg->declspec.type) == VT_BSTR && expr->type == EXPR_STRLIT) { bstr = *expr; bstr.type = EXPR_WSTRLIT; @@ -1119,8 +1167,9 @@ static void write_cpp_method_def(FILE *header, const type_t *iface) { const var_t *func = stmt->u.var; if (!is_callas(func->attrs)) { - const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV); - const var_list_t *args = type_get_function_args(func->type); + const decl_spec_t *ret = type_function_get_ret(func->declspec.type); + const char *callconv = get_attrp(func->declspec.type->attrs, ATTR_CALLCONV); + const var_list_t *args = type_function_get_args(func->declspec.type); const var_t *arg; if (!callconv) callconv = "STDMETHODCALLTYPE"; @@ -1130,29 +1179,29 @@ static void write_cpp_method_def(FILE *header, const type_t *iface) indent(header, 0); fprintf(header, "virtual "); - write_type_decl_left(header, type_function_get_rettype(func->type)); + write_type_decl_left(header, ret); fprintf(header, "* %s %s(\n", callconv, get_name(func)); ++indentation; indent(header, 0); - write_type_decl_left(header, type_function_get_rettype(func->type)); + write_type_decl_left(header, ret); fprintf(header, " *__ret"); --indentation; if (args) { fprintf(header, ",\n"); - write_args(header, args, iface->name, 2, TRUE); + write_args(header, args, iface->name, 2, TRUE, NAME_DEFAULT); } fprintf(header, ") = 0;\n"); indent(header, 0); - write_type_decl_left(header, type_function_get_rettype(func->type)); + write_type_decl_left(header, ret); fprintf(header, " %s %s(\n", callconv, get_name(func)); - write_args(header, args, iface->name, 2, TRUE); + write_args(header, args, iface->name, 2, TRUE, NAME_DEFAULT); fprintf(header, ")\n"); indent(header, 0); fprintf(header, "{\n"); ++indentation; indent(header, 0); - write_type_decl_left(header, type_function_get_rettype(func->type)); + write_type_decl_left(header, ret); fprintf(header, " __ret;\n"); indent(header, 0); fprintf(header, "return *%s(&__ret", get_name(func)); @@ -1169,9 +1218,9 @@ static void write_cpp_method_def(FILE *header, const type_t *iface) indent(header, 0); fprintf(header, "virtual "); - write_type_decl_left(header, type_function_get_rettype(func->type)); + write_type_decl_left(header, ret); fprintf(header, " %s %s(\n", callconv, get_name(func)); - write_args(header, args, iface->name, 2, TRUE); + write_args(header, args, iface->name, 2, TRUE, NAME_DEFAULT); fprintf(header, ") = 0;\n"); if (is_aggregate_return(func)) @@ -1205,30 +1254,26 @@ static void write_inline_wrappers(FILE *header, const type_t *iface, const type_ if (!is_callas(func->attrs)) { const var_t *arg; -#ifdef __REACTOS__ - fprintf(header, "FORCEINLINE "); -#else - fprintf(header, "static FORCEINLINE "); -#endif - write_type_decl_left(header, type_function_get_rettype(func->type)); + fprintf(header, "static inline "); + write_type_decl_left(header, type_function_get_ret(func->declspec.type)); fprintf(header, " %s_%s(", name, get_name(func)); - write_args(header, type_get_function_args(func->type), name, 1, FALSE); + write_args(header, type_function_get_args(func->declspec.type), name, 1, FALSE, NAME_C); fprintf(header, ") {\n"); ++indentation; if (!is_aggregate_return(func)) { indent(header, 0); fprintf(header, "%sThis->lpVtbl->%s(This", - is_void(type_function_get_rettype(func->type)) ? "" : "return ", + is_void(type_function_get_rettype(func->declspec.type)) ? "" : "return ", get_vtbl_entry_name(iface, func)); } else { indent(header, 0); - write_type_decl_left(header, type_function_get_rettype(func->type)); + write_type_decl_left(header, type_function_get_ret(func->declspec.type)); fprintf(header, " __ret;\n"); indent(header, 0); fprintf(header, "return *This->lpVtbl->%s(This,&__ret", get_vtbl_entry_name(iface, func)); } - if (type_get_function_args(func->type)) - LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry ) + if (type_function_get_args(func->declspec.type)) + LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), const var_t, entry ) fprintf(header, ",%s", arg->name); fprintf(header, ");\n"); --indentation; @@ -1265,10 +1310,10 @@ static void do_write_c_method_def(FILE *header, const type_t *iface, const char first_iface = 0; } if (!is_callas(func->attrs)) { - const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV); + const char *callconv = get_attrp(func->declspec.type->attrs, ATTR_CALLCONV); if (!callconv) callconv = "STDMETHODCALLTYPE"; indent(header, 0); - write_type_decl_left(header, type_function_get_rettype(func->type)); + write_type_decl_left(header, type_function_get_ret(func->declspec.type)); if (is_aggregate_return(func)) fprintf(header, " *"); if (is_inherited_method(iface, func)) @@ -1281,13 +1326,13 @@ static void do_write_c_method_def(FILE *header, const type_t *iface, const char if (is_aggregate_return(func)) { fprintf(header, ",\n"); indent(header, 0); - write_type_decl_left(header, type_function_get_rettype(func->type)); + write_type_decl_left(header, type_function_get_ret(func->declspec.type)); fprintf(header, " *__ret"); } --indentation; - if (type_get_function_args(func->type)) { + if (type_function_get_args(func->declspec.type)) { fprintf(header, ",\n"); - write_args(header, type_get_function_args(func->type), name, 0, TRUE); + write_args(header, type_function_get_args(func->declspec.type), name, 0, TRUE, NAME_C); } fprintf(header, ");\n"); fprintf(header, "\n"); @@ -1314,12 +1359,12 @@ static void write_method_proto(FILE *header, const type_t *iface) const var_t *func = stmt->u.var; if (is_callas(func->attrs)) { - const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV); + const char *callconv = get_attrp(func->declspec.type->attrs, ATTR_CALLCONV); if (!callconv) callconv = "STDMETHODCALLTYPE"; /* proxy prototype */ - write_type_decl_left(header, type_function_get_rettype(func->type)); + write_type_decl_left(header, type_function_get_ret(func->declspec.type)); fprintf(header, " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(func)); - write_args(header, type_get_function_args(func->type), iface->name, 1, TRUE); + write_args(header, type_function_get_args(func->declspec.type), iface->name, 1, TRUE, NAME_DEFAULT); fprintf(header, ");\n"); /* stub prototype */ fprintf(header, "void __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(func)); @@ -1352,17 +1397,17 @@ static void write_locals(FILE *fp, const type_t *iface, int body) if (&stmt2->entry != type_iface_get_stmts(iface)) { const var_t *m = stmt2->u.var; /* proxy prototype - use local prototype */ - write_type_decl_left(fp, type_function_get_rettype(m->type)); + write_type_decl_left(fp, type_function_get_ret(m->declspec.type)); fprintf(fp, " CALLBACK %s_%s_Proxy(\n", iface->name, get_name(m)); - write_args(fp, type_get_function_args(m->type), iface->name, 1, TRUE); + write_args(fp, type_function_get_args(m->declspec.type), iface->name, 1, TRUE, NAME_DEFAULT); fprintf(fp, ")"); if (body) { - type_t *rt = type_function_get_rettype(m->type); + const decl_spec_t *rt = type_function_get_ret(m->declspec.type); fprintf(fp, "\n{\n"); fprintf(fp, " %s\n", comment); - if (rt->name && strcmp(rt->name, "HRESULT") == 0) + if (rt->type->name && strcmp(rt->type->name, "HRESULT") == 0) fprintf(fp, " return E_NOTIMPL;\n"); - else if (type_get_type(rt) != TYPE_VOID) { + else if (type_get_type(rt->type) != TYPE_VOID) { fprintf(fp, " "); write_type_decl(fp, rt, "rv"); fprintf(fp, ";\n"); @@ -1374,9 +1419,9 @@ static void write_locals(FILE *fp, const type_t *iface, int body) else fprintf(fp, ";\n"); /* stub prototype - use remotable prototype */ - write_type_decl_left(fp, type_function_get_rettype(func->type)); + write_type_decl_left(fp, type_function_get_ret(func->declspec.type)); fprintf(fp, " __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(m)); - write_args(fp, type_get_function_args(func->type), iface->name, 1, TRUE); + write_args(fp, type_function_get_args(func->declspec.type), iface->name, 1, TRUE, NAME_DEFAULT); fprintf(fp, ")"); if (body) /* Remotable methods must all return HRESULTs. */ @@ -1422,47 +1467,206 @@ void write_local_stubs(const statement_list_t *stmts) static void write_function_proto(FILE *header, const type_t *iface, const var_t *fun, const char *prefix) { - const char *callconv = get_attrp(fun->type->attrs, ATTR_CALLCONV); + const char *callconv = get_attrp(fun->declspec.type->attrs, ATTR_CALLCONV); if (!callconv) callconv = "__cdecl"; /* FIXME: do we need to handle call_as? */ - write_type_decl_left(header, type_function_get_rettype(fun->type)); + write_type_decl_left(header, type_function_get_ret(fun->declspec.type)); fprintf(header, " %s ", callconv); fprintf(header, "%s%s(\n", prefix, get_name(fun)); - if (type_get_function_args(fun->type)) - write_args(header, type_get_function_args(fun->type), iface->name, 0, TRUE); + if (type_function_get_args(fun->declspec.type)) + write_args(header, type_function_get_args(fun->declspec.type), iface->name, 0, TRUE, NAME_DEFAULT); else fprintf(header, " void"); fprintf(header, ");\n\n"); } +static void write_parameterized_type_forward(FILE *header, type_t *type) +{ + type_t *iface = type->details.parameterized.type; + char *args; + + if (type_get_type(iface) == TYPE_DELEGATE) iface = type_delegate_get_iface(iface); + + fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n"); + write_namespace_start(header, type->namespace); + + args = format_parameterized_type_args(type, "class ", ""); + write_line(header, 0, "template <%s>", args); + write_line(header, 0, "struct %s_impl;\n", iface->name); + + write_line(header, 0, "template <%s>", args); + free(args); + args = format_parameterized_type_args(type, "", ""); + write_line(header, 0, "struct %s : %s_impl<%s> {};", iface->name, iface->name, args); + free(args); + + write_namespace_end(header, type->namespace); + fprintf(header, "#endif\n\n" ); +} + +static void write_parameterized_implementation(FILE *header, type_t *type, bool define) +{ + const statement_t *stmt; + typeref_list_t *params = type->details.parameterized.params; + typeref_t *ref; + type_t *iface = type->details.parameterized.type, *base; + char *args = NULL; + + fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n"); + write_line(header, 0, "} /* extern \"C\" */"); + write_namespace_start(header, type->namespace); + + if (type_get_type(iface) == TYPE_DELEGATE) iface = type_delegate_get_iface(iface); + base = type_iface_get_inherit(iface); + + args = format_parameterized_type_args(type, "class ", ""); + write_line(header, 0, "template <%s>", args); + free(args); + write_line(header, 0, "struct %s_impl%s", iface->name, base ? strmake(" : %s", base->name) : ""); + write_line(header, 0, "{"); + + write_line(header, 1, "private:"); + if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry) + { + write_line(header, 0, "typedef typename Windows::Foundation::Internal::GetAbiType<%s>::type %s_abi;", ref->type->name, ref->type->name); + write_line(header, 0, "typedef typename Windows::Foundation::Internal::GetLogicalType<%s>::type %s_logical;", ref->type->name, ref->type->name); + } + indentation -= 1; + + write_line(header, 1, "public:"); + if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry) + write_line(header, 0, "typedef %s %s_complex;", ref->type->name, ref->type->name); + + STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) + { + const var_t *func = stmt->u.var; + if (is_callas(func->attrs)) continue; + indent(header, 1); + fprintf(header, "virtual "); + write_type_decl_left(header, &func->declspec); + fprintf(header, "%s(", get_name(func)); + write_args(header, type_function_get_args(func->declspec.type), NULL, 0, 0, NAME_DEFAULT); + fprintf(header, ") = 0;\n"); + indentation -= 1; + } + write_line(header, -1, "};"); + + write_namespace_end(header, type->namespace); + write_line(header, 0, "extern \"C\" {"); + write_line(header, 0, "#endif\n"); +} + static void write_forward(FILE *header, type_t *iface) { fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", iface->c_name); fprintf(header, "#define __%s_FWD_DEFINED__\n", iface->c_name); fprintf(header, "typedef interface %s %s;\n", iface->c_name, iface->c_name); fprintf(header, "#ifdef __cplusplus\n"); - write_namespace_start(header, iface->namespace); - write_line(header, 0, "interface %s;", iface->name); - write_namespace_end(header, iface->namespace); + if (iface->namespace && !is_global_namespace(iface->namespace)) + fprintf(header, "#define %s %s\n", iface->c_name, iface->qualified_name); + if (!iface->impl_name) + { + write_namespace_start(header, iface->namespace); + write_line(header, 0, "interface %s;", iface->name); + write_namespace_end(header, iface->namespace); + } fprintf(header, "#endif /* __cplusplus */\n"); fprintf(header, "#endif\n\n" ); } +static char *format_apicontract_macro(const type_t *type) +{ + char *name = format_namespace(type->namespace, "", "_", type->name, NULL); + int i; + for (i = strlen(name); i > 0; --i) name[i - 1] = toupper(name[i - 1]); + return name; +} + +static void write_apicontract_guard_start(FILE *header, const expr_t *expr) +{ + const type_t *type; + char *name; + int ver; + if (!winrt_mode) return; + type = expr->u.tref.type; + ver = expr->ref->u.integer.value; + name = format_apicontract_macro(type); + fprintf(header, "#if %s_VERSION >= %#x\n", name, ver); + free(name); +} + +static void write_apicontract_guard_end(FILE *header, const expr_t *expr) +{ + const type_t *type; + char *name; + int ver; + if (!winrt_mode) return; + type = expr->u.tref.type; + ver = expr->ref->u.integer.value; + name = format_apicontract_macro(type); + fprintf(header, "#endif /* %s_VERSION >= %#x */\n", name, ver); + free(name); +} + static void write_com_interface_start(FILE *header, const type_t *iface) { int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE); + expr_t *contract = get_attrp(iface->attrs, ATTR_CONTRACT); fprintf(header, "/*****************************************************************************\n"); fprintf(header, " * %s %sinterface\n", iface->name, dispinterface ? "disp" : ""); fprintf(header, " */\n"); + if (contract) write_apicontract_guard_start(header, contract); fprintf(header,"#ifndef __%s_%sINTERFACE_DEFINED__\n", iface->c_name, dispinterface ? "DISP" : ""); fprintf(header,"#define __%s_%sINTERFACE_DEFINED__\n\n", iface->c_name, dispinterface ? "DISP" : ""); } +static void write_widl_using_method_macros(FILE *header, const type_t *iface, const type_t *top_iface) +{ + const statement_t *stmt; + const char *name = top_iface->short_name ? top_iface->short_name : top_iface->name; + + if (type_iface_get_inherit(iface)) write_widl_using_method_macros(header, type_iface_get_inherit(iface), top_iface); + + STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) + { + const var_t *func = stmt->u.var; + const char *func_name; + + if (is_override_method(iface, top_iface, func)) continue; + if (is_callas(func->attrs)) continue; + + func_name = get_name(func); + fprintf(header, "#define %s_%s %s_%s\n", name, func_name, top_iface->c_name, func_name); + } +} + +static void write_widl_using_macros(FILE *header, type_t *iface) +{ + const struct uuid *uuid = get_attrp(iface->attrs, ATTR_UUID); + const char *name = iface->short_name ? iface->short_name : iface->name; + char *macro; + + if (!strcmp(iface->name, iface->c_name)) return; + + macro = format_namespace(iface->namespace, "WIDL_using_", "_", NULL, NULL); + fprintf(header, "#ifdef %s\n", macro); + + if (uuid) fprintf(header, "#define IID_%s IID_%s\n", name, iface->c_name); + if (iface->type_type == TYPE_INTERFACE) fprintf(header, "#define %sVtbl %sVtbl\n", name, iface->c_name); + fprintf(header, "#define %s %s\n", name, iface->c_name); + + if (iface->type_type == TYPE_INTERFACE) write_widl_using_method_macros(header, iface, iface); + + fprintf(header, "#endif /* %s */\n", macro); + free(macro); +} + static void write_com_interface_end(FILE *header, type_t *iface) { int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE); - const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); + const struct uuid *uuid = get_attrp(iface->attrs, ATTR_UUID); + expr_t *contract = get_attrp(iface->attrs, ATTR_CONTRACT); type_t *type; if (uuid) @@ -1475,13 +1679,20 @@ static void write_com_interface_end(FILE *header, type_t *iface) write_namespace_start(header, iface->namespace); } if (uuid) { + if (strchr(iface->name, '<')) write_line(header, 0, "template<>"); write_line(header, 0, "MIDL_INTERFACE(\"%s\")", uuid_string(uuid)); indent(header, 0); }else { indent(header, 0); - fprintf(header, "interface "); + if (strchr(iface->name, '<')) fprintf(header, "template<> struct "); + else fprintf(header, "interface "); } - if (type_iface_get_inherit(iface)) + if (iface->impl_name) + { + fprintf(header, "%s : %s\n", iface->name, iface->impl_name); + write_line(header, 1, "{"); + } + else if (type_iface_get_inherit(iface)) { fprintf(header, "%s : public %s\n", iface->name, type_iface_get_inherit(iface)->name); @@ -1495,9 +1706,9 @@ static void write_com_interface_end(FILE *header, type_t *iface) } /* dispinterfaces don't have real functions, so don't write C++ functions for * them */ - if (!dispinterface) + if (!dispinterface && !iface->impl_name) write_cpp_method_def(header, iface); - if (!type_iface_get_inherit(iface)) + if (!type_iface_get_inherit(iface) && !iface->impl_name) write_line(header, 0, "END_INTERFACE\n"); write_line(header, -1, "};"); if (!is_global_namespace(iface->namespace)) { @@ -1528,6 +1739,7 @@ static void write_com_interface_end(FILE *header, type_t *iface) fprintf(header, "#else\n"); write_inline_wrappers(header, type, type, iface->c_name); fprintf(header, "#endif\n"); + if (winrt_mode) write_widl_using_macros(header, iface); fprintf(header, "#endif\n"); fprintf(header, "\n"); fprintf(header, "#endif\n"); @@ -1540,23 +1752,27 @@ static void write_com_interface_end(FILE *header, type_t *iface) write_locals(header, iface, FALSE); fprintf(header, "\n"); } - fprintf(header,"#endif /* __%s_%sINTERFACE_DEFINED__ */\n\n", iface->c_name, dispinterface ? "DISP" : ""); + fprintf(header, "#endif /* __%s_%sINTERFACE_DEFINED__ */\n", iface->c_name, dispinterface ? "DISP" : ""); + if (contract) write_apicontract_guard_end(header, contract); + fprintf(header, "\n"); } static void write_rpc_interface_start(FILE *header, const type_t *iface) { unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION); const var_t *var = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE); + expr_t *contract = get_attrp(iface->attrs, ATTR_CONTRACT); fprintf(header, "/*****************************************************************************\n"); fprintf(header, " * %s interface (v%d.%d)\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver)); fprintf(header, " */\n"); + if (contract) write_apicontract_guard_start(header, contract); fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name); fprintf(header,"#define __%s_INTERFACE_DEFINED__\n\n", iface->name); if (var) { fprintf(header, "extern "); - write_type_decl( header, var->type, var->name ); + write_type_decl( header, &var->declspec, var->name ); fprintf(header, ";\n"); } if (old_names) @@ -1575,12 +1791,15 @@ static void write_rpc_interface_start(FILE *header, const type_t *iface) static void write_rpc_interface_end(FILE *header, const type_t *iface) { - fprintf(header,"\n#endif /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name); + expr_t *contract = get_attrp(iface->attrs, ATTR_CONTRACT); + fprintf(header, "\n#endif /* __%s_INTERFACE_DEFINED__ */\n", iface->name); + if (contract) write_apicontract_guard_end(header, contract); + fprintf(header, "\n"); } static void write_coclass(FILE *header, type_t *cocl) { - const UUID *uuid = get_attrp(cocl->attrs, ATTR_UUID); + const struct uuid *uuid = get_attrp(cocl->attrs, ATTR_UUID); fprintf(header, "/*****************************************************************************\n"); fprintf(header, " * %s coclass\n", cocl->name); @@ -1613,14 +1832,66 @@ static void write_coclass_forward(FILE *header, type_t *cocl) fprintf(header, "#endif /* defined __%s_FWD_DEFINED__ */\n\n", cocl->name ); } +static void write_apicontract(FILE *header, type_t *apicontract) +{ + char *name = format_apicontract_macro(apicontract); + fprintf(header, "#if !defined(%s_VERSION)\n", name); + fprintf(header, "#define %s_VERSION %#x\n", name, get_attrv(apicontract->attrs, ATTR_CONTRACTVERSION)); + fprintf(header, "#endif // defined(%s_VERSION)\n\n", name); + free(name); +} + +static void write_runtimeclass(FILE *header, type_t *runtimeclass) +{ + expr_t *contract = get_attrp(runtimeclass->attrs, ATTR_CONTRACT); + char *name, *c_name; + size_t i, len; + name = format_namespace(runtimeclass->namespace, "", ".", runtimeclass->name, NULL); + c_name = format_namespace(runtimeclass->namespace, "", "_", runtimeclass->name, NULL); + fprintf(header, "/*\n"); + fprintf(header, " * Class %s\n", name); + fprintf(header, " */\n"); + if (contract) write_apicontract_guard_start(header, contract); + fprintf(header, "#ifndef RUNTIMECLASS_%s_DEFINED\n", c_name); + fprintf(header, "#define RUNTIMECLASS_%s_DEFINED\n", c_name); + fprintf(header, "#if !defined(_MSC_VER) && !defined(__MINGW32__)\n"); + fprintf(header, "static const WCHAR RuntimeClass_%s[] = {", c_name); + for (i = 0, len = strlen(name); i < len; ++i) fprintf(header, "'%c',", name[i]); + fprintf(header, "0};\n"); + fprintf(header, "#elif defined(__GNUC__) && !defined(__cplusplus)\n"); + /* FIXME: MIDL generates extern const here but GCC warns if extern is initialized */ + fprintf(header, "const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = L\"%s\";\n", c_name, name); + fprintf(header, "#else\n"); + fprintf(header, "extern const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = {", c_name); + for (i = 0, len = strlen(name); i < len; ++i) fprintf(header, "'%c',", name[i]); + fprintf(header, "0};\n"); + fprintf(header, "#endif\n"); + fprintf(header, "#endif /* RUNTIMECLASS_%s_DEFINED */\n", c_name); + free(c_name); + free(name); + if (contract) write_apicontract_guard_end(header, contract); + fprintf(header, "\n"); +} + +static void write_runtimeclass_forward(FILE *header, type_t *runtimeclass) +{ + fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", runtimeclass->c_name); + fprintf(header, "#define __%s_FWD_DEFINED__\n", runtimeclass->c_name); + fprintf(header, "#ifdef __cplusplus\n"); + write_namespace_start(header, runtimeclass->namespace); + write_line(header, 0, "class %s;", runtimeclass->name); + write_namespace_end(header, runtimeclass->namespace); + fprintf(header, "#else\n"); + fprintf(header, "typedef struct %s %s;\n", runtimeclass->c_name, runtimeclass->c_name); + fprintf(header, "#endif /* defined __cplusplus */\n"); + fprintf(header, "#endif /* defined __%s_FWD_DEFINED__ */\n\n", runtimeclass->c_name); +} + static void write_import(FILE *header, const char *fname) { - char *hname, *p; - - hname = dup_basename(fname, ".idl"); - p = hname + strlen(hname) - 2; - if (p <= hname || strcmp( p, ".h" )) strcat(hname, ".h"); + char *hname = replace_extension( get_basename(fname), ".idl", "" ); + if (!strendswith( hname, ".h" )) hname = strmake( "%s.h", hname ); fprintf(header, "#include <%s>\n", hname); free(hname); } @@ -1665,18 +1936,23 @@ static void write_forward_decls(FILE *header, const statement_list_t *stmts) switch (stmt->type) { case STMT_TYPE: - if (type_get_type(stmt->u.type) == TYPE_INTERFACE) + if (type_get_type(stmt->u.type) == TYPE_INTERFACE || type_get_type(stmt->u.type) == TYPE_DELEGATE) { type_t *iface = stmt->u.type; + if (type_get_type(iface) == TYPE_DELEGATE) iface = type_delegate_get_iface(iface); if (is_object(iface) || is_attr(iface->attrs, ATTR_DISPINTERFACE)) { write_forward(header, iface); - if (iface->details.iface->async_iface) - write_forward(header, iface->details.iface->async_iface); + if (type_iface_get_async_iface(iface)) + write_forward(header, type_iface_get_async_iface(iface)); } } else if (type_get_type(stmt->u.type) == TYPE_COCLASS) write_coclass_forward(header, stmt->u.type); + else if (type_get_type(stmt->u.type) == TYPE_RUNTIMECLASS) + write_runtimeclass_forward(header, stmt->u.type); + else if (type_get_type(stmt->u.type) == TYPE_PARAMETERIZED_TYPE) + write_parameterized_type_forward(header, stmt->u.type); break; case STMT_TYPEREF: case STMT_IMPORTLIB: @@ -1705,10 +1981,11 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons switch (stmt->type) { case STMT_TYPE: - if (type_get_type(stmt->u.type) == TYPE_INTERFACE) + if (type_get_type(stmt->u.type) == TYPE_INTERFACE || type_get_type(stmt->u.type) == TYPE_DELEGATE) { - type_t *iface = stmt->u.type; - type_t *async_iface = iface->details.iface->async_iface; + type_t *iface = stmt->u.type, *async_iface; + if (type_get_type(stmt->u.type) == TYPE_DELEGATE) iface = type_delegate_get_iface(iface); + async_iface = type_iface_get_async_iface(iface); if (is_object(iface)) is_object_interface++; if (is_attr(stmt->u.type->attrs, ATTR_DISPINTERFACE) || is_object(stmt->u.type)) { @@ -1731,9 +2008,17 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons } else if (type_get_type(stmt->u.type) == TYPE_COCLASS) write_coclass(header, stmt->u.type); + else if (type_get_type(stmt->u.type) == TYPE_APICONTRACT) + write_apicontract(header, stmt->u.type); + else if (type_get_type(stmt->u.type) == TYPE_RUNTIMECLASS) + write_runtimeclass(header, stmt->u.type); + else if (type_get_type(stmt->u.type) != TYPE_PARAMETERIZED_TYPE) + write_type_definition(header, stmt->u.type, stmt->is_defined); else { - write_type_definition(header, stmt->u.type); + is_object_interface++; + write_parameterized_implementation(header, stmt->u.type, stmt->is_defined); + is_object_interface--; } break; case STMT_TYPEREF: @@ -1743,7 +2028,6 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons write_forward(header, stmt->u.type); break; case STMT_IMPORTLIB: - case STMT_MODULE: case STMT_PRAGMA: /* not included in header */ break; @@ -1752,20 +2036,29 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons break; case STMT_TYPEDEF: { - const type_list_t *type_entry = stmt->u.type_list; - for (; type_entry; type_entry = type_entry->next) - write_typedef(header, type_entry->type); + typeref_t *ref; + if (stmt->u.type_list) LIST_FOR_EACH_ENTRY(ref, stmt->u.type_list, typeref_t, entry) + write_typedef(header, ref->type, stmt->is_defined); break; } case STMT_LIBRARY: + fprintf(header, "#ifndef __%s_LIBRARY_DEFINED__\n", stmt->u.lib->name); + fprintf(header, "#define __%s_LIBRARY_DEFINED__\n", stmt->u.lib->name); write_library(header, stmt->u.lib); write_header_stmts(header, stmt->u.lib->stmts, NULL, FALSE); + fprintf(header, "#endif /* __%s_LIBRARY_DEFINED__ */\n", stmt->u.lib->name); + break; + case STMT_MODULE: + fprintf(header, "#ifndef __%s_MODULE_DEFINED__\n", stmt->u.type->name); + fprintf(header, "#define __%s_MODULE_DEFINED__\n", stmt->u.type->name); + write_header_stmts(header, stmt->u.type->details.module->stmts, stmt->u.type, FALSE); + fprintf(header, "#endif /* __%s_MODULE_DEFINED__ */\n", stmt->u.type->name); break; case STMT_CPPQUOTE: fprintf(header, "%s\n", stmt->u.str); break; case STMT_DECLARATION: - if (iface && type_get_type(stmt->u.var->type) == TYPE_FUNCTION) + if (iface && type_get_type(stmt->u.var->declspec.type) == TYPE_FUNCTION) { if (!ignore_funcs) { @@ -1802,12 +2095,15 @@ void write_header(const statement_list_t *stmts) fprintf(header, "#ifdef _WIN32\n"); fprintf(header, "#ifndef __REQUIRED_RPCNDR_H_VERSION__\n"); fprintf(header, "#define __REQUIRED_RPCNDR_H_VERSION__ 475\n"); +#ifdef __REACTOS__ fprintf(header, "#endif\n\n"); fprintf(header, "#ifdef __REACTOS__\n"); fprintf(header, "#define WIN32_LEAN_AND_MEAN\n"); fprintf(header, "#endif\n\n"); - +#else + fprintf(header, "#endif\n"); +#endif fprintf(header, "#include \n" ); fprintf(header, "#include \n" ); if (!for_each_serializable(stmts, NULL, serializable_exists)) diff --git a/sdk/tools/widl/header.h b/sdk/tools/widl/header.h index 0d44b4039fe..45066898a66 100644 --- a/sdk/tools/widl/header.h +++ b/sdk/tools/widl/header.h @@ -23,22 +23,18 @@ #include "typetree.h" -extern int is_ptrchain_attr(const var_t *var, enum attr_type t); -extern int is_aliaschain_attr(const type_t *var, enum attr_type t); -extern int is_attr(const attr_list_t *list, enum attr_type t); -extern void *get_attrp(const attr_list_t *list, enum attr_type t); -extern unsigned int get_attrv(const attr_list_t *list, enum attr_type t); extern const char* get_name(const var_t *v); -extern void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly); +extern void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, bool define, int write_callconv); extern void write_type_right(FILE *h, type_t *t, int is_field); -extern void write_type_decl(FILE *f, type_t *t, const char *name); -extern void write_type_decl_left(FILE *f, type_t *t); +extern void write_type_decl(FILE *f, const decl_spec_t *t, const char *name); +extern void write_type_decl_left(FILE *f, const decl_spec_t *ds); extern unsigned int get_context_handle_offset( const type_t *type ); extern unsigned int get_generic_handle_offset( const type_t *type ); extern int needs_space_after(type_t *t); extern int is_object(const type_t *iface); extern int is_local(const attr_list_t *list); extern int count_methods(const type_t *iface); +extern const statement_t * get_callas_source(const type_t *iface, const var_t *def); extern int need_stub(const type_t *iface); extern int need_proxy(const type_t *iface); extern int need_inline_stubs(const type_t *iface); @@ -47,7 +43,7 @@ extern int need_proxy_file(const statement_list_t *stmts); extern int need_proxy_delegation(const statement_list_t *stmts); extern int need_inline_stubs_file(const statement_list_t *stmts); extern const var_t *is_callas(const attr_list_t *list); -extern void write_args(FILE *h, const var_list_t *arg, const char *name, int obj, int do_indent); +extern void write_args(FILE *h, const var_list_t *arg, const char *name, int obj, int do_indent, enum name_type name_type); extern const type_t* get_explicit_generic_handle_type(const var_t* var); extern const var_t *get_func_handle_var( const type_t *iface, const var_t *func, unsigned char *explicit_fc, unsigned char *implicit_fc ); @@ -66,6 +62,11 @@ static inline int is_array(const type_t *t) return type_get_type(t) == TYPE_ARRAY; } +static inline int is_func(const type_t *t) +{ + return type_get_type(t) == TYPE_FUNCTION; +} + static inline int is_void(const type_t *t) { return type_get_type(t) == TYPE_VOID; @@ -83,12 +84,12 @@ static inline int is_conformant_array(const type_t *t) static inline int last_ptr(const type_t *type) { - return is_ptr(type) && !is_declptr(type_pointer_get_ref(type)); + return is_ptr(type) && !is_declptr(type_pointer_get_ref_type(type)); } static inline int last_array(const type_t *type) { - return is_array(type) && !is_array(type_array_get_element(type)); + return is_array(type) && !is_array(type_array_get_element_type(type)); } static inline int is_string_type(const attr_list_t *attrs, const type_t *type) @@ -102,7 +103,7 @@ static inline int is_context_handle(const type_t *type) const type_t *t; for (t = type; is_ptr(t) || type_is_alias(t); - t = type_is_alias(t) ? type_alias_get_aliasee(t) : type_pointer_get_ref(t)) + t = type_is_alias(t) ? type_alias_get_aliasee_type(t) : type_pointer_get_ref_type(t)) if (is_attr(t->attrs, ATTR_CONTEXTHANDLE)) return 1; return 0; diff --git a/sdk/tools/widl/parser.h b/sdk/tools/widl/parser.h index f48cacc005c..8db115dd03f 100644 --- a/sdk/tools/widl/parser.h +++ b/sdk/tools/widl/parser.h @@ -21,33 +21,27 @@ #ifndef __WIDL_PARSER_H #define __WIDL_PARSER_H -typedef struct -{ - type_t *interface; - unsigned char old_pointer_default; -} interface_info_t; +#include "widltypes.h" int parser_parse(void); +extern void parser_warning( const struct location *where, const char *message ); +extern void parser_error( const struct location *where, const char *message ); +extern void init_location( struct location *copy, const struct location *begin, const struct location *end ); + extern FILE *parser_in; -extern char *parser_text; extern int parser_debug; extern int yy_flex_debug; -int parser_lex(void); - -extern int import_stack_ptr; -int do_import(char *fname); -void abort_import(void); -void pop_import(void); - -#define parse_only import_stack_ptr +extern int parse_only; int is_type(const char *name); -int do_warning(char *toggle, warning_list_t *wnum); +int do_warning(const char *toggle, warning_list_t *wnum); int is_warning_enabled(int warning); -extern char *temp_name; +extern char *find_input_file( const char *name, const char *parent ); +extern FILE *open_input_file( const char *path ); +extern void close_all_inputs(void); #endif diff --git a/sdk/tools/widl/parser.l b/sdk/tools/widl/parser.l index da80432e050..9ff4e7b01f6 100644 --- a/sdk/tools/widl/parser.l +++ b/sdk/tools/widl/parser.l @@ -18,32 +18,25 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +%option bison-bridge +%option bison-locations %option stack %option noinput nounput noyy_top_state +%option noyywrap %option 8bit never-interactive prefix="parser_" -nl \r?\n -ws [ \f\t\r] -cident [a-zA-Z_][0-9a-zA-Z_]* -u_suffix (u|U) -l_suffix (l|L) -int [0-9]+({l_suffix}?{u_suffix}?|{u_suffix}?{l_suffix}?)? -hexd [0-9a-fA-F] -hex 0(x|X){hexd}+({l_suffix}?{u_suffix}?|{u_suffix}?{l_suffix}?)? -uuid {hexd}{8}-{hexd}{4}-{hexd}{4}-{hexd}{4}-{hexd}{12} -double [0-9]+\.[0-9]+([eE][+-]?[0-9]+)* +ws [ \f\t\r] +hd [0-9a-fA-F] +uuid {hd}{8}-{hd}{4}-{hd}{4}-{hd}{4}-{hd}{12} -%x QUOTE -%x WSTRQUOTE %x ATTR %x PP_LINE +%x PP_FILE %x PP_PRAGMA -%x SQUOTE %{ #include "config.h" -#include "wine/port.h" #include #include @@ -52,42 +45,49 @@ double [0-9]+\.[0-9]+([eE][+-]?[0-9]+)* #include #include #include - -#ifdef HAVE_UNISTD_H -#include -#else #define YY_NO_UNISTD_H -#endif #include "widl.h" #include "utils.h" #include "parser.h" -#include "wine/wpp.h" +#include "wpp_private.h" + +#define YYerror PARSER_error +#define YYSTYPE PARSER_STYPE +#define YYLTYPE PARSER_LTYPE +#define YYUNDEF PARSER_UNDEF +#define yyerror parser_error #include "parser.tab.h" -static void addcchar(char c); -static char *get_buffered_cstring(void); +static void reset_location( struct location *where, const char *input_name ); +static void update_location( struct location *where, const char *yytext ); +static void end_of_line( struct location *where ); -static char *cbuffer; -static int cbufidx; -static int cbufalloc = 0; - -static int kw_token(const char *kw); -static int attr_token(const char *kw); +#define YY_USER_INIT reset_location( yylloc, input_name ) +#define YY_USER_ACTION update_location( yylloc, yytext ); static void switch_to_acf(void); static warning_list_t *disabled_warnings = NULL; -#define MAX_IMPORT_DEPTH 20 -struct { - YY_BUFFER_STATE state; - char *input_name; - int line_number; - char *temp_name; -} import_stack[MAX_IMPORT_DEPTH]; -int import_stack_ptr = 0; +struct import_state +{ + YY_BUFFER_STATE buffer; + char *input_name; + struct location where; + struct list entry; +}; +static struct list import_stack = LIST_INIT( import_stack ); +int parse_only = 0; + +struct import +{ + const char *name; + struct list entry; +}; +static struct list imports = LIST_INIT( imports ); +static struct location previous_location; /* converts an integer in string form to an unsigned long and prints an error * on overflow */ @@ -102,24 +102,84 @@ static unsigned int xstrtoul(const char *nptr, char **endptr, int base) return val; } -UUID *parse_uuid(const char *u) +static int token_uuid( const char *str, YYSTYPE *yylval ) { - UUID* uuid = xmalloc(sizeof(UUID)); - char b[3]; - /* it would be nice to use UuidFromStringA */ - uuid->Data1 = strtoul(u, NULL, 16); - uuid->Data2 = strtoul(u+9, NULL, 16); - uuid->Data3 = strtoul(u+14, NULL, 16); - b[2] = 0; - memcpy(b, u+19, 2); uuid->Data4[0] = strtoul(b, NULL, 16); - memcpy(b, u+21, 2); uuid->Data4[1] = strtoul(b, NULL, 16); - memcpy(b, u+24, 2); uuid->Data4[2] = strtoul(b, NULL, 16); - memcpy(b, u+26, 2); uuid->Data4[3] = strtoul(b, NULL, 16); - memcpy(b, u+28, 2); uuid->Data4[4] = strtoul(b, NULL, 16); - memcpy(b, u+30, 2); uuid->Data4[5] = strtoul(b, NULL, 16); - memcpy(b, u+32, 2); uuid->Data4[6] = strtoul(b, NULL, 16); - memcpy(b, u+34, 2); uuid->Data4[7] = strtoul(b, NULL, 16); - return uuid; + struct uuid *uuid; + char tmp[3] = {0}; + + if (*str == '\"') str++; + + uuid = xmalloc( sizeof(*uuid) ); + uuid->Data1 = strtoul( str , NULL, 16 ); + uuid->Data2 = strtoul( str + 9, NULL, 16 ); + uuid->Data3 = strtoul( str + 14, NULL, 16 ); + memcpy( tmp, str + 19, 2 ); + uuid->Data4[0] = strtoul( tmp, NULL, 16 ); + memcpy( tmp, str + 21, 2 ); + uuid->Data4[1] = strtoul( tmp, NULL, 16 ); + memcpy( tmp, str + 24, 2 ); + uuid->Data4[2] = strtoul( tmp, NULL, 16 ); + memcpy( tmp, str + 26, 2 ); + uuid->Data4[3] = strtoul( tmp, NULL, 16 ); + memcpy( tmp, str + 28, 2 ); + uuid->Data4[4] = strtoul( tmp, NULL, 16 ); + memcpy( tmp, str + 30, 2 ); + uuid->Data4[5] = strtoul( tmp, NULL, 16 ); + memcpy( tmp, str + 32, 2 ); + uuid->Data4[6] = strtoul( tmp, NULL, 16 ); + memcpy( tmp, str + 34, 2 ); + uuid->Data4[7] = strtoul( tmp, NULL, 16 ); + + yylval->uuid = uuid; + return aUUID; +} + +static int token_str( int token, const char *str, YYSTYPE *yylval ) +{ + char *tmp = xstrdup( str ); + + if (token == aWSTRING || token == aSTRING || token == aSQSTRING) + { + char *src, *dst; + src = dst = ++tmp; /* skip first quote */ + while (*src) + { + if (*src == '\\') src++; + *dst++ = *src++; + } + dst[-1] = 0; /* strip last quote */ + } + + yylval->str = tmp; + return token; +} + +static int token_num( const char *yytext, YYSTYPE *yylval, int is_hex ) +{ + yylval->integer.value = xstrtoul( yytext, NULL, 0 ); + yylval->integer.is_hex = is_hex; + yylval->integer.is_long = !!strchr(yytext, 'l'); + yylval->integer.is_unsigned = !!strchr(yytext, 'u'); + return is_hex ? aHEXNUM : aNUM; +} + +static int token_ident( const char *str, YYSTYPE *yylval ) +{ + return token_str( is_type( str ) ? aKNOWNTYPE : aIDENTIFIER, str, yylval ); +} + +static int token_winrt( int token, const char *str, YYSTYPE *yylval ) +{ + if (winrt_mode) return token; + return token_ident( str, yylval ); +} + +static void winrt_enable( int ns_prefix ) +{ + if (!list_empty( &import_stack ) && !winrt_mode) error_loc( "WinRT IDL file imported in non-winrt mode.\n" ); + + use_abi_namespace = ns_prefix; + winrt_mode = TRUE; } %} @@ -130,104 +190,274 @@ UUID *parse_uuid(const char *u) ************************************************************************** */ %% -^{ws}*\#{ws}*pragma{ws}+ yy_push_state(PP_PRAGMA); -^{ws}*\#{ws}* yy_push_state(PP_LINE); -[^\n]* { - int lineno; - char *cptr, *fname; - yy_pop_state(); - lineno = (int)strtol(yytext, &cptr, 10); - if(!lineno) - error_loc("Malformed '#...' line-directive; invalid linenumber\n"); - fname = strchr(cptr, '"'); - if(!fname) - error_loc("Malformed '#...' line-directive; missing filename\n"); - fname++; - cptr = strchr(fname, '"'); - if(!cptr) - error_loc("Malformed '#...' line-directive; missing terminating \"\n"); - *cptr = '\0'; - line_number = lineno - 1; /* We didn't read the newline */ - input_name = xstrdup(fname); - } -midl_echo[^\n]* yyless(9); yy_pop_state(); return tCPPQUOTE; -winrt[^\n]* { - if(import_stack_ptr) { - if(!winrt_mode) - error_loc("winrt IDL file imported in non-winrt mode\n"); - }else { - const char *ptr = yytext+5; +{ + midl_echo/"(" { + yy_pop_state(); + yylloc->first_line -= 1; + return tCPPQUOTE; + } + winrt{ws}+ns_prefix[^\n]* { + yy_pop_state(); + yylloc->first_line -= 1; + winrt_enable( TRUE ); + } + winrt[^\n]* { + yy_pop_state(); + yylloc->first_line -= 1; + winrt_enable( FALSE ); + } + [^\n]* { + yy_pop_state(); + yylloc->first_line -= 1; + return token_str( aPRAGMA, yytext, yylval ); + } +} +[0-9]+{ws}* { + yylloc->first_line = strtoul( yytext, NULL, 10 ) - 1; + yylloc->last_line = yylloc->first_line; + yy_pop_state(); + yy_push_state(PP_FILE); + } +\"(\\[^n]|[^"\\\n])*\"{ws}* { + input_name = xstrdup( yytext + 1 ); + *strchr( input_name, '"' ) = 0; + yylloc->input_name = input_name; + } +[^"][^\n]* { yy_pop_state(); } - winrt_mode = TRUE; +{ + \] { yy_pop_state(); return ']'; } + + ({uuid}|\"{uuid}\") { return token_uuid( yytext, yylval ); } + activatable { return token_winrt( tACTIVATABLE, yytext, yylval ); } + aggregatable { return tAGGREGATABLE; } + agile { return token_winrt( tAGILE, yytext, yylval ); } + all_nodes { return tALLNODES; } + allocate { return tALLOCATE; } + annotation { return tANNOTATION; } + apartment { return tAPARTMENT; } + appobject { return tAPPOBJECT; } + async { return tASYNC; } + async_uuid { return tASYNCUUID; } + auto_handle { return tAUTOHANDLE; } + bindable { return tBINDABLE; } + both { return tBOTH; } + broadcast { return tBROADCAST; } + byte_count { return tBYTECOUNT; } + call_as { return tCALLAS; } + callback { return tCALLBACK; } + code { return tCODE; } + comm_status { return tCOMMSTATUS; } + composable { return token_winrt( tCOMPOSABLE, yytext, yylval ); } + context_handle { return tCONTEXTHANDLE; } + context_handle_noserialize { return tCONTEXTHANDLENOSERIALIZE; } + context_handle_serialize { return tCONTEXTHANDLENOSERIALIZE; } + contract { return token_winrt( tCONTRACT, yytext, yylval ); } + contractversion { return token_winrt( tCONTRACTVERSION, yytext, yylval ); } + control { return tCONTROL; } + custom { return tCUSTOM; } + decode { return tDECODE; } + default_overload { return tDEFAULT_OVERLOAD; } + defaultbind { return tDEFAULTBIND; } + defaultcollelem { return tDEFAULTCOLLELEM; } + defaultvalue { return tDEFAULTVALUE; } + defaultvtable { return tDEFAULTVTABLE; } + deprecated { return token_winrt( tDEPRECATED, yytext, yylval ); } + disable_consistency_check { return tDISABLECONSISTENCYCHECK; } + displaybind { return tDISPLAYBIND; } + dllname { return tDLLNAME; } + dont_free { return tDONTFREE; } + dual { return tDUAL; } + enable_allocate { return tENABLEALLOCATE; } + encode { return tENCODE; } + endpoint { return tENDPOINT; } + entry { return tENTRY; } + eventadd { return token_winrt( tEVENTADD, yytext, yylval ); } + eventremove { return token_winrt( tEVENTREMOVE, yytext, yylval ); } + exclusiveto { return token_winrt( tEXCLUSIVETO, yytext, yylval ); } + explicit_handle { return tEXPLICITHANDLE; } + fault_status { return tFAULTSTATUS; } + flags { return token_winrt( tFLAGS, yytext, yylval ); } + force_allocate { return tFORCEALLOCATE; } + free { return tFREE; } + handle { return tHANDLE; } + helpcontext { return tHELPCONTEXT; } + helpfile { return tHELPFILE; } + helpstring { return tHELPSTRING; } + helpstringcontext { return tHELPSTRINGCONTEXT; } + helpstringdll { return tHELPSTRINGDLL; } + hidden { return tHIDDEN; } + id { return tID; } + idempotent { return tIDEMPOTENT; } + ignore { return tIGNORE; } + iid_is { return tIIDIS; } + immediatebind { return tIMMEDIATEBIND; } + implicit_handle { return tIMPLICITHANDLE; } + in { return tIN; } + in_line { return tIN_LINE; } + input_sync { return tINPUTSYNC; } + lcid { return tLCID; } + length_is { return tLENGTHIS; } + licensed { return tLICENSED; } + local { return tLOCAL; } + marshaling_behavior { return token_winrt( tMARSHALINGBEHAVIOR, yytext, yylval ); } + maybe { return tMAYBE; } + message { return tMESSAGE; } + mta { return tMTA; } + neutral { return tNEUTRAL; } + nocode { return tNOCODE; } + nonbrowsable { return tNONBROWSABLE; } + noncreatable { return tNONCREATABLE; } + none { return token_winrt( tNONE, yytext, yylval ); } + nonextensible { return tNONEXTENSIBLE; } + notify { return tNOTIFY; } + notify_flag { return tNOTIFYFLAG; } + object { return tOBJECT; } + odl { return tODL; } + oleautomation { return tOLEAUTOMATION; } + optimize { return tOPTIMIZE; } + optional { return tOPTIONAL; } + out { return tOUT; } + overload { return tOVERLOAD; } + partial_ignore { return tPARTIALIGNORE; } + pointer_default { return tPOINTERDEFAULT; } + progid { return tPROGID; } + propget { return tPROPGET; } + propput { return tPROPPUT; } + propputref { return tPROPPUTREF; } + protected { return tPROTECTED; } + proxy { return tPROXY; } + ptr { return tPTR; } + public { return tPUBLIC; } + range { return tRANGE; } + readonly { return tREADONLY; } + ref { return tREF; } + represent_as { return tREPRESENTAS; } + requestedit { return tREQUESTEDIT; } + restricted { return tRESTRICTED; } + retval { return tRETVAL; } + single { return tSINGLE; } + single_node { return tSINGLENODE; } + size_is { return tSIZEIS; } + source { return tSOURCE; } + standard { return token_winrt( tSTANDARD, yytext, yylval ); } + static { return token_winrt( tSTATIC, yytext, yylval ); } + strict_context_handle { return tSTRICTCONTEXTHANDLE; } + string { return tSTRING; } + switch_is { return tSWITCHIS; } + switch_type { return tSWITCHTYPE; } + threading { return tTHREADING; } + transmit_as { return tTRANSMITAS; } + uidefault { return tUIDEFAULT; } + unique { return tUNIQUE; } + user_marshal { return tUSERMARSHAL; } + usesgetlasterror { return tUSESGETLASTERROR; } + uuid { return tUUID; } + v1_enum { return tV1ENUM; } + vararg { return tVARARG; } + version { return tVERSION; } + vi_progid { return tVIPROGID; } + wire_marshal { return tWIREMARSHAL; } +} + +{ + ^{ws}*\#{ws}*pragma{ws}+ { yy_push_state( PP_PRAGMA ); } + ^{ws}*midl_pragma{ws}+warning { return tPRAGMA_WARNING; } + + [0-9]+\.[0-9]+([eE][+-]?[0-9]+)* { + yylval->dbl = strtod( yytext, NULL ); + return aDOUBLE; + } +} - while(isspace(*ptr)) - ptr++; - if(!strncmp(ptr, "ns_prefix", 9) && (!*(ptr += 9) || isspace(*ptr))) - use_abi_namespace = TRUE; - } - yy_pop_state(); - } -[^\n]* parser_lval.str = xstrdup(yytext); yy_pop_state(); return aPRAGMA; -^{ws}*midl_pragma{ws}+warning return tPRAGMA_WARNING; -\" yy_push_state(QUOTE); cbufidx = 0; -\" { - yy_pop_state(); - parser_lval.str = get_buffered_cstring(); - return aSTRING; - } -L\" yy_push_state(WSTRQUOTE); cbufidx = 0; -\" { - yy_pop_state(); - parser_lval.str = get_buffered_cstring(); - return aWSTRING; - } -\' yy_push_state(SQUOTE); cbufidx = 0; -\' { - yy_pop_state(); - parser_lval.str = get_buffered_cstring(); - return aSQSTRING; - } -\\\\ | -\\\" addcchar(yytext[1]); -\\\' addcchar(yytext[1]); -\\. addcchar('\\'); addcchar(yytext[1]); -. addcchar(yytext[0]); -\[ yy_push_state(ATTR); return '['; -\] yy_pop_state(); return ']'; -{cident} return attr_token(yytext); -{uuid} { - parser_lval.uuid = parse_uuid(yytext); - return aUUID; - } -{hex} { - parser_lval.num = xstrtoul(yytext, NULL, 0); - return aHEXNUM; - } -{int} { - parser_lval.num = xstrtoul(yytext, NULL, 0); - return aNUM; - } -{double} { - parser_lval.dbl = strtod(yytext, NULL); - return aDOUBLE; - } SAFEARRAY{ws}*/\( return tSAFEARRAY; -{cident} return kw_token(yytext); -\n line_number++; -{ws} -\<\< return SHL; -\>\> return SHR; -\-\> return MEMBERPTR; -== return EQUALITY; -!= return INEQUALITY; -\>= return GREATEREQUAL; -\<= return LESSEQUAL; -\|\| return LOGICALOR; -&& return LOGICALAND; -\.\.\. return ELLIPSIS; -. return yytext[0]; + +{ + ^{ws}*\#{ws}* { yy_push_state(PP_LINE); } + \[ { yy_push_state(ATTR); return '['; } + + FALSE { return tFALSE; } + NULL { return tNULL; } + TRUE { return tTRUE; } + _?_?cdecl { return token_str( tCDECL, "__cdecl", yylval ); } + _?_?pascal { return token_str( tPASCAL, "__pascal", yylval ); } + _?_?stdcall { return token_str( tSTDCALL, "__stdcall", yylval ); } + __?fastcall { return token_str( tFASTCALL, "__fastcall", yylval ); } + __int32 { return tINT32; } + __int3264 { return tINT3264; } + __int64 { return tINT64; } + apicontract { return token_winrt( tAPICONTRACT, yytext, yylval ); } + boolean { return tBOOLEAN; } + byte { return tBYTE; } + case { return tCASE; } + char { return tCHAR; } + coclass { return tCOCLASS; } + const { return tCONST; } + cpp_quote { return tCPPQUOTE; } + declare { return token_winrt( tDECLARE, yytext, yylval ); } + default { return tDEFAULT; } + delegate { return token_winrt( tDELEGATE, yytext, yylval ); } + dispinterface { return tDISPINTERFACE; } + double { return tDOUBLE; } + enum { return tENUM; } + error_status_t { return tERRORSTATUST; } + extern { return tEXTERN; } + float { return tFLOAT; } + handle_t { return tHANDLET; } + hyper { return tHYPER; } + import { return tIMPORT; } + importlib { return tIMPORTLIB; } + inline { return tINLINE; } + int { return tINT; } + interface { return tINTERFACE; } + library { return tLIBRARY; } + long { return tLONG; } + methods { return tMETHODS; } + module { return tMODULE; } + namespace { return token_winrt( tNAMESPACE, yytext, yylval ); } + properties { return tPROPERTIES; } + register { return tREGISTER; } + requires { return token_winrt( tREQUIRES, yytext, yylval ); } + runtimeclass { return token_winrt( tRUNTIMECLASS, yytext, yylval ); } + short { return tSHORT; } + signed { return tSIGNED; } + sizeof { return tSIZEOF; } + small { return tSMALL; } + static { return tSTATIC; } + struct { return tSTRUCT; } + switch { return tSWITCH; } + typedef { return tTYPEDEF; } + union { return tUNION; } + unsigned { return tUNSIGNED; } + void { return tVOID; } + wchar_t { return tWCHAR; } + + [a-zA-Z_][0-9a-zA-Z_]* { return token_ident( yytext, yylval ); } + + 0[xX]{hd}+[uU]?[lL]? { return token_num( yytext, yylval, TRUE ); } + [0-9]+[uU]?[lL]? { return token_num( yytext, yylval, FALSE ); } + + L\"(\\.|[^"\\])*\" { return token_str( aWSTRING, yytext + 1, yylval ); } + \"(\\.|[^"\\])*\" { return token_str( aSTRING, yytext, yylval ); } + \'(\\.|[^'\\])*\' { return token_str( aSQSTRING, yytext, yylval ); } + + \n { end_of_line( yylloc ); } + {ws} {} + \<\< { return SHL; } + \>\> { return SHR; } + \-\> { return MEMBERPTR; } + == { return EQUALITY; } + != { return INEQUALITY; } + \>= { return GREATEREQUAL; } + \<= { return LESSEQUAL; } + \|\| { return LOGICALOR; } + && { return LOGICALAND; } + \.\.\. { return ELLIPSIS; } + . { return yytext[0]; } +} + <> { - if (import_stack_ptr) + if (!list_empty( &import_stack )) return aEOF; if (acf_name) { @@ -238,371 +468,172 @@ SAFEARRAY{ws}*/\( return tSAFEARRAY; } %% -#ifndef parser_wrap -int parser_wrap(void) +static void print_imports(void) { - return 1; -} -#endif + struct import_state *state, *next; -struct keyword { - const char *kw; - int token; -}; + if (list_empty( &import_stack )) return; -/* This table MUST be alphabetically sorted on the kw field */ -static const struct keyword keywords[] = { - {"FALSE", tFALSE}, - {"NULL", tNULL}, - {"TRUE", tTRUE}, - {"__cdecl", tCDECL}, - {"__fastcall", tFASTCALL}, - {"__int32", tINT32}, - {"__int3264", tINT3264}, - {"__int64", tINT64}, - {"__pascal", tPASCAL}, - {"__stdcall", tSTDCALL}, - {"_cdecl", tCDECL}, - {"_fastcall", tFASTCALL}, - {"_pascal", tPASCAL}, - {"_stdcall", tSTDCALL}, - {"boolean", tBOOLEAN}, - {"byte", tBYTE}, - {"case", tCASE}, - {"cdecl", tCDECL}, - {"char", tCHAR}, - {"coclass", tCOCLASS}, - {"const", tCONST}, - {"cpp_quote", tCPPQUOTE}, - {"default", tDEFAULT}, - {"dispinterface", tDISPINTERFACE}, - {"double", tDOUBLE}, - {"enum", tENUM}, - {"error_status_t", tERRORSTATUST}, - {"extern", tEXTERN}, - {"float", tFLOAT}, - {"handle_t", tHANDLET}, - {"hyper", tHYPER}, - {"import", tIMPORT}, - {"importlib", tIMPORTLIB}, - {"inline", tINLINE}, - {"int", tINT}, - {"interface", tINTERFACE}, - {"library", tLIBRARY}, - {"long", tLONG}, - {"methods", tMETHODS}, - {"module", tMODULE}, - {"namespace", tNAMESPACE}, - {"pascal", tPASCAL}, - {"properties", tPROPERTIES}, - {"register", tREGISTER}, - {"short", tSHORT}, - {"signed", tSIGNED}, - {"sizeof", tSIZEOF}, - {"small", tSMALL}, - {"static", tSTATIC}, - {"stdcall", tSTDCALL}, - {"struct", tSTRUCT}, - {"switch", tSWITCH}, - {"typedef", tTYPEDEF}, - {"union", tUNION}, - {"unsigned", tUNSIGNED}, - {"void", tVOID}, - {"wchar_t", tWCHAR}, -}; -#define NKEYWORDS (sizeof(keywords)/sizeof(keywords[0])) - -/* keywords only recognized in attribute lists - * This table MUST be alphabetically sorted on the kw field - */ -static const struct keyword attr_keywords[] = -{ - {"aggregatable", tAGGREGATABLE}, - {"all_nodes", tALLNODES}, - {"allocate", tALLOCATE}, - {"annotation", tANNOTATION}, - {"apartment", tAPARTMENT}, - {"appobject", tAPPOBJECT}, - {"async", tASYNC}, - {"async_uuid", tASYNCUUID}, - {"auto_handle", tAUTOHANDLE}, - {"bindable", tBINDABLE}, - {"both", tBOTH}, - {"broadcast", tBROADCAST}, - {"byte_count", tBYTECOUNT}, - {"call_as", tCALLAS}, - {"callback", tCALLBACK}, - {"code", tCODE}, - {"comm_status", tCOMMSTATUS}, - {"context_handle", tCONTEXTHANDLE}, - {"context_handle_noserialize", tCONTEXTHANDLENOSERIALIZE}, - {"context_handle_serialize", tCONTEXTHANDLENOSERIALIZE}, - {"control", tCONTROL}, - {"decode", tDECODE}, - {"defaultbind", tDEFAULTBIND}, - {"defaultcollelem", tDEFAULTCOLLELEM}, - {"defaultvalue", tDEFAULTVALUE}, - {"defaultvtable", tDEFAULTVTABLE}, - {"disable_consistency_check", tDISABLECONSISTENCYCHECK}, - {"displaybind", tDISPLAYBIND}, - {"dllname", tDLLNAME}, - {"dont_free", tDONTFREE}, - {"dual", tDUAL}, - {"enable_allocate", tENABLEALLOCATE}, - {"encode", tENCODE}, - {"endpoint", tENDPOINT}, - {"entry", tENTRY}, - {"explicit_handle", tEXPLICITHANDLE}, - {"fault_status", tFAULTSTATUS}, - {"force_allocate", tFORCEALLOCATE}, - {"free", tFREE}, - {"handle", tHANDLE}, - {"helpcontext", tHELPCONTEXT}, - {"helpfile", tHELPFILE}, - {"helpstring", tHELPSTRING}, - {"helpstringcontext", tHELPSTRINGCONTEXT}, - {"helpstringdll", tHELPSTRINGDLL}, - {"hidden", tHIDDEN}, - {"id", tID}, - {"idempotent", tIDEMPOTENT}, - {"ignore", tIGNORE}, - {"iid_is", tIIDIS}, - {"immediatebind", tIMMEDIATEBIND}, - {"implicit_handle", tIMPLICITHANDLE}, - {"in", tIN}, - {"in_line", tIN_LINE}, - {"input_sync", tINPUTSYNC}, - {"lcid", tLCID}, - {"length_is", tLENGTHIS}, - {"licensed", tLICENSED}, - {"local", tLOCAL}, - {"maybe", tMAYBE}, - {"message", tMESSAGE}, - {"neutral", tNEUTRAL}, - {"nocode", tNOCODE}, - {"nonbrowsable", tNONBROWSABLE}, - {"noncreatable", tNONCREATABLE}, - {"nonextensible", tNONEXTENSIBLE}, - {"notify", tNOTIFY}, - {"notify_flag", tNOTIFYFLAG}, - {"object", tOBJECT}, - {"odl", tODL}, - {"oleautomation", tOLEAUTOMATION}, - {"optimize", tOPTIMIZE}, - {"optional", tOPTIONAL}, - {"out", tOUT}, - {"partial_ignore", tPARTIALIGNORE}, - {"pointer_default", tPOINTERDEFAULT}, - {"progid", tPROGID}, - {"propget", tPROPGET}, - {"propput", tPROPPUT}, - {"propputref", tPROPPUTREF}, - {"proxy", tPROXY}, - {"ptr", tPTR}, - {"public", tPUBLIC}, - {"range", tRANGE}, - {"readonly", tREADONLY}, - {"ref", tREF}, - {"represent_as", tREPRESENTAS}, - {"requestedit", tREQUESTEDIT}, - {"restricted", tRESTRICTED}, - {"retval", tRETVAL}, - {"single", tSINGLE}, - {"single_node", tSINGLENODE}, - {"size_is", tSIZEIS}, - {"source", tSOURCE}, - {"strict_context_handle", tSTRICTCONTEXTHANDLE}, - {"string", tSTRING}, - {"switch_is", tSWITCHIS}, - {"switch_type", tSWITCHTYPE}, - {"threading", tTHREADING}, - {"transmit_as", tTRANSMITAS}, - {"uidefault", tUIDEFAULT}, - {"unique", tUNIQUE}, - {"user_marshal", tUSERMARSHAL}, - {"usesgetlasterror", tUSESGETLASTERROR}, - {"uuid", tUUID}, - {"v1_enum", tV1ENUM}, - {"vararg", tVARARG}, - {"version", tVERSION}, - {"vi_progid", tVIPROGID}, - {"wire_marshal", tWIREMARSHAL}, -}; - -/* attributes TODO: - custom - first_is - last_is - max_is - min_is -*/ - -#define KWP(p) ((const struct keyword *)(p)) - -static int kw_cmp_func(const void *s1, const void *s2) -{ - return strcmp(KWP(s1)->kw, KWP(s2)->kw); + fprintf( stderr, "In file included from " ); + LIST_FOR_EACH_ENTRY_SAFE_REV( state, next, &import_stack, struct import_state, entry ) + { + if (&next->entry == &import_stack) break; + fprintf( stderr, "%s:%d,\n", state->input_name, state->where.first_line ); + fprintf( stderr, " from "); + } + fprintf( stderr, "%s:%d:\n", state->input_name, state->where.first_line ); } -static int kw_token(const char *kw) +struct location pop_import(void) { - struct keyword key, *kwp; - key.kw = kw; - kwp = bsearch(&key, keywords, NKEYWORDS, sizeof(keywords[0]), kw_cmp_func); - if (kwp && (winrt_mode || kwp->token != tNAMESPACE)) { - parser_lval.str = xstrdup(kwp->kw); - return kwp->token; - } - parser_lval.str = xstrdup(kw); - return is_type(kw) ? aKNOWNTYPE : aIDENTIFIER; + struct list *entry = list_head( &import_stack ); + struct import_state *state; + struct location where; + assert( entry ); + + state = LIST_ENTRY( entry, struct import_state, entry ); + list_remove( &state->entry ); + parse_only = !list_empty( &import_stack ); + + if (yyin) fclose( yyin ); + yy_delete_buffer( YY_CURRENT_BUFFER ); + yy_switch_to_buffer( state->buffer ); + + input_name = state->input_name; + where = state->where; + free( state ); + return where; } -static int attr_token(const char *kw) +void push_import( const char *import_name, struct location *where ) { - struct keyword key, *kwp; - key.kw = kw; - kwp = bsearch(&key, attr_keywords, sizeof(attr_keywords)/sizeof(attr_keywords[0]), - sizeof(attr_keywords[0]), kw_cmp_func); - if (kwp) { - parser_lval.str = xstrdup(kwp->kw); - return kwp->token; - } - return kw_token(kw); -} + struct import_state *state; + struct import *import; + FILE *file; -static void addcchar(char c) -{ - if(cbufidx >= cbufalloc) - { - cbufalloc += 1024; - cbuffer = xrealloc(cbuffer, cbufalloc * sizeof(cbuffer[0])); - if(cbufalloc > 65536) - parser_warning("Reallocating string buffer larger than 64kB\n"); - } - cbuffer[cbufidx++] = c; -} + state = xmalloc( sizeof(struct import_state )); + list_add_head( &import_stack, &state->entry ); + parse_only = !list_empty( &import_stack ); -static char *get_buffered_cstring(void) -{ - addcchar(0); - return xstrdup(cbuffer); -} + state->buffer = YY_CURRENT_BUFFER; + state->input_name = input_name; + state->where = *where; + input_name = NULL; -void pop_import(void) -{ - int ptr = import_stack_ptr-1; + /* reset buffer for <>, in case import fails or already imported */ + yy_scan_string( "" ); - fclose(yyin); - yy_delete_buffer( YY_CURRENT_BUFFER ); - yy_switch_to_buffer( import_stack[ptr].state ); - if (temp_name) { - unlink(temp_name); - free(temp_name); - } - temp_name = import_stack[ptr].temp_name; - input_name = import_stack[ptr].input_name; - line_number = import_stack[ptr].line_number; - import_stack_ptr--; -} + LIST_FOR_EACH_ENTRY( import, &imports, struct import, entry ) + if (!strcmp( import->name, import_name )) return; /* already imported */ + if (!strcmp( idl_name, import_name )) return; /* already imported */ -struct imports { - char *name; - struct imports *next; -} *first_import; + import = xmalloc( sizeof(struct import) ); + import->name = xstrdup( import_name ); + list_add_tail( &imports, &import->entry ); -int do_import(char *fname) -{ - FILE *f; - char *path, *name; - struct imports *import; - int ptr = import_stack_ptr; - int ret, fd; + input_name = find_input_file( import_name, state->input_name ); + file = open_input_file( input_name ); + reset_location( where, input_name ); - import = first_import; - while (import && strcmp(import->name, fname)) - import = import->next; - if (import) return 0; /* already imported */ - - import = xmalloc(sizeof(struct imports)); - import->name = xstrdup(fname); - import->next = first_import; - first_import = import; - - /* don't search for a file name with a path in the include directories, - * for compatibility with MIDL */ - if (strchr( fname, '/' ) || strchr( fname, '\\' )) - path = xstrdup( fname ); - else if (!(path = wpp_find_include( fname, input_name ))) - error_loc("Unable to open include file %s\n", fname); - - if (import_stack_ptr == MAX_IMPORT_DEPTH) - error_loc("Exceeded max import depth\n"); - - import_stack[ptr].temp_name = temp_name; - import_stack[ptr].input_name = input_name; - import_stack[ptr].line_number = line_number; - import_stack_ptr++; - input_name = path; - line_number = 1; - - name = xstrdup( "widl.XXXXXX" ); - if((fd = mkstemps( name, 0 )) == -1) - error("Could not generate a temp name from %s\n", name); - - temp_name = name; - if (!(f = fdopen(fd, "wt"))) - error("Could not open fd %s for writing\n", name); - - ret = wpp_parse( path, f ); - fclose( f ); - if (ret) exit(1); - - if((f = fopen(temp_name, "r")) == NULL) - error_loc("Unable to open %s\n", temp_name); - - import_stack[ptr].state = YY_CURRENT_BUFFER; - yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE)); - return 1; -} - -void abort_import(void) -{ - int ptr; - - for (ptr=0; ptrfirst_line = 1; + where->last_line = 1; + where->first_column = 1; + where->last_column = 1; + where->input_name = xstrdup( input_name ); +} - if((f = fopen(temp_name, "r")) == NULL) - error_loc("Unable to open %s\n", temp_name); +static void update_location( struct location *where, const char *yytext ) +{ + int len = strlen( yytext ); + previous_location = *where; + where->first_column = where->last_column; + where->last_column += len; +} - import_stack[ptr].state = YY_CURRENT_BUFFER; - yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE)); +static void end_of_line( struct location *where ) +{ + where->first_line++; + where->last_line++; + where->first_column = 1; + where->last_column = 1; +} + +void init_location( struct location *where, const struct location *begin, const struct location *end ) +{ + if (!begin) begin = &previous_location; + *where = *begin; + + if (end) + { + where->last_line = end->last_line; + where->last_column = end->last_column; + } + else + { + where->first_line = begin->last_line; + where->first_column = begin->last_column; + } +} + +static void diagnostic( const struct location *where, const char *type, const char *message ) +{ + char buffer[1024], *line = NULL; + FILE *file; + int i; + + if (!where) where = &previous_location; + + print_imports(); + + fprintf( stderr, "%s:%d:%d: %s: %s\n", where->input_name, where->first_line, where->first_column, type, message ); + + if (!where->input_name || !(file = fopen( where->input_name, "r" ))) return; + for (i = 0; i < where->first_line; i++) if (!(line = fgets( buffer, sizeof(buffer), file ))) break; + fclose( file ); + if (!line) return; + fprintf( stderr, "%s", line ); + + line = buffer; + for (i = 0; i < where->first_column - 1; i++) *line++ = ' '; + *line++ = '^'; + for (i = where->first_column + 1; i < where->last_column; i++) *line++ = '~'; + *line = '\0'; + fprintf( stderr, "%s\n", buffer ); +} + +void parser_error( const struct location *where, const char *message ) +{ + diagnostic( where, "error", message ); +} + +void parser_warning( const struct location *where, const char *message ) +{ + diagnostic( where, "warning", message ); } static void warning_disable(int warning) @@ -628,7 +659,7 @@ static void warning_enable(int warning) } } -int do_warning(char *toggle, warning_list_t *wnum) +int do_warning(const char *toggle, warning_list_t *wnum) { warning_t *warning, *next; int ret = 1; @@ -641,7 +672,7 @@ int do_warning(char *toggle, warning_list_t *wnum) if(!strcmp(toggle, "disable")) LIST_FOR_EACH_ENTRY(warning, wnum, warning_t, entry) warning_disable(warning->num); - else if(!strcmp(toggle, "enable")) + else if(!strcmp(toggle, "enable") || !strcmp(toggle, "default")) LIST_FOR_EACH_ENTRY(warning, wnum, warning_t, entry) warning_enable(warning->num); else diff --git a/sdk/tools/widl/parser.y b/sdk/tools/widl/parser.y index bbb03e8ef74..0e879688d58 100644 --- a/sdk/tools/widl/parser.y +++ b/sdk/tools/widl/parser.y @@ -38,80 +38,43 @@ #include "expr.h" #include "typetree.h" -static unsigned char pointer_default = FC_UP; - -typedef struct list typelist_t; -struct typenode { - type_t *type; - struct list entry; -}; - struct _import_t { char *name; int import_performed; }; -typedef struct _decl_spec_t -{ - type_t *type; - attr_list_t *attrs; - enum storage_class stgclass; -} decl_spec_t; - -typelist_t incomplete_types = LIST_INIT(incomplete_types); - -static void fix_incomplete(void); -static void fix_incomplete_types(type_t *complete_type); - static str_list_t *append_str(str_list_t *list, char *str); -static attr_list_t *append_attr(attr_list_t *list, attr_t *attr); -static attr_list_t *append_attr_list(attr_list_t *new_list, attr_list_t *old_list); -static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, attr_t *attr, enum storage_class stgclass); -static attr_t *make_attr(enum attr_type type); -static attr_t *make_attrv(enum attr_type type, unsigned int val); -static attr_t *make_attrp(enum attr_type type, void *val); +static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, + enum storage_class stgclass, enum type_qualifier qual, enum function_specifier func_specifier); static expr_list_t *append_expr(expr_list_t *list, expr_t *expr); -static type_t *append_array(type_t *chain, expr_t *expr); -static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const declarator_t *decl, int top); +static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, declarator_t *decl, int top); static var_list_t *set_var_types(attr_list_t *attrs, decl_spec_t *decl_spec, declarator_list_t *decls); -static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface); -static ifref_t *make_ifref(type_t *iface); static var_list_t *append_var_list(var_list_t *list, var_list_t *vars); static declarator_list_t *append_declarator(declarator_list_t *list, declarator_t *p); static declarator_t *make_declarator(var_t *var); static type_t *make_safearray(type_t *type); static typelib_t *make_library(const char *name, const attr_list_t *attrs); -static type_t *append_chain_type(type_t *chain, type_t *type); +static void append_array(declarator_t *decl, expr_t *expr); +static void append_chain_type(declarator_t *decl, type_t *type, enum type_qualifier qual); +static void append_chain_callconv( struct location where, type_t *chain, char *callconv ); static warning_list_t *append_warning(warning_list_t *, int); -static type_t *reg_typedefs(decl_spec_t *decl_spec, var_list_t *names, attr_list_t *attrs); -static type_t *find_type_or_error(const char *name, int t); -static type_t *find_type_or_error2(char *name, int t); +static type_t *reg_typedefs( struct location where, decl_spec_t *decl_spec, var_list_t *names, attr_list_t *attrs ); +static type_t *find_type_or_error(struct namespace *parent, const char *name); +static struct namespace *find_namespace_or_error(struct namespace *namespace, const char *name); static var_t *reg_const(var_t *var); -static void push_namespace(const char *name); -static void pop_namespace(const char *name); +static void push_namespaces(str_list_t *names); +static void pop_namespaces(str_list_t *names); +static void push_parameters_namespace(const char *name); +static void pop_parameters_namespace(const char *name); -static char *gen_name(void); -static void check_arg_attrs(const var_t *arg); +static statement_list_t *append_parameterized_type_stmts(statement_list_t *stmts); static void check_statements(const statement_list_t *stmts, int is_inside_library); static void check_all_user_types(const statement_list_t *stmts); -static attr_list_t *check_iface_attrs(const char *name, attr_list_t *attrs); -static attr_list_t *check_function_attrs(const char *name, attr_list_t *attrs); -static attr_list_t *check_typedef_attrs(attr_list_t *attrs); -static attr_list_t *check_enum_attrs(attr_list_t *attrs); -static attr_list_t *check_struct_attrs(attr_list_t *attrs); -static attr_list_t *check_union_attrs(attr_list_t *attrs); -static attr_list_t *check_field_attrs(const char *name, attr_list_t *attrs); -static attr_list_t *check_library_attrs(const char *name, attr_list_t *attrs); -static attr_list_t *check_dispiface_attrs(const char *name, attr_list_t *attrs); -static attr_list_t *check_module_attrs(const char *name, attr_list_t *attrs); -static attr_list_t *check_coclass_attrs(const char *name, attr_list_t *attrs); -const char *get_attr_display_name(enum attr_type type); static void add_explicit_handle_if_necessary(const type_t *iface, var_t *func); -static void check_def(const type_t *t); static void check_async_uuid(type_t *iface); @@ -124,21 +87,50 @@ static statement_t *make_statement_pragma(const char *str); static statement_t *make_statement_cppquote(const char *str); static statement_t *make_statement_importlib(const char *str); static statement_t *make_statement_module(type_t *type); -static statement_t *make_statement_typedef(var_list_t *names); +static statement_t *make_statement_typedef(var_list_t *names, bool is_defined); static statement_t *make_statement_import(const char *str); +static statement_t *make_statement_parameterized_type(type_t *type, typeref_list_t *params); +static statement_t *make_statement_delegate(type_t *ret, var_list_t *args); static statement_list_t *append_statement(statement_list_t *list, statement_t *stmt); static statement_list_t *append_statements(statement_list_t *, statement_list_t *); -static attr_list_t *append_attribs(attr_list_t *, attr_list_t *); static struct namespace global_namespace = { NULL, NULL, LIST_INIT(global_namespace.entry), LIST_INIT(global_namespace.children) }; static struct namespace *current_namespace = &global_namespace; +static struct namespace *parameters_namespace = NULL; +static statement_list_t *parameterized_type_stmts = NULL; static typelib_t *current_typelib; %} + +%code requires +{ + +#define PARSER_LTYPE struct location + +} + +%code provides +{ + +int parser_lex( PARSER_STYPE *yylval, PARSER_LTYPE *yylloc ); +void push_import( const char *fname, PARSER_LTYPE *yylloc ); +PARSER_LTYPE pop_import(void); + +# define YYLLOC_DEFAULT( cur, rhs, n ) \ + do { if (n) init_location( &(cur), &YYRHSLOC( rhs, 1 ), &YYRHSLOC( rhs, n ) ); \ + else init_location( &(cur), &YYRHSLOC( rhs, 0 ), NULL ); } while(0) + +} + +%define api.prefix {parser_} +%define api.pure full +%define parse.error verbose +%locations + %union { attr_t *attr; attr_list_t *attr_list; @@ -154,24 +146,31 @@ static typelib_t *current_typelib; statement_list_t *stmt_list; warning_t *warning; warning_list_t *warning_list; - ifref_t *ifref; - ifref_list_t *ifref_list; + typeref_t *typeref; + typeref_list_t *typeref_list; char *str; - UUID *uuid; + struct uuid *uuid; unsigned int num; + struct integer integer; double dbl; - interface_info_t ifinfo; typelib_t *typelib; struct _import_t *import; struct _decl_spec_t *declspec; enum storage_class stgclass; + enum type_qualifier type_qualifier; + enum function_specifier function_specifier; + struct namespace *namespace; } %token aIDENTIFIER aPRAGMA %token aKNOWNTYPE -%token aNUM aHEXNUM +%token aNUM aHEXNUM %token aDOUBLE %token aSTRING aWSTRING aSQSTRING +%token tCDECL +%token tFASTCALL +%token tPASCAL +%token tSTDCALL %token aUUID %token aEOF aACF %token SHL SHR @@ -180,23 +179,40 @@ static typelib_t *current_typelib; %token GREATEREQUAL LESSEQUAL %token LOGICALOR LOGICALAND %token ELLIPSIS -%token tAGGREGATABLE tALLNODES tALLOCATE tANNOTATION tAPPOBJECT tASYNC tASYNCUUID +%token tACTIVATABLE +%token tAGGREGATABLE +%token tAGILE +%token tALLNODES tALLOCATE tANNOTATION +%token tAPICONTRACT +%token tAPPOBJECT tASYNC tASYNCUUID %token tAUTOHANDLE tBINDABLE tBOOLEAN tBROADCAST tBYTE tBYTECOUNT -%token tCALLAS tCALLBACK tCASE tCDECL tCHAR tCOCLASS tCODE tCOMMSTATUS +%token tCALLAS tCALLBACK tCASE tCHAR tCOCLASS tCODE tCOMMSTATUS +%token tCOMPOSABLE %token tCONST tCONTEXTHANDLE tCONTEXTHANDLENOSERIALIZE -%token tCONTEXTHANDLESERIALIZE tCONTROL tCPPQUOTE +%token tCONTEXTHANDLESERIALIZE +%token tCONTRACT +%token tCONTRACTVERSION +%token tCONTROL tCPPQUOTE +%token tCUSTOM +%token tDECLARE %token tDECODE tDEFAULT tDEFAULTBIND +%token tDELEGATE +%token tDEFAULT_OVERLOAD %token tDEFAULTCOLLELEM %token tDEFAULTVALUE %token tDEFAULTVTABLE +%token tDEPRECATED %token tDISABLECONSISTENCYCHECK tDISPLAYBIND %token tDISPINTERFACE %token tDLLNAME tDONTFREE tDOUBLE tDUAL %token tENABLEALLOCATE tENCODE tENDPOINT %token tENTRY tENUM tERRORSTATUST +%token tEVENTADD tEVENTREMOVE +%token tEXCLUSIVETO %token tEXPLICITHANDLE tEXTERN %token tFALSE -%token tFASTCALL tFAULTSTATUS +%token tFAULTSTATUS +%token tFLAGS %token tFLOAT tFORCEALLOCATE %token tHANDLE %token tHANDLET @@ -216,39 +232,46 @@ static typelib_t *current_typelib; %token tLENGTHIS tLIBRARY %token tLICENSED tLOCAL %token tLONG +%token tMARSHALINGBEHAVIOR %token tMAYBE tMESSAGE %token tMETHODS %token tMODULE +%token tMTA %token tNAMESPACE %token tNOCODE tNONBROWSABLE %token tNONCREATABLE +%token tNONE %token tNONEXTENSIBLE %token tNOTIFY tNOTIFYFLAG %token tNULL %token tOBJECT tODL tOLEAUTOMATION %token tOPTIMIZE tOPTIONAL %token tOUT -%token tPARTIALIGNORE tPASCAL +%token tOVERLOAD +%token tPARTIALIGNORE %token tPOINTERDEFAULT %token tPRAGMA_WARNING %token tPROGID tPROPERTIES %token tPROPGET tPROPPUT tPROPPUTREF +%token tPROTECTED %token tPROXY tPTR %token tPUBLIC %token tRANGE %token tREADONLY tREF %token tREGISTER tREPRESENTAS %token tREQUESTEDIT +%token tREQUIRES %token tRESTRICTED %token tRETVAL +%token tRUNTIMECLASS %token tSAFEARRAY %token tSHORT %token tSIGNED tSINGLENODE %token tSIZEIS tSIZEOF %token tSMALL %token tSOURCE +%token tSTANDARD %token tSTATIC -%token tSTDCALL %token tSTRICTCONTEXTHANDLE %token tSTRING tSTRUCT %token tSWITCH tSWITCHIS tSWITCHTYPE @@ -266,25 +289,42 @@ static typelib_t *current_typelib; %token tWCHAR tWIREMARSHAL %token tAPARTMENT tNEUTRAL tSINGLE tFREE tBOTH -%type attribute type_qualifier function_specifier acf_attribute -%type m_attributes attributes attrib_list m_type_qual_list +%type access_attr +%type attribute acf_attribute +%type m_attributes attributes attrib_list %type acf_attributes acf_attribute_list +%type dispattributes %type str_list %type m_expr expr expr_const expr_int_const array m_bitfield %type m_exprs /* exprs expr_list */ expr_list_int_const -%type interfacehdr +%type contract_req +%type static_attr +%type activatable_attr +%type composable_attr +%type deprecated_attr +%type delegatedef %type storage_cls_spec -%type decl_spec decl_spec_no_type m_decl_spec_no_type -%type inherit interface interfacedef interfacedec -%type dispinterface dispinterfacehdr dispinterfacedef -%type module modulehdr moduledef -%type namespacedef +%type type_qualifier m_type_qual_list +%type function_specifier +%type decl_spec unqualified_decl_spec decl_spec_no_type m_decl_spec_no_type +%type inherit interface interfacedef +%type interfaceref +%type dispinterfaceref +%type dispinterface dispinterfacedef +%type module moduledef +%type namespacedef %type base_type int_std %type enumdef structdef uniondef typedecl -%type type -%type coclass_int -%type coclass_ints -%type arg ne_union_field union_field s_field case enum declaration +%type type unqualified_type qualified_type +%type type_parameter +%type type_parameters +%type parameterized_type +%type parameterized_type_arg +%type parameterized_type_args +%type class_interface +%type class_interfaces +%type requires required_types +%type arg ne_union_field union_field s_field case enum enum_member declaration %type funcdef %type m_args arg_list args dispint_meths %type fields ne_union_fields cases enums enum_list dispint_props field @@ -293,16 +333,22 @@ static typelib_t *current_typelib; %type m_any_declarator any_declarator any_declarator_no_direct any_direct_declarator %type m_abstract_declarator abstract_declarator abstract_declarator_no_direct abstract_direct_declarator %type declarator_list struct_declarator_list -%type coclass coclasshdr coclassdef -%type pointer_type threading_type version -%type libraryhdr callconv cppquote importlib import t_ident -%type uuid_string -%type import_start +%type coclass coclassdef +%type runtimeclass runtimeclass_def +%type apicontract apicontract_def +%type contract_ver +%type pointer_type threading_type marshaling_behavior version +%type libraryhdr callconv cppquote importlib import +%type typename m_typename +%type import_start %type library_start librarydef %type statement typedef pragma_warning %type gbl_statements imp_statements int_statements +%type decl_block decl_statements +%type imp_decl_block imp_decl_statements %type warnings %type allocate_option_list allocate_option +%type namespace_pfx %left ',' %right '?' ':' @@ -319,11 +365,9 @@ static typelib_t *current_typelib; %right '!' '~' CAST PPTR POS NEG ADDRESSOF tSIZEOF %left '.' MEMBERPTR '[' ']' -%define parse.error verbose - %% -input: gbl_statements m_acf { fix_incomplete(); +input: gbl_statements m_acf { $1 = append_parameterized_type_stmts($1); check_statements($1, FALSE); check_all_user_types($1); write_header($1); @@ -337,47 +381,94 @@ input: gbl_statements m_acf { fix_incomplete(); #endif write_dlldata($1); write_local_stubs($1); + (void)parser_nerrs; /* avoid unused variable warning */ } ; -m_acf: /* empty */ | aACF acf_statements +m_acf + : %empty + | aACF acf_statements + ; -gbl_statements: { $$ = NULL; } - | gbl_statements namespacedef '{' { push_namespace($2); } gbl_statements '}' - { pop_namespace($2); $$ = append_statements($1, $5); } - | gbl_statements interfacedec { $$ = append_statement($1, make_statement_reference($2)); } +decl_statements + : %empty { $$ = NULL; } + | decl_statements tINTERFACE qualified_type '<' parameterized_type_args '>' ';' + { parameterized_type_stmts = append_statement(parameterized_type_stmts, make_statement_parameterized_type($3, $5)); + $$ = append_statement($1, make_statement_reference(type_parameterized_type_specialize_declare($3, $5))); + } + ; + +decl_block: tDECLARE '{' decl_statements '}' { $$ = $3; } + ; + +imp_decl_statements + : %empty { $$ = NULL; } + | imp_decl_statements tINTERFACE qualified_type '<' parameterized_type_args '>' ';' + { $$ = append_statement($1, make_statement_reference(type_parameterized_type_specialize_declare($3, $5))); } + ; + +imp_decl_block + : tDECLARE '{' imp_decl_statements '}' { $$ = $3; } + ; + +gbl_statements + : %empty { $$ = NULL; } + | gbl_statements namespacedef '{' { push_namespaces($2); } gbl_statements '}' + { pop_namespaces($2); $$ = append_statements($1, $5); } + | gbl_statements interface ';' { $$ = append_statement($1, make_statement_reference($2)); } + | gbl_statements dispinterface ';' { $$ = append_statement($1, make_statement_reference($2)); } | gbl_statements interfacedef { $$ = append_statement($1, make_statement_type_decl($2)); } + | gbl_statements delegatedef { $$ = append_statement($1, make_statement_type_decl($2)); } | gbl_statements coclass ';' { $$ = $1; reg_type($2, $2->name, current_namespace, 0); } | gbl_statements coclassdef { $$ = append_statement($1, make_statement_type_decl($2)); reg_type($2, $2->name, current_namespace, 0); } + | gbl_statements apicontract ';' { $$ = $1; reg_type($2, $2->name, current_namespace, 0); } + | gbl_statements apicontract_def { $$ = append_statement($1, make_statement_type_decl($2)); + reg_type($2, $2->name, current_namespace, 0); } + | gbl_statements runtimeclass ';' { $$ = $1; reg_type($2, $2->name, current_namespace, 0); } + | gbl_statements runtimeclass_def { $$ = append_statement($1, make_statement_type_decl($2)); + reg_type($2, $2->name, current_namespace, 0); } | gbl_statements moduledef { $$ = append_statement($1, make_statement_module($2)); } | gbl_statements librarydef { $$ = append_statement($1, make_statement_library($2)); } | gbl_statements statement { $$ = append_statement($1, $2); } + | gbl_statements decl_block { $$ = append_statements($1, $2); } ; -imp_statements: { $$ = NULL; } - | imp_statements interfacedec { $$ = append_statement($1, make_statement_reference($2)); } - | imp_statements namespacedef '{' { push_namespace($2); } imp_statements '}' - { pop_namespace($2); $$ = append_statements($1, $5); } +imp_statements + : %empty { $$ = NULL; } + | imp_statements interface ';' { $$ = append_statement($1, make_statement_reference($2)); } + | imp_statements dispinterface ';' { $$ = append_statement($1, make_statement_reference($2)); } + | imp_statements namespacedef '{' { push_namespaces($2); } imp_statements '}' + { pop_namespaces($2); $$ = append_statements($1, $5); } | imp_statements interfacedef { $$ = append_statement($1, make_statement_type_decl($2)); } + | imp_statements delegatedef { $$ = append_statement($1, make_statement_type_decl($2)); } | imp_statements coclass ';' { $$ = $1; reg_type($2, $2->name, current_namespace, 0); } | imp_statements coclassdef { $$ = append_statement($1, make_statement_type_decl($2)); reg_type($2, $2->name, current_namespace, 0); } + | imp_statements apicontract ';' { $$ = $1; reg_type($2, $2->name, current_namespace, 0); } + | imp_statements apicontract_def { $$ = append_statement($1, make_statement_type_decl($2)); + reg_type($2, $2->name, current_namespace, 0); } + | imp_statements runtimeclass ';' { $$ = $1; reg_type($2, $2->name, current_namespace, 0); } + | imp_statements runtimeclass_def { $$ = append_statement($1, make_statement_type_decl($2)); + reg_type($2, $2->name, current_namespace, 0); } | imp_statements moduledef { $$ = append_statement($1, make_statement_module($2)); } | imp_statements statement { $$ = append_statement($1, $2); } | imp_statements importlib { $$ = append_statement($1, make_statement_importlib($2)); } | imp_statements librarydef { $$ = append_statement($1, make_statement_library($2)); } + | imp_statements imp_decl_block { $$ = append_statements($1, $2); } ; -int_statements: { $$ = NULL; } +int_statements + : %empty { $$ = NULL; } | int_statements statement { $$ = append_statement($1, $2); } ; -semicolon_opt: +semicolon_opt + : %empty | ';' ; @@ -397,22 +488,27 @@ pragma_warning: tPRAGMA_WARNING '(' aIDENTIFIER ':' warnings ')' $$ = NULL; result = do_warning($3, $5); if(!result) - error_loc("expected \"disable\" or \"enable\"\n"); + error_loc("expected \"disable\", \"enable\" or \"default\"\n"); + } + | tPRAGMA_WARNING '(' tDEFAULT ':' warnings ')' + { + $$ = NULL; + do_warning("default", $5); } ; warnings: - aNUM { $$ = append_warning(NULL, $1); } - | warnings aNUM { $$ = append_warning($1, $2); } + aNUM { $$ = append_warning(NULL, $1.value); } + | warnings aNUM { $$ = append_warning($1, $2.value); } ; typedecl: enumdef - | tENUM aIDENTIFIER { $$ = type_new_enum($2, current_namespace, FALSE, NULL); } + | tENUM typename { $$ = type_new_enum($2, current_namespace, FALSE, NULL, &@$); } | structdef - | tSTRUCT aIDENTIFIER { $$ = type_new_struct($2, current_namespace, FALSE, NULL); } + | tSTRUCT typename { $$ = type_new_struct($2, current_namespace, FALSE, NULL, &@$); } | uniondef - | tUNION aIDENTIFIER { $$ = type_new_nonencapsulated_union($2, FALSE, NULL); } + | tUNION typename { $$ = type_new_nonencapsulated_union($2, current_namespace, FALSE, NULL, &@$); } | attributes enumdef { $$ = $2; $$->attrs = check_enum_attrs($1); } | attributes structdef { $$ = $2; $$->attrs = check_struct_attrs($1); } | attributes uniondef { $$ = $2; $$->attrs = check_union_attrs($1); } @@ -420,18 +516,10 @@ typedecl: cppquote: tCPPQUOTE '(' aSTRING ')' { $$ = $3; } ; -import_start: tIMPORT aSTRING ';' { assert(yychar == YYEMPTY); - $$ = xmalloc(sizeof(struct _import_t)); - $$->name = $2; - $$->import_performed = do_import($2); - if (!$$->import_performed) yychar = aEOF; - } - ; -import: import_start imp_statements aEOF { $$ = $1->name; - if ($1->import_performed) pop_import(); - free($1); - } +import_start: tIMPORT aSTRING ';' { $$ = $2; push_import( $2, &yylloc ); } + ; +import: import_start imp_statements aEOF { yylloc = pop_import(); } ; importlib: tIMPORTLIB '(' aSTRING ')' @@ -442,8 +530,7 @@ importlib: tIMPORTLIB '(' aSTRING ')' */ ; -libraryhdr: tLIBRARY aIDENTIFIER { $$ = $2; } - | tLIBRARY aKNOWNTYPE { $$ = $2; } +libraryhdr: tLIBRARY typename { $$ = $2; } ; library_start: attributes libraryhdr '{' { $$ = make_library($2, check_library_attrs($2, $1)); /* ifdef __REACTOS__ */ @@ -464,7 +551,8 @@ librarydef: library_start imp_statements '}' */ ; -m_args: { $$ = NULL; } +m_args + : %empty { $$ = NULL; } | args ; @@ -473,7 +561,7 @@ arg_list: arg { check_arg_attrs($1); $$ = append_var( NULL, $1 ); } ; args: arg_list - | arg_list ',' ELLIPSIS { $$ = append_var( $1, make_var(strdup("...")) ); } + | arg_list ',' ELLIPSIS { $$ = append_var( $1, make_var(xstrdup("...")) ); } ; /* split into two rules to get bison to resolve a tVOID conflict */ @@ -497,7 +585,8 @@ array: '[' expr ']' { $$ = $2; | '[' ']' { $$ = make_expr(EXPR_VOID); } ; -m_attributes: { $$ = NULL; } +m_attributes + : %empty { $$ = NULL; } | attributes ; @@ -514,185 +603,275 @@ str_list: aSTRING { $$ = append_str( NULL, $1 ); } | str_list ',' aSTRING { $$ = append_str( $1, $3 ); } ; -attribute: { $$ = NULL; } - | tAGGREGATABLE { $$ = make_attr(ATTR_AGGREGATABLE); } - | tANNOTATION '(' aSTRING ')' { $$ = make_attrp(ATTR_ANNOTATION, $3); } - | tAPPOBJECT { $$ = make_attr(ATTR_APPOBJECT); } - | tASYNC { $$ = make_attr(ATTR_ASYNC); } - | tAUTOHANDLE { $$ = make_attr(ATTR_AUTO_HANDLE); } - | tBINDABLE { $$ = make_attr(ATTR_BINDABLE); } - | tBROADCAST { $$ = make_attr(ATTR_BROADCAST); } - | tCALLAS '(' ident ')' { $$ = make_attrp(ATTR_CALLAS, $3); } - | tCASE '(' expr_list_int_const ')' { $$ = make_attrp(ATTR_CASE, $3); } - | tCODE { $$ = make_attr(ATTR_CODE); } - | tCOMMSTATUS { $$ = make_attr(ATTR_COMMSTATUS); } - | tCONTEXTHANDLE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); } - | tCONTEXTHANDLENOSERIALIZE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ } - | tCONTEXTHANDLESERIALIZE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_SERIALIZE */ } - | tCONTROL { $$ = make_attr(ATTR_CONTROL); } - | tDECODE { $$ = make_attr(ATTR_DECODE); } - | tDEFAULT { $$ = make_attr(ATTR_DEFAULT); } - | tDEFAULTBIND { $$ = make_attr(ATTR_DEFAULTBIND); } - | tDEFAULTCOLLELEM { $$ = make_attr(ATTR_DEFAULTCOLLELEM); } - | tDEFAULTVALUE '(' expr_const ')' { $$ = make_attrp(ATTR_DEFAULTVALUE, $3); } - | tDEFAULTVTABLE { $$ = make_attr(ATTR_DEFAULTVTABLE); } - | tDISABLECONSISTENCYCHECK { $$ = make_attr(ATTR_DISABLECONSISTENCYCHECK); } - | tDISPLAYBIND { $$ = make_attr(ATTR_DISPLAYBIND); } - | tDLLNAME '(' aSTRING ')' { $$ = make_attrp(ATTR_DLLNAME, $3); } - | tDUAL { $$ = make_attr(ATTR_DUAL); } - | tENABLEALLOCATE { $$ = make_attr(ATTR_ENABLEALLOCATE); } - | tENCODE { $$ = make_attr(ATTR_ENCODE); } - | tENDPOINT '(' str_list ')' { $$ = make_attrp(ATTR_ENDPOINT, $3); } - | tENTRY '(' expr_const ')' { $$ = make_attrp(ATTR_ENTRY, $3); } - | tEXPLICITHANDLE { $$ = make_attr(ATTR_EXPLICIT_HANDLE); } - | tFAULTSTATUS { $$ = make_attr(ATTR_FAULTSTATUS); } - | tFORCEALLOCATE { $$ = make_attr(ATTR_FORCEALLOCATE); } - | tHANDLE { $$ = make_attr(ATTR_HANDLE); } - | tHELPCONTEXT '(' expr_int_const ')' { $$ = make_attrp(ATTR_HELPCONTEXT, $3); } - | tHELPFILE '(' aSTRING ')' { $$ = make_attrp(ATTR_HELPFILE, $3); } - | tHELPSTRING '(' aSTRING ')' { $$ = make_attrp(ATTR_HELPSTRING, $3); } - | tHELPSTRINGCONTEXT '(' expr_int_const ')' { $$ = make_attrp(ATTR_HELPSTRINGCONTEXT, $3); } - | tHELPSTRINGDLL '(' aSTRING ')' { $$ = make_attrp(ATTR_HELPSTRINGDLL, $3); } - | tHIDDEN { $$ = make_attr(ATTR_HIDDEN); } - | tID '(' expr_int_const ')' { $$ = make_attrp(ATTR_ID, $3); } - | tIDEMPOTENT { $$ = make_attr(ATTR_IDEMPOTENT); } - | tIGNORE { $$ = make_attr(ATTR_IGNORE); } - | tIIDIS '(' expr ')' { $$ = make_attrp(ATTR_IIDIS, $3); } - | tIMMEDIATEBIND { $$ = make_attr(ATTR_IMMEDIATEBIND); } - | tIMPLICITHANDLE '(' arg ')' { $$ = make_attrp(ATTR_IMPLICIT_HANDLE, $3); } - | tIN { $$ = make_attr(ATTR_IN); } - | tINPUTSYNC { $$ = make_attr(ATTR_INPUTSYNC); } - | tLENGTHIS '(' m_exprs ')' { $$ = make_attrp(ATTR_LENGTHIS, $3); } - | tLCID '(' expr_int_const ')' { $$ = make_attrp(ATTR_LIBLCID, $3); } - | tLCID { $$ = make_attr(ATTR_PARAMLCID); } - | tLICENSED { $$ = make_attr(ATTR_LICENSED); } - | tLOCAL { $$ = make_attr(ATTR_LOCAL); } - | tMAYBE { $$ = make_attr(ATTR_MAYBE); } - | tMESSAGE { $$ = make_attr(ATTR_MESSAGE); } - | tNOCODE { $$ = make_attr(ATTR_NOCODE); } - | tNONBROWSABLE { $$ = make_attr(ATTR_NONBROWSABLE); } - | tNONCREATABLE { $$ = make_attr(ATTR_NONCREATABLE); } - | tNONEXTENSIBLE { $$ = make_attr(ATTR_NONEXTENSIBLE); } - | tNOTIFY { $$ = make_attr(ATTR_NOTIFY); } - | tNOTIFYFLAG { $$ = make_attr(ATTR_NOTIFYFLAG); } - | tOBJECT { $$ = make_attr(ATTR_OBJECT); } - | tODL { $$ = make_attr(ATTR_ODL); } - | tOLEAUTOMATION { $$ = make_attr(ATTR_OLEAUTOMATION); } - | tOPTIMIZE '(' aSTRING ')' { $$ = make_attrp(ATTR_OPTIMIZE, $3); } - | tOPTIONAL { $$ = make_attr(ATTR_OPTIONAL); } - | tOUT { $$ = make_attr(ATTR_OUT); } - | tPARTIALIGNORE { $$ = make_attr(ATTR_PARTIALIGNORE); } - | tPOINTERDEFAULT '(' pointer_type ')' { $$ = make_attrv(ATTR_POINTERDEFAULT, $3); } - | tPROGID '(' aSTRING ')' { $$ = make_attrp(ATTR_PROGID, $3); } - | tPROPGET { $$ = make_attr(ATTR_PROPGET); } - | tPROPPUT { $$ = make_attr(ATTR_PROPPUT); } - | tPROPPUTREF { $$ = make_attr(ATTR_PROPPUTREF); } - | tPROXY { $$ = make_attr(ATTR_PROXY); } - | tPUBLIC { $$ = make_attr(ATTR_PUBLIC); } - | tRANGE '(' expr_int_const ',' expr_int_const ')' - { expr_list_t *list = append_expr( NULL, $3 ); - list = append_expr( list, $5 ); - $$ = make_attrp(ATTR_RANGE, list); } - | tREADONLY { $$ = make_attr(ATTR_READONLY); } - | tREPRESENTAS '(' type ')' { $$ = make_attrp(ATTR_REPRESENTAS, $3); } - | tREQUESTEDIT { $$ = make_attr(ATTR_REQUESTEDIT); } - | tRESTRICTED { $$ = make_attr(ATTR_RESTRICTED); } - | tRETVAL { $$ = make_attr(ATTR_RETVAL); } - | tSIZEIS '(' m_exprs ')' { $$ = make_attrp(ATTR_SIZEIS, $3); } - | tSOURCE { $$ = make_attr(ATTR_SOURCE); } - | tSTRICTCONTEXTHANDLE { $$ = make_attr(ATTR_STRICTCONTEXTHANDLE); } - | tSTRING { $$ = make_attr(ATTR_STRING); } - | tSWITCHIS '(' expr ')' { $$ = make_attrp(ATTR_SWITCHIS, $3); } - | tSWITCHTYPE '(' type ')' { $$ = make_attrp(ATTR_SWITCHTYPE, $3); } - | tTRANSMITAS '(' type ')' { $$ = make_attrp(ATTR_TRANSMITAS, $3); } - | tTHREADING '(' threading_type ')' { $$ = make_attrv(ATTR_THREADING, $3); } - | tUIDEFAULT { $$ = make_attr(ATTR_UIDEFAULT); } - | tUSESGETLASTERROR { $$ = make_attr(ATTR_USESGETLASTERROR); } - | tUSERMARSHAL '(' type ')' { $$ = make_attrp(ATTR_USERMARSHAL, $3); } - | tUUID '(' uuid_string ')' { $$ = make_attrp(ATTR_UUID, $3); } - | tASYNCUUID '(' uuid_string ')' { $$ = make_attrp(ATTR_ASYNCUUID, $3); } - | tV1ENUM { $$ = make_attr(ATTR_V1ENUM); } - | tVARARG { $$ = make_attr(ATTR_VARARG); } - | tVERSION '(' version ')' { $$ = make_attrv(ATTR_VERSION, $3); } - | tVIPROGID '(' aSTRING ')' { $$ = make_attrp(ATTR_VIPROGID, $3); } - | tWIREMARSHAL '(' type ')' { $$ = make_attrp(ATTR_WIREMARSHAL, $3); } - | pointer_type { $$ = make_attrv(ATTR_POINTERTYPE, $1); } +marshaling_behavior: + tAGILE { $$ = MARSHALING_AGILE; } + | tNONE { $$ = MARSHALING_NONE; } + | tSTANDARD { $$ = MARSHALING_STANDARD; } ; -uuid_string: - aUUID - | aSTRING { if (!is_valid_uuid($1)) - error_loc("invalid UUID: %s\n", $1); - $$ = parse_uuid($1); } +contract_ver: + aNUM { $$ = MAKEVERSION(0, $1.value); } + | aNUM '.' aNUM { $$ = MAKEVERSION($3.value, $1.value); } + ; + +contract_req + : decl_spec ',' contract_ver { + struct integer integer = {.value = $3}; + if ($1->type->type_type != TYPE_APICONTRACT) + error_loc("type %s is not an apicontract\n", $1->type->name); + $$ = make_exprl(EXPR_NUM, &integer); + $$ = make_exprt(EXPR_GTREQL, declare_var(NULL, $1, make_declarator(NULL), 0), $$); + } ; -callconv: tCDECL { $$ = xstrdup("__cdecl"); } - | tFASTCALL { $$ = xstrdup("__fastcall"); } - | tPASCAL { $$ = xstrdup("__pascal"); } - | tSTDCALL { $$ = xstrdup("__stdcall"); } +static_attr + : decl_spec ',' contract_req { if ($1->type->type_type != TYPE_INTERFACE) + error_loc("type %s is not an interface\n", $1->type->name); + $$ = make_exprt(EXPR_MEMBER, declare_var(NULL, $1, make_declarator(NULL), 0), $3); + } ; -cases: { $$ = NULL; } +activatable_attr: + decl_spec ',' contract_req { if ($1->type->type_type != TYPE_INTERFACE) + error_loc("type %s is not an interface\n", $1->type->name); + $$ = make_exprt(EXPR_MEMBER, declare_var(NULL, $1, make_declarator(NULL), 0), $3); + } + | contract_req { $$ = $1; } /* activatable on the default activation factory */ + ; + +access_attr + : tPUBLIC { $$ = attr_int( @$, ATTR_PUBLIC, 0 ); } + | tPROTECTED { $$ = attr_int( @$, ATTR_PROTECTED, 0 ); } + ; + +composable_attr + : decl_spec ',' access_attr ',' contract_req + { if ($1->type->type_type != TYPE_INTERFACE) + error_loc( "type %s is not an interface\n", $1->type->name ); + $$ = make_exprt( EXPR_MEMBER, declare_var( append_attr( NULL, $3 ), $1, make_declarator( NULL ), 0 ), $5 ); + } + ; + +deprecated_attr + : aSTRING ',' aIDENTIFIER ',' contract_req + { $$ = make_expr3( EXPR_MEMBER, make_exprs( EXPR_STRLIT, $1 ), make_exprs( EXPR_IDENTIFIER, $3 ), $5 ); } + ; + +attribute + : %empty { $$ = NULL; } + | tACTIVATABLE '(' activatable_attr ')' { $$ = attr_ptr( @$, ATTR_ACTIVATABLE, $3 ); } + | tAGGREGATABLE { $$ = attr_int( @$, ATTR_AGGREGATABLE, 0 ); } + | tANNOTATION '(' aSTRING ')' { $$ = attr_ptr( @$, ATTR_ANNOTATION, $3 ); } + | tAPPOBJECT { $$ = attr_int( @$, ATTR_APPOBJECT, 0 ); } + | tASYNC { $$ = attr_int( @$, ATTR_ASYNC, 0 ); } + | tAUTOHANDLE { $$ = attr_int( @$, ATTR_AUTO_HANDLE, 0 ); } + | tBINDABLE { $$ = attr_int( @$, ATTR_BINDABLE, 0 ); } + | tBROADCAST { $$ = attr_int( @$, ATTR_BROADCAST, 0 ); } + | tCALLAS '(' ident ')' { $$ = attr_ptr( @$, ATTR_CALLAS, $3 ); } + | tCASE '(' expr_list_int_const ')' { $$ = attr_ptr( @$, ATTR_CASE, $3 ); } + | tCODE { $$ = attr_int( @$, ATTR_CODE, 0 ); } + | tCOMPOSABLE '(' composable_attr ')' { $$ = attr_ptr( @$, ATTR_COMPOSABLE, $3 ); } + | tCOMMSTATUS { $$ = attr_int( @$, ATTR_COMMSTATUS, 0 ); } + | tCONTEXTHANDLE { $$ = attr_int( @$, ATTR_CONTEXTHANDLE, 0 ); } + | tCONTEXTHANDLENOSERIALIZE { $$ = attr_int( @$, ATTR_CONTEXTHANDLE, 0 ); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ } + | tCONTEXTHANDLESERIALIZE { $$ = attr_int( @$, ATTR_CONTEXTHANDLE, 0 ); /* RPC_CONTEXT_HANDLE_SERIALIZE */ } + | tCONTRACT '(' contract_req ')' { $$ = attr_ptr( @$, ATTR_CONTRACT, $3 ); } + | tCONTRACTVERSION '(' contract_ver ')' { $$ = attr_int( @$, ATTR_CONTRACTVERSION, $3 ); } + | tCONTROL { $$ = attr_int( @$, ATTR_CONTROL, 0 ); } + | tCUSTOM '(' aUUID ',' expr_const ')' { attr_custdata_t *data = xmalloc( sizeof(*data) ); + data->id = *$3; data->pval = $5; + $$ = attr_ptr( @$, ATTR_CUSTOM, data ); + } + | tDECODE { $$ = attr_int( @$, ATTR_DECODE, 0 ); } + | tDEFAULT { $$ = attr_int( @$, ATTR_DEFAULT, 0 ); } + | tDEFAULT_OVERLOAD { $$ = attr_int( @$, ATTR_DEFAULT_OVERLOAD, 0 ); } + | tDEFAULTBIND { $$ = attr_int( @$, ATTR_DEFAULTBIND, 0 ); } + | tDEFAULTCOLLELEM { $$ = attr_int( @$, ATTR_DEFAULTCOLLELEM, 0 ); } + | tDEFAULTVALUE '(' expr_const ')' { $$ = attr_ptr( @$, ATTR_DEFAULTVALUE, $3 ); } + | tDEFAULTVTABLE { $$ = attr_int( @$, ATTR_DEFAULTVTABLE, 0 ); } + | tDEPRECATED '(' deprecated_attr ')' { $$ = attr_ptr( @$, ATTR_DEPRECATED, $3 ); } + | tDISABLECONSISTENCYCHECK { $$ = attr_int( @$, ATTR_DISABLECONSISTENCYCHECK, 0 ); } + | tDISPLAYBIND { $$ = attr_int( @$, ATTR_DISPLAYBIND, 0 ); } + | tDLLNAME '(' aSTRING ')' { $$ = attr_ptr( @$, ATTR_DLLNAME, $3 ); } + | tDUAL { $$ = attr_int( @$, ATTR_DUAL, 0 ); } + | tENABLEALLOCATE { $$ = attr_int( @$, ATTR_ENABLEALLOCATE, 0 ); } + | tENCODE { $$ = attr_int( @$, ATTR_ENCODE, 0 ); } + | tENDPOINT '(' str_list ')' { $$ = attr_ptr( @$, ATTR_ENDPOINT, $3 ); } + | tENTRY '(' expr_const ')' { $$ = attr_ptr( @$, ATTR_ENTRY, $3 ); } + | tEVENTADD { $$ = attr_int( @$, ATTR_EVENTADD, 0 ); } + | tEVENTREMOVE { $$ = attr_int( @$, ATTR_EVENTREMOVE, 0 ); } + | tEXCLUSIVETO '(' decl_spec ')' { if ($3->type->type_type != TYPE_RUNTIMECLASS) + error_loc( "type %s is not a runtimeclass\n", $3->type->name ); + $$ = attr_ptr( @$, ATTR_EXCLUSIVETO, $3->type ); + } + | tEXPLICITHANDLE { $$ = attr_int( @$, ATTR_EXPLICIT_HANDLE, 0 ); } + | tFAULTSTATUS { $$ = attr_int( @$, ATTR_FAULTSTATUS, 0 ); } + | tFLAGS { $$ = attr_int( @$, ATTR_FLAGS, 0 ); } + | tFORCEALLOCATE { $$ = attr_int( @$, ATTR_FORCEALLOCATE, 0 ); } + | tHANDLE { $$ = attr_int( @$, ATTR_HANDLE, 0 ); } + | tHELPCONTEXT '(' expr_int_const ')' { $$ = attr_ptr( @$, ATTR_HELPCONTEXT, $3 ); } + | tHELPFILE '(' aSTRING ')' { $$ = attr_ptr( @$, ATTR_HELPFILE, $3 ); } + | tHELPSTRING '(' aSTRING ')' { $$ = attr_ptr( @$, ATTR_HELPSTRING, $3 ); } + | tHELPSTRINGCONTEXT '(' expr_int_const ')' + { $$ = attr_ptr( @$, ATTR_HELPSTRINGCONTEXT, $3 ); } + | tHELPSTRINGDLL '(' aSTRING ')' { $$ = attr_ptr( @$, ATTR_HELPSTRINGDLL, $3 ); } + | tHIDDEN { $$ = attr_int( @$, ATTR_HIDDEN, 0 ); } + | tID '(' expr_int_const ')' { $$ = attr_ptr( @$, ATTR_ID, $3 ); } + | tIDEMPOTENT { $$ = attr_int( @$, ATTR_IDEMPOTENT, 0 ); } + | tIGNORE { $$ = attr_int( @$, ATTR_IGNORE, 0 ); } + | tIIDIS '(' expr ')' { $$ = attr_ptr( @$, ATTR_IIDIS, $3 ); } + | tIMMEDIATEBIND { $$ = attr_int( @$, ATTR_IMMEDIATEBIND, 0 ); } + | tIMPLICITHANDLE '(' arg ')' { $$ = attr_ptr( @$, ATTR_IMPLICIT_HANDLE, $3 ); } + | tIN { $$ = attr_int( @$, ATTR_IN, 0 ); } + | tINPUTSYNC { $$ = attr_int( @$, ATTR_INPUTSYNC, 0 ); } + | tLENGTHIS '(' m_exprs ')' { $$ = attr_ptr( @$, ATTR_LENGTHIS, $3 ); } + | tLCID '(' expr_int_const ')' { $$ = attr_ptr( @$, ATTR_LIBLCID, $3 ); } + | tLCID { $$ = attr_int( @$, ATTR_PARAMLCID, 0 ); } + | tLICENSED { $$ = attr_int( @$, ATTR_LICENSED, 0 ); } + | tLOCAL { $$ = attr_int( @$, ATTR_LOCAL, 0 ); } + | tMARSHALINGBEHAVIOR '(' marshaling_behavior ')' + { $$ = attr_int( @$, ATTR_MARSHALING_BEHAVIOR, $3 ); } + | tMAYBE { $$ = attr_int( @$, ATTR_MAYBE, 0 ); } + | tMESSAGE { $$ = attr_int( @$, ATTR_MESSAGE, 0 ); } + | tNOCODE { $$ = attr_int( @$, ATTR_NOCODE, 0 ); } + | tNONBROWSABLE { $$ = attr_int( @$, ATTR_NONBROWSABLE, 0 ); } + | tNONCREATABLE { $$ = attr_int( @$, ATTR_NONCREATABLE, 0 ); } + | tNONEXTENSIBLE { $$ = attr_int( @$, ATTR_NONEXTENSIBLE, 0 ); } + | tNOTIFY { $$ = attr_int( @$, ATTR_NOTIFY, 0 ); } + | tNOTIFYFLAG { $$ = attr_int( @$, ATTR_NOTIFYFLAG, 0 ); } + | tOBJECT { $$ = attr_int( @$, ATTR_OBJECT, 0 ); } + | tODL { $$ = attr_int( @$, ATTR_ODL, 0 ); } + | tOLEAUTOMATION { $$ = attr_int( @$, ATTR_OLEAUTOMATION, 0 ); } + | tOPTIMIZE '(' aSTRING ')' { $$ = attr_ptr( @$, ATTR_OPTIMIZE, $3 ); } + | tOPTIONAL { $$ = attr_int( @$, ATTR_OPTIONAL, 0 ); } + | tOUT { $$ = attr_int( @$, ATTR_OUT, 0 ); } + | tOVERLOAD '(' aSTRING ')' { $$ = attr_ptr( @$, ATTR_OVERLOAD, $3 ); } + | tPARTIALIGNORE { $$ = attr_int( @$, ATTR_PARTIALIGNORE, 0 ); } + | tPOINTERDEFAULT '(' pointer_type ')' { $$ = attr_int( @$, ATTR_POINTERDEFAULT, $3 ); } + | tPROGID '(' aSTRING ')' { $$ = attr_ptr( @$, ATTR_PROGID, $3 ); } + | tPROPGET { $$ = attr_int( @$, ATTR_PROPGET, 0 ); } + | tPROPPUT { $$ = attr_int( @$, ATTR_PROPPUT, 0 ); } + | tPROPPUTREF { $$ = attr_int( @$, ATTR_PROPPUTREF, 0 ); } + | tPROTECTED { $$ = attr_int( @$, ATTR_PROTECTED, 0 ); } + | tPROXY { $$ = attr_int( @$, ATTR_PROXY, 0 ); } + | tPUBLIC { $$ = attr_int( @$, ATTR_PUBLIC, 0 ); } + | tRANGE '(' expr_int_const ',' expr_int_const ')' + { expr_list_t *list = append_expr( NULL, $3 ); + list = append_expr( list, $5 ); + $$ = attr_ptr( @$, ATTR_RANGE, list ); + } + | tREADONLY { $$ = attr_int( @$, ATTR_READONLY, 0 ); } + | tREPRESENTAS '(' type ')' { $$ = attr_ptr( @$, ATTR_REPRESENTAS, $3 ); } + | tREQUESTEDIT { $$ = attr_int( @$, ATTR_REQUESTEDIT, 0 ); } + | tRESTRICTED { $$ = attr_int( @$, ATTR_RESTRICTED, 0 ); } + | tRETVAL { $$ = attr_int( @$, ATTR_RETVAL, 0 ); } + | tSIZEIS '(' m_exprs ')' { $$ = attr_ptr( @$, ATTR_SIZEIS, $3 ); } + | tSOURCE { $$ = attr_int( @$, ATTR_SOURCE, 0 ); } + | tSTATIC '(' static_attr ')' { $$ = attr_ptr( @$, ATTR_STATIC, $3 ); } + | tSTRICTCONTEXTHANDLE { $$ = attr_int( @$, ATTR_STRICTCONTEXTHANDLE, 0 ); } + | tSTRING { $$ = attr_int( @$, ATTR_STRING, 0 ); } + | tSWITCHIS '(' expr ')' { $$ = attr_ptr( @$, ATTR_SWITCHIS, $3 ); } + | tSWITCHTYPE '(' type ')' { $$ = attr_ptr( @$, ATTR_SWITCHTYPE, $3 ); } + | tTRANSMITAS '(' type ')' { $$ = attr_ptr( @$, ATTR_TRANSMITAS, $3 ); } + | tTHREADING '(' threading_type ')' { $$ = attr_int( @$, ATTR_THREADING, $3 ); } + | tUIDEFAULT { $$ = attr_int( @$, ATTR_UIDEFAULT, 0 ); } + | tUSESGETLASTERROR { $$ = attr_int( @$, ATTR_USESGETLASTERROR, 0 ); } + | tUSERMARSHAL '(' type ')' { $$ = attr_ptr( @$, ATTR_USERMARSHAL, $3 ); } + | tUUID '(' aUUID ')' { $$ = attr_ptr( @$, ATTR_UUID, $3 ); } + | tASYNCUUID '(' aUUID ')' { $$ = attr_ptr( @$, ATTR_ASYNCUUID, $3 ); } + | tV1ENUM { $$ = attr_int( @$, ATTR_V1ENUM, 0 ); } + | tVARARG { $$ = attr_int( @$, ATTR_VARARG, 0 ); } + | tVERSION '(' version ')' { $$ = attr_int( @$, ATTR_VERSION, $3 ); } + | tVIPROGID '(' aSTRING ')' { $$ = attr_ptr( @$, ATTR_VIPROGID, $3 ); } + | tWIREMARSHAL '(' type ')' { $$ = attr_ptr( @$, ATTR_WIREMARSHAL, $3 ); } + | pointer_type { $$ = attr_int( @$, ATTR_POINTERTYPE, $1 ); } + ; + +callconv: tCDECL + | tFASTCALL + | tPASCAL + | tSTDCALL + ; + +cases + : %empty { $$ = NULL; } | cases case { $$ = append_var( $1, $2 ); } ; -case: tCASE expr_int_const ':' union_field { attr_t *a = make_attrp(ATTR_CASE, append_expr( NULL, $2 )); - $$ = $4; if (!$$) $$ = make_var(NULL); - $$->attrs = append_attr( $$->attrs, a ); - } - | tDEFAULT ':' union_field { attr_t *a = make_attr(ATTR_DEFAULT); - $$ = $3; if (!$$) $$ = make_var(NULL); - $$->attrs = append_attr( $$->attrs, a ); - } - ; +case : tCASE expr_int_const ':' union_field { attr_t *a = attr_ptr( @$, ATTR_CASE, append_expr( NULL, $2 ) ); + $$ = $4; if (!$$) $$ = make_var( NULL ); + $$->attrs = append_attr( $$->attrs, a ); + } + | tDEFAULT ':' union_field { attr_t *a = attr_int( @$, ATTR_DEFAULT, 0 ); + $$ = $3; if (!$$) $$ = make_var( NULL ); + $$->attrs = append_attr( $$->attrs, a ); + } + ; -enums: { $$ = NULL; } +enums + : %empty { $$ = NULL; } | enum_list ',' { $$ = $1; } | enum_list ; -enum_list: enum { if (!$1->eval) - $1->eval = make_exprl(EXPR_NUM, 0 /* default for first enum entry */); +enum_list: enum { + struct integer integer = {.value = 0}; + if (!$1->eval) + $1->eval = make_exprl(EXPR_NUM, &integer); $$ = append_var( NULL, $1 ); - } - | enum_list ',' enum { if (!$3->eval) + } + | enum_list ',' enum { + if (!$3->eval) { var_t *last = LIST_ENTRY( list_tail($$), var_t, entry ); - enum expr_type type = EXPR_NUM; - if (last->eval->type == EXPR_HEXNUM) type = EXPR_HEXNUM; - if (last->eval->cval + 1 < 0) type = EXPR_HEXNUM; - $3->eval = make_exprl(type, last->eval->cval + 1); + struct integer integer; + + if (last->eval->type == EXPR_NUM) + integer.is_hex = last->eval->u.integer.is_hex; + integer.value = last->eval->cval + 1; + if (integer.value < 0) + integer.is_hex = TRUE; + $3->eval = make_exprl(EXPR_NUM, &integer); } $$ = append_var( $1, $3 ); + } + ; + +enum_member: m_attributes ident { $$ = $2; + $$->attrs = check_enum_member_attrs($1); } ; -enum: ident '=' expr_int_const { $$ = reg_const($1); +enum: enum_member '=' expr_int_const { $$ = reg_const($1); $$->eval = $3; - $$->type = type_new_int(TYPE_BASIC_INT, 0); + $$->declspec.type = type_new_int(TYPE_BASIC_INT, 0); } - | ident { $$ = reg_const($1); - $$->type = type_new_int(TYPE_BASIC_INT, 0); + | enum_member { $$ = reg_const($1); + $$->declspec.type = type_new_int(TYPE_BASIC_INT, 0); } ; -enumdef: tENUM t_ident '{' enums '}' { $$ = type_new_enum($2, current_namespace, TRUE, $4); } +enumdef: tENUM m_typename '{' enums '}' { $$ = type_new_enum($2, current_namespace, TRUE, $4, &@2); } ; m_exprs: m_expr { $$ = append_expr( NULL, $1 ); } | m_exprs ',' m_expr { $$ = append_expr( $1, $3 ); } ; -m_expr: { $$ = make_expr(EXPR_VOID); } +m_expr + : %empty { $$ = make_expr(EXPR_VOID); } | expr ; -expr: aNUM { $$ = make_exprl(EXPR_NUM, $1); } - | aHEXNUM { $$ = make_exprl(EXPR_HEXNUM, $1); } +expr: aNUM { $$ = make_exprl(EXPR_NUM, &$1); } + | aHEXNUM { $$ = make_exprl(EXPR_NUM, &$1); } | aDOUBLE { $$ = make_exprd(EXPR_DOUBLE, $1); } - | tFALSE { $$ = make_exprl(EXPR_TRUEFALSE, 0); } - | tNULL { $$ = make_exprl(EXPR_NUM, 0); } - | tTRUE { $$ = make_exprl(EXPR_TRUEFALSE, 1); } + | tFALSE { struct integer integer = {.value = 0}; + $$ = make_exprl(EXPR_TRUEFALSE, &integer); } + | tNULL { struct integer integer = {.value = 0}; + $$ = make_exprl(EXPR_NUM, &integer); } + | tTRUE { struct integer integer = {.value = 1}; + $$ = make_exprl(EXPR_TRUEFALSE, &integer); } | aSTRING { $$ = make_exprs(EXPR_STRLIT, $1); } | aWSTRING { $$ = make_exprs(EXPR_WSTRLIT, $1); } | aSQSTRING { $$ = make_exprs(EXPR_CHARCONST, $1); } @@ -724,9 +903,9 @@ expr: aNUM { $$ = make_exprl(EXPR_NUM, $1); } | '*' expr %prec PPTR { $$ = make_expr1(EXPR_PPTR, $2); } | expr MEMBERPTR aIDENTIFIER { $$ = make_expr2(EXPR_MEMBER, make_expr1(EXPR_PPTR, $1), make_exprs(EXPR_IDENTIFIER, $3)); } | expr '.' aIDENTIFIER { $$ = make_expr2(EXPR_MEMBER, $1, make_exprs(EXPR_IDENTIFIER, $3)); } - | '(' decl_spec m_abstract_declarator ')' expr %prec CAST + | '(' unqualified_decl_spec m_abstract_declarator ')' expr %prec CAST { $$ = make_exprt(EXPR_CAST, declare_var(NULL, $2, $3, 0), $5); free($2); free($3); } - | tSIZEOF '(' decl_spec m_abstract_declarator ')' + | tSIZEOF '(' unqualified_decl_spec m_abstract_declarator ')' { $$ = make_exprt(EXPR_SIZEOF, declare_var(NULL, $3, $4, 0), NULL); free($3); free($4); } | expr '[' expr ']' { $$ = make_expr2(EXPR_ARRAY, $1, $3); } | '(' expr ')' { $$ = $2; } @@ -748,7 +927,8 @@ expr_const: expr { $$ = $1; } ; -fields: { $$ = NULL; } +fields + : %empty { $$ = NULL; } | fields field { $$ = append_var_list($1, $2); } ; @@ -758,7 +938,7 @@ field: m_attributes decl_spec struct_declarator_list ';' $$ = set_var_types($1, $2, $3); } | m_attributes uniondef ';' { var_t *v = make_var(NULL); - v->type = $2; v->attrs = $1; + v->declspec.type = $2; v->attrs = $1; $$ = append_var(NULL, v); } ; @@ -768,7 +948,8 @@ ne_union_field: | attributes ';' { $$ = make_var(NULL); $$->attrs = $1; } ; -ne_union_fields: { $$ = NULL; } +ne_union_fields + : %empty { $$ = NULL; } | ne_union_fields ne_union_field { $$ = append_var( $1, $2 ); } ; @@ -782,13 +963,13 @@ s_field: m_attributes decl_spec declarator { $$ = declare_var(check_field_attrs free($3); } | m_attributes structdef { var_t *v = make_var(NULL); - v->type = $2; v->attrs = $1; + v->declspec.type = $2; v->attrs = $1; $$ = v; } ; funcdef: declaration { $$ = $1; - if (type_get_type($$->type) != TYPE_FUNCTION) + if (type_get_type($$->declspec.type) != TYPE_FUNCTION) error_loc("only methods may be declared inside the methods section of a dispinterface\n"); check_function_attrs($$->name, $$->attrs); } @@ -804,34 +985,38 @@ declaration: } ; -m_ident: { $$ = NULL; } +m_ident + : %empty { $$ = NULL; } | ident ; -t_ident: { $$ = NULL; } - | aIDENTIFIER { $$ = $1; } - | aKNOWNTYPE { $$ = $1; } +m_typename + : %empty { $$ = NULL; } + | typename ; -ident: aIDENTIFIER { $$ = make_var($1); } -/* some "reserved words" used in attributes are also used as field names in some MS IDL files */ - | aKNOWNTYPE { $$ = make_var($1); } +typename: aIDENTIFIER + | aKNOWNTYPE ; -base_type: tBYTE { $$ = find_type_or_error($1, 0); } - | tWCHAR { $$ = find_type_or_error($1, 0); } +ident: typename { $$ = make_var($1); } + ; + +base_type: tBYTE { $$ = find_type_or_error( NULL, "byte" ); } + | tWCHAR { $$ = find_type_or_error( NULL, "wchar_t" ); } | int_std | tSIGNED int_std { $$ = type_new_int(type_basic_get_type($2), -1); } | tUNSIGNED int_std { $$ = type_new_int(type_basic_get_type($2), 1); } | tUNSIGNED { $$ = type_new_int(TYPE_BASIC_INT, 1); } - | tFLOAT { $$ = find_type_or_error($1, 0); } - | tDOUBLE { $$ = find_type_or_error($1, 0); } - | tBOOLEAN { $$ = find_type_or_error($1, 0); } - | tERRORSTATUST { $$ = find_type_or_error($1, 0); } - | tHANDLET { $$ = find_type_or_error($1, 0); } + | tFLOAT { $$ = find_type_or_error( NULL, "float" ); } + | tDOUBLE { $$ = find_type_or_error( NULL, "double" ); } + | tBOOLEAN { $$ = find_type_or_error( NULL, "boolean" ); } + | tERRORSTATUST { $$ = find_type_or_error( NULL, "error_status_t" ); } + | tHANDLET { $$ = find_type_or_error( NULL, "handle_t" ); } ; -m_int: +m_int + : %empty | tINT ; @@ -846,49 +1031,76 @@ int_std: tINT { $$ = type_new_int(TYPE_BASIC_INT, 0); } | tINT3264 { $$ = type_new_int(TYPE_BASIC_INT3264, 0); } ; -coclass: tCOCLASS aIDENTIFIER { $$ = type_new_coclass($2); } - | tCOCLASS aKNOWNTYPE { $$ = find_type($2, NULL, 0); - if (type_get_type_detect_alias($$) != TYPE_COCLASS) - error_loc("%s was not declared a coclass at %s:%d\n", - $2, $$->loc_info.input_name, - $$->loc_info.line_number); - } +namespace_pfx: + aIDENTIFIER '.' { $$ = find_namespace_or_error(&global_namespace, $1); } + | namespace_pfx aIDENTIFIER '.' { $$ = find_namespace_or_error($1, $2); } ; -coclasshdr: attributes coclass { $$ = $2; - check_def($$); - $$->attrs = check_coclass_attrs($2->name, $1); - } +qualified_type: + typename { $$ = find_type_or_error(current_namespace, $1); } + | namespace_pfx typename { $$ = find_type_or_error($1, $2); } ; -coclassdef: coclasshdr '{' coclass_ints '}' semicolon_opt - { $$ = type_coclass_define($1, $3); } +parameterized_type: qualified_type '<' parameterized_type_args '>' + { $$ = find_parameterized_type($1, $3); } ; -namespacedef: tNAMESPACE aIDENTIFIER { $$ = $2; } +parameterized_type_arg: + base_type { $$ = $1; } + | qualified_type { $$ = $1; } + | qualified_type '*' { $$ = type_new_pointer($1); } + | parameterized_type { $$ = $1; } + | parameterized_type '*' { $$ = type_new_pointer($1); } ; -coclass_ints: { $$ = NULL; } - | coclass_ints coclass_int { $$ = append_ifref( $1, $2 ); } +parameterized_type_args: + parameterized_type_arg { $$ = append_typeref(NULL, make_typeref($1)); } + | parameterized_type_args ',' parameterized_type_arg + { $$ = append_typeref($1, make_typeref($3)); } ; -coclass_int: - m_attributes interfacedec { $$ = make_ifref($2); $$->attrs = $1; } +coclass: tCOCLASS typename { $$ = type_coclass_declare($2); } ; -dispinterface: tDISPINTERFACE aIDENTIFIER { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); } - | tDISPINTERFACE aKNOWNTYPE { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); } +coclassdef: attributes coclass '{' class_interfaces '}' semicolon_opt + { $$ = type_coclass_define($2, $1, $4, &@2); } ; -dispinterfacehdr: attributes dispinterface { attr_t *attrs; - $$ = $2; - check_def($$); - attrs = make_attr(ATTR_DISPINTERFACE); - $$->attrs = append_attr( check_dispiface_attrs($2->name, $1), attrs ); - $$->defined = TRUE; - } +runtimeclass: tRUNTIMECLASS typename { $$ = type_runtimeclass_declare($2, current_namespace); } ; +runtimeclass_def: attributes runtimeclass inherit '{' class_interfaces '}' semicolon_opt + { if ($3 && type_get_type($3) != TYPE_RUNTIMECLASS) error_loc("%s is not a runtimeclass\n", $3->name); + $$ = type_runtimeclass_define($2, $1, $5, &@2); } + ; + +apicontract: tAPICONTRACT typename { $$ = type_apicontract_declare($2, current_namespace); } + ; + +apicontract_def: attributes apicontract '{' '}' semicolon_opt + { $$ = type_apicontract_define($2, $1, &@2); } + ; + +namespacedef: tNAMESPACE aIDENTIFIER { $$ = append_str( NULL, $2 ); } + | namespacedef '.' aIDENTIFIER { $$ = append_str( $1, $3 ); } + ; + +class_interfaces + : %empty { $$ = NULL; } + | class_interfaces class_interface { $$ = append_typeref( $1, $2 ); } + ; + +class_interface: + m_attributes interfaceref ';' { $$ = make_typeref($2); $$->attrs = $1; } + | m_attributes dispinterfaceref ';' { $$ = make_typeref($2); $$->attrs = $1; } + ; + +dispinterface: tDISPINTERFACE typename { $$ = type_dispinterface_declare($2); } + ; + +dispattributes: attributes { $$ = append_attr( $1, attr_int( @$, ATTR_DISPINTERFACE, 0 ) ); } + ; + dispint_props: tPROPERTIES ':' { $$ = NULL; } | dispint_props s_field ';' { $$ = append_var( $1, $2 ); } ; @@ -897,73 +1109,88 @@ dispint_meths: tMETHODS ':' { $$ = NULL; } | dispint_meths funcdef ';' { $$ = append_var( $1, $2 ); } ; -dispinterfacedef: dispinterfacehdr '{' - dispint_props - dispint_meths - '}' { $$ = $1; - type_dispinterface_define($$, $3, $4); +dispinterfacedef: + dispattributes dispinterface '{' dispint_props dispint_meths '}' + { $$ = type_dispinterface_define($2, $1, $4, $5, &@2); } + | dispattributes dispinterface '{' interface ';' '}' + { $$ = type_dispinterface_define_from_iface($2, $1, $4, &@2); } + ; + +inherit + : %empty { $$ = NULL; } + | ':' qualified_type { $$ = $2; } + | ':' parameterized_type { $$ = $2; } + ; + +type_parameter: typename { $$ = get_type(TYPE_PARAMETER, $1, parameters_namespace, 0); } + ; + +type_parameters: + type_parameter { $$ = append_typeref(NULL, make_typeref($1)); } + | type_parameters ',' type_parameter { $$ = append_typeref($1, make_typeref($3)); } + ; + +interface: + tINTERFACE typename { $$ = type_interface_declare($2, current_namespace); } + | tINTERFACE typename '<' { push_parameters_namespace($2); } type_parameters { pop_parameters_namespace($2); } '>' + { $$ = type_parameterized_interface_declare($2, current_namespace, $5); } + ; + +delegatedef: m_attributes tDELEGATE type ident '(' m_args ')' semicolon_opt + { $$ = type_delegate_declare($4->name, current_namespace); + $$ = type_delegate_define($$, $1, append_statement(NULL, make_statement_delegate($3, $6)), &@4); } - | dispinterfacehdr - '{' interface ';' '}' { $$ = $1; - type_dispinterface_define_from_iface($$, $3); + | m_attributes tDELEGATE type ident + '<' { push_parameters_namespace($4->name); } type_parameters '>' + '(' m_args ')' { pop_parameters_namespace($4->name); } semicolon_opt + { $$ = type_parameterized_delegate_declare($4->name, current_namespace, $7); + $$ = type_parameterized_delegate_define($$, $1, append_statement(NULL, make_statement_delegate($3, $10)), &@4); } ; -inherit: { $$ = NULL; } - | ':' aKNOWNTYPE { $$ = find_type_or_error2($2, 0); } +required_types: + qualified_type { $$ = append_typeref(NULL, make_typeref($1)); } + | parameterized_type { $$ = append_typeref(NULL, make_typeref($1)); } + | required_types ',' qualified_type { $$ = append_typeref($1, make_typeref($3)); } + | required_types ',' parameterized_type { $$ = append_typeref($1, make_typeref($3)); } ; -interface: tINTERFACE aIDENTIFIER { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); } - | tINTERFACE aKNOWNTYPE { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); } +requires + : %empty { $$ = NULL; } + | tREQUIRES required_types { $$ = $2; } ; -interfacehdr: attributes interface { $$.interface = $2; - $$.old_pointer_default = pointer_default; - if (is_attr($1, ATTR_POINTERDEFAULT)) - pointer_default = get_attrv($1, ATTR_POINTERDEFAULT); - check_def($2); - $2->attrs = check_iface_attrs($2->name, $1); - $2->defined = TRUE; - } - ; - -interfacedef: interfacehdr inherit - '{' int_statements '}' semicolon_opt { $$ = $1.interface; - if($$ == $2) - error_loc("Interface can't inherit from itself\n"); - type_interface_define($$, $2, $4); - check_async_uuid($$); - pointer_default = $1.old_pointer_default; - } -/* MIDL is able to import the definition of a base class from inside the - * definition of a derived class, I'll try to support it with this rule */ - | interfacehdr ':' aIDENTIFIER - '{' import int_statements '}' - semicolon_opt { $$ = $1.interface; - type_interface_define($$, find_type_or_error2($3, 0), $6); - pointer_default = $1.old_pointer_default; +interfacedef: attributes interface { if ($2->type_type == TYPE_PARAMETERIZED_TYPE) push_parameters_namespace($2->name); } + inherit requires '{' int_statements '}' semicolon_opt + { if ($2->type_type == TYPE_PARAMETERIZED_TYPE) + { + $$ = type_parameterized_interface_define($2, $1, $4, $7, $5, &@2); + pop_parameters_namespace($2->name); + } + else + { + $$ = type_interface_define($2, $1, $4, $7, $5, &@2); + check_async_uuid($$); + } } | dispinterfacedef semicolon_opt { $$ = $1; } ; -interfacedec: - interface ';' { $$ = $1; } - | dispinterface ';' { $$ = $1; } +interfaceref: + tINTERFACE typename { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); } + | tINTERFACE namespace_pfx typename { $$ = get_type(TYPE_INTERFACE, $3, $2, 0); } + | tINTERFACE parameterized_type { if (type_get_type(($$ = $2)) != TYPE_INTERFACE) error_loc("%s is not an interface\n", $$->name); } ; -module: tMODULE aIDENTIFIER { $$ = type_new_module($2); } - | tMODULE aKNOWNTYPE { $$ = type_new_module($2); } +dispinterfaceref: + tDISPINTERFACE typename { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); } ; -modulehdr: attributes module { $$ = $2; - $$->attrs = check_module_attrs($2->name, $1); - } +module: tMODULE typename { $$ = type_module_declare($2); } ; -moduledef: modulehdr '{' int_statements '}' - semicolon_opt { $$ = $1; - type_module_define($$, $3); - } +moduledef: m_attributes module '{' int_statements '}' semicolon_opt + { $$ = type_module_define($2, $1, $4, &@2); } ; storage_cls_spec: @@ -973,106 +1200,108 @@ storage_cls_spec: ; function_specifier: - tINLINE { $$ = make_attr(ATTR_INLINE); } + tINLINE { $$ = FUNCTION_SPECIFIER_INLINE; } ; type_qualifier: - tCONST { $$ = make_attr(ATTR_CONST); } + tCONST { $$ = TYPE_QUALIFIER_CONST; } ; -m_type_qual_list: { $$ = NULL; } - | m_type_qual_list type_qualifier { $$ = append_attr($1, $2); } +m_type_qual_list + : %empty { $$ = 0; } + | m_type_qual_list type_qualifier { $$ = $1 | $2; } ; -decl_spec: type m_decl_spec_no_type { $$ = make_decl_spec($1, $2, NULL, NULL, STG_NONE); } +decl_spec: type m_decl_spec_no_type { $$ = make_decl_spec($1, $2, NULL, STG_NONE, 0, 0); } | decl_spec_no_type type m_decl_spec_no_type - { $$ = make_decl_spec($2, $1, $3, NULL, STG_NONE); } + { $$ = make_decl_spec($2, $1, $3, STG_NONE, 0, 0); } ; -m_decl_spec_no_type: { $$ = NULL; } +unqualified_decl_spec: unqualified_type m_decl_spec_no_type + { $$ = make_decl_spec($1, $2, NULL, STG_NONE, 0, 0); } + | decl_spec_no_type unqualified_type m_decl_spec_no_type + { $$ = make_decl_spec($2, $1, $3, STG_NONE, 0, 0); } + ; + +m_decl_spec_no_type + : %empty { $$ = NULL; } | decl_spec_no_type ; decl_spec_no_type: - type_qualifier m_decl_spec_no_type { $$ = make_decl_spec(NULL, $2, NULL, $1, STG_NONE); } - | function_specifier m_decl_spec_no_type { $$ = make_decl_spec(NULL, $2, NULL, $1, STG_NONE); } - | storage_cls_spec m_decl_spec_no_type { $$ = make_decl_spec(NULL, $2, NULL, NULL, $1); } + type_qualifier m_decl_spec_no_type { $$ = make_decl_spec(NULL, $2, NULL, STG_NONE, $1, 0); } + | function_specifier m_decl_spec_no_type { $$ = make_decl_spec(NULL, $2, NULL, STG_NONE, 0, $1); } + | storage_cls_spec m_decl_spec_no_type { $$ = make_decl_spec(NULL, $2, NULL, $1, 0, 0); } ; declarator: '*' m_type_qual_list declarator %prec PPTR - { $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); } - | callconv declarator { $$ = $2; if ($$->func_type) $$->func_type->attrs = append_attr($$->func_type->attrs, make_attrp(ATTR_CALLCONV, $1)); - else if ($$->type) $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); } + { $$ = $3; append_chain_type($$, type_new_pointer(NULL), $2); } + | callconv declarator { $$ = $2; append_chain_callconv( @$, $$->type, $1 ); } | direct_declarator ; direct_declarator: ident { $$ = make_declarator($1); } | '(' declarator ')' { $$ = $2; } - | direct_declarator array { $$ = $1; $$->type = append_array($$->type, $2); } - | direct_declarator '(' m_args ')' { $$ = $1; - $$->func_type = append_chain_type($$->type, type_new_function($3)); - $$->type = NULL; - } + | direct_declarator array { $$ = $1; append_array($$, $2); } + | direct_declarator '(' m_args ')' { $$ = $1; append_chain_type($$, type_new_function($3), 0); } ; /* abstract declarator */ abstract_declarator: '*' m_type_qual_list m_abstract_declarator %prec PPTR - { $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); } - | callconv m_abstract_declarator { $$ = $2; if ($$->func_type) $$->func_type->attrs = append_attr($$->func_type->attrs, make_attrp(ATTR_CALLCONV, $1)); - else if ($$->type) $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); } + { $$ = $3; append_chain_type($$, type_new_pointer(NULL), $2); } + | callconv m_abstract_declarator { $$ = $2; append_chain_callconv( @$, $$->type, $1 ); } | abstract_direct_declarator ; /* abstract declarator without accepting direct declarator */ abstract_declarator_no_direct: '*' m_type_qual_list m_any_declarator %prec PPTR - { $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); } - | callconv m_any_declarator { $$ = $2; if ($$->func_type) $$->func_type->attrs = append_attr($$->func_type->attrs, make_attrp(ATTR_CALLCONV, $1)); - else if ($$->type) $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); } + { $$ = $3; append_chain_type($$, type_new_pointer(NULL), $2); } + | callconv m_any_declarator { $$ = $2; append_chain_callconv( @$, $$->type, $1 ); } ; /* abstract declarator or empty */ -m_abstract_declarator: { $$ = make_declarator(NULL); } +m_abstract_declarator + : %empty { $$ = make_declarator(NULL); } | abstract_declarator ; /* abstract direct declarator */ abstract_direct_declarator: '(' abstract_declarator_no_direct ')' { $$ = $2; } - | abstract_direct_declarator array { $$ = $1; $$->type = append_array($$->type, $2); } - | array { $$ = make_declarator(NULL); $$->type = append_array($$->type, $1); } + | abstract_direct_declarator array { $$ = $1; append_array($$, $2); } + | array { $$ = make_declarator(NULL); append_array($$, $1); } | '(' m_args ')' { $$ = make_declarator(NULL); - $$->func_type = append_chain_type($$->type, type_new_function($2)); - $$->type = NULL; + append_chain_type($$, type_new_function($2), 0); } | abstract_direct_declarator '(' m_args ')' { $$ = $1; - $$->func_type = append_chain_type($$->type, type_new_function($3)); - $$->type = NULL; + append_chain_type($$, type_new_function($3), 0); } ; /* abstract or non-abstract declarator */ any_declarator: '*' m_type_qual_list m_any_declarator %prec PPTR - { $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); } - | callconv m_any_declarator { $$ = $2; $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); } + { $$ = $3; append_chain_type($$, type_new_pointer(NULL), $2); } + | callconv m_any_declarator { $$ = $2; append_chain_callconv( @$, $$->type, $1 ); } | any_direct_declarator ; /* abstract or non-abstract declarator without accepting direct declarator */ any_declarator_no_direct: '*' m_type_qual_list m_any_declarator %prec PPTR - { $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); } - | callconv m_any_declarator { $$ = $2; $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); } + { $$ = $3; append_chain_type($$, type_new_pointer(NULL), $2); } + | callconv m_any_declarator { $$ = $2; append_chain_callconv( @$, $$->type, $1 ); } ; /* abstract or non-abstract declarator or empty */ -m_any_declarator: { $$ = make_declarator(NULL); } +m_any_declarator + : %empty { $$ = make_declarator(NULL); } | any_declarator ; @@ -1082,17 +1311,15 @@ m_any_declarator: { $$ = make_declarator(NULL); } any_direct_declarator: ident { $$ = make_declarator($1); } | '(' any_declarator_no_direct ')' { $$ = $2; } - | any_direct_declarator array { $$ = $1; $$->type = append_array($$->type, $2); } - | array { $$ = make_declarator(NULL); $$->type = append_array($$->type, $1); } + | any_direct_declarator array { $$ = $1; append_array($$, $2); } + | array { $$ = make_declarator(NULL); append_array($$, $1); } | '(' m_args ')' { $$ = make_declarator(NULL); - $$->func_type = append_chain_type($$->type, type_new_function($2)); - $$->type = NULL; + append_chain_type($$, type_new_function($2), 0); } | any_direct_declarator '(' m_args ')' { $$ = $1; - $$->func_type = append_chain_type($$->type, type_new_function($3)); - $$->type = NULL; + append_chain_type($$, type_new_function($3), 0); } ; @@ -1101,7 +1328,8 @@ declarator_list: | declarator_list ',' declarator { $$ = append_declarator( $1, $3 ); } ; -m_bitfield: { $$ = NULL; } +m_bitfield + : %empty { $$ = NULL; } | ':' expr_const { $$ = $2; } ; @@ -1128,6 +1356,7 @@ threading_type: | tSINGLE { $$ = THREADING_SINGLE; } | tFREE { $$ = THREADING_FREE; } | tBOTH { $$ = THREADING_BOTH; } + | tMTA { $$ = THREADING_FREE; } ; pointer_type: @@ -1136,61 +1365,68 @@ pointer_type: | tPTR { $$ = FC_FP; } ; -structdef: tSTRUCT t_ident '{' fields '}' { $$ = type_new_struct($2, current_namespace, TRUE, $4); } +structdef: tSTRUCT m_typename '{' fields '}' { $$ = type_new_struct($2, current_namespace, TRUE, $4, &@2); } ; -type: tVOID { $$ = type_new_void(); } - | aKNOWNTYPE { $$ = find_type_or_error($1, 0); } - | base_type { $$ = $1; } - | enumdef { $$ = $1; } - | tENUM aIDENTIFIER { $$ = type_new_enum($2, current_namespace, FALSE, NULL); } - | structdef { $$ = $1; } - | tSTRUCT aIDENTIFIER { $$ = type_new_struct($2, current_namespace, FALSE, NULL); } - | uniondef { $$ = $1; } - | tUNION aIDENTIFIER { $$ = type_new_nonencapsulated_union($2, FALSE, NULL); } - | tSAFEARRAY '(' type ')' { $$ = make_safearray($3); } +unqualified_type: + tVOID { $$ = type_new_void(); } + | base_type { $$ = $1; } + | enumdef { $$ = $1; } + | tENUM typename { $$ = type_new_enum($2, current_namespace, FALSE, NULL, &@$); } + | structdef { $$ = $1; } + | tSTRUCT typename { $$ = type_new_struct($2, current_namespace, FALSE, NULL, &@$); } + | uniondef { $$ = $1; } + | tUNION typename { $$ = type_new_nonencapsulated_union($2, current_namespace, FALSE, NULL, &@$); } + | tSAFEARRAY '(' type ')' { $$ = make_safearray($3); } + | aKNOWNTYPE { $$ = find_type_or_error(current_namespace, $1); } + ; + +type: + unqualified_type + | namespace_pfx typename { $$ = find_type_or_error($1, $2); } + | parameterized_type { $$ = $1; } ; typedef: m_attributes tTYPEDEF m_attributes decl_spec declarator_list { $1 = append_attribs($1, $3); - reg_typedefs($4, $5, check_typedef_attrs($1)); - $$ = make_statement_typedef($5); + reg_typedefs( @$, $4, $5, check_typedef_attrs( $1 ) ); + $$ = make_statement_typedef($5, $4->type->defined && !$4->type->defined_in_import); } ; -uniondef: tUNION t_ident '{' ne_union_fields '}' - { $$ = type_new_nonencapsulated_union($2, TRUE, $4); } - | tUNION t_ident +uniondef: tUNION m_typename '{' ne_union_fields '}' + { $$ = type_new_nonencapsulated_union($2, current_namespace, TRUE, $4, &@2); } + | tUNION m_typename tSWITCH '(' s_field ')' - m_ident '{' cases '}' { $$ = type_new_encapsulated_union($2, $5, $7, $9); } + m_ident '{' cases '}' { $$ = type_new_encapsulated_union($2, $5, $7, $9, &@2); } ; version: - aNUM { $$ = MAKEVERSION($1, 0); } - | aNUM '.' aNUM { $$ = MAKEVERSION($1, $3); } - | aHEXNUM { $$ = $1; } + aNUM { $$ = MAKEVERSION($1.value, 0); } + | aNUM '.' aNUM { $$ = MAKEVERSION($1.value, $3.value); } + | aHEXNUM { $$ = $1.value; } ; acf_statements - : /* empty */ + : %empty | acf_interface acf_statements ; acf_int_statements - : /* empty */ + : %empty | acf_int_statement acf_int_statements ; acf_int_statement : tTYPEDEF acf_attributes aKNOWNTYPE ';' - { type_t *type = find_type_or_error($3, 0); + { type_t *type = find_type_or_error(current_namespace, $3); type->attrs = append_attr_list(type->attrs, $2); } ; acf_interface : acf_attributes tINTERFACE aKNOWNTYPE '{' acf_int_statements '}' - { type_t *iface = find_type_or_error2($3, 0); + { type_t *iface = find_type_or_error(current_namespace, $3); if (type_get_type(iface) != TYPE_INTERFACE) error_loc("%s is not an interface\n", iface->name); iface->attrs = append_attr_list(iface->attrs, $1); @@ -1198,8 +1434,8 @@ acf_interface ; acf_attributes - : /* empty */ { $$ = NULL; }; - | '[' acf_attribute_list ']' { $$ = $2; }; + : %empty { $$ = NULL; } + | '[' acf_attribute_list ']' { $$ = $2; } ; acf_attribute_list @@ -1208,12 +1444,12 @@ acf_attribute_list ; acf_attribute - : tALLOCATE '(' allocate_option_list ')' - { $$ = make_attrv(ATTR_ALLOCATE, $3); } - | tENCODE { $$ = make_attr(ATTR_ENCODE); } - | tDECODE { $$ = make_attr(ATTR_DECODE); } - | tEXPLICITHANDLE { $$ = make_attr(ATTR_EXPLICIT_HANDLE); } - ; + : tALLOCATE '(' allocate_option_list ')' + { $$ = attr_int( @$, ATTR_ALLOCATE, $3 ); } + | tENCODE { $$ = attr_int( @$, ATTR_ENCODE, 0 ); } + | tDECODE { $$ = attr_int( @$, ATTR_DECODE, 0 ); } + | tEXPLICITHANDLE { $$ = attr_int( @$, ATTR_EXPLICIT_HANDLE, 0 ); } + ; allocate_option_list : allocate_option { $$ = $1; } @@ -1227,6 +1463,7 @@ allocate_option | tALLNODES { $$ = FC_ALLOCATE_ALL_NODES; } | tSINGLENODE { $$ = 0; } ; + %% static void decl_builtin_basic(const char *name, enum type_basic_type type) @@ -1237,7 +1474,8 @@ static void decl_builtin_basic(const char *name, enum type_basic_type type) static void decl_builtin_alias(const char *name, type_t *t) { - reg_type(type_new_alias(t, name), name, NULL, 0); + const decl_spec_t ds = {.type = t}; + reg_type(type_new_alias(&ds, name), name, NULL, 0); } void init_types(void) @@ -1248,7 +1486,7 @@ void init_types(void) decl_builtin_basic("double", TYPE_BASIC_DOUBLE); decl_builtin_basic("error_status_t", TYPE_BASIC_ERROR_STATUS_T); decl_builtin_basic("handle_t", TYPE_BASIC_HANDLE); - decl_builtin_alias("boolean", type_new_basic(TYPE_BASIC_BYTE)); + decl_builtin_alias("boolean", type_new_basic(TYPE_BASIC_CHAR)); } static str_list_t *append_str(str_list_t *list, char *str) @@ -1267,152 +1505,53 @@ static str_list_t *append_str(str_list_t *list, char *str) return list; } -static attr_list_t *append_attr(attr_list_t *list, attr_t *attr) -{ - attr_t *attr_existing; - if (!attr) return list; - if (!list) - { - list = xmalloc( sizeof(*list) ); - list_init( list ); - } - LIST_FOR_EACH_ENTRY(attr_existing, list, attr_t, entry) - if (attr_existing->type == attr->type) - { - parser_warning("duplicate attribute %s\n", get_attr_display_name(attr->type)); - /* use the last attribute, like MIDL does */ - list_remove(&attr_existing->entry); - break; - } - list_add_tail( list, &attr->entry ); - return list; -} -static attr_list_t *move_attr(attr_list_t *dst, attr_list_t *src, enum attr_type type) -{ - attr_t *attr; - if (!src) return dst; - LIST_FOR_EACH_ENTRY(attr, src, attr_t, entry) - if (attr->type == type) - { - list_remove(&attr->entry); - return append_attr(dst, attr); - } - return dst; -} - -static attr_list_t *append_attr_list(attr_list_t *new_list, attr_list_t *old_list) -{ - struct list *entry; - - if (!old_list) return new_list; - - while ((entry = list_head(old_list))) - { - attr_t *attr = LIST_ENTRY(entry, attr_t, entry); - list_remove(entry); - new_list = append_attr(new_list, attr); - } - return new_list; -} - -typedef int (*map_attrs_filter_t)(attr_list_t*,const attr_t*); - -static attr_list_t *map_attrs(const attr_list_t *list, map_attrs_filter_t filter) -{ - attr_list_t *new_list; - const attr_t *attr; - attr_t *new_attr; - - if (!list) return NULL; - - new_list = xmalloc( sizeof(*list) ); - list_init( new_list ); - LIST_FOR_EACH_ENTRY(attr, list, const attr_t, entry) - { - if (filter && !filter(new_list, attr)) continue; - new_attr = xmalloc(sizeof(*new_attr)); - *new_attr = *attr; - list_add_tail(new_list, &new_attr->entry); - } - return new_list; -} - -static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, attr_t *attr, enum storage_class stgclass) +static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, + enum storage_class stgclass, enum type_qualifier qual, enum function_specifier func_specifier) { decl_spec_t *declspec = left ? left : right; if (!declspec) { declspec = xmalloc(sizeof(*declspec)); declspec->type = NULL; - declspec->attrs = NULL; declspec->stgclass = STG_NONE; + declspec->qualifier = 0; + declspec->func_specifier = 0; } declspec->type = type; if (left && declspec != left) { - declspec->attrs = append_attr_list(declspec->attrs, left->attrs); if (declspec->stgclass == STG_NONE) declspec->stgclass = left->stgclass; else if (left->stgclass != STG_NONE) error_loc("only one storage class can be specified\n"); + declspec->qualifier |= left->qualifier; + declspec->func_specifier |= left->func_specifier; assert(!left->type); free(left); } if (right && declspec != right) { - declspec->attrs = append_attr_list(declspec->attrs, right->attrs); if (declspec->stgclass == STG_NONE) declspec->stgclass = right->stgclass; else if (right->stgclass != STG_NONE) error_loc("only one storage class can be specified\n"); + declspec->qualifier |= right->qualifier; + declspec->func_specifier |= right->func_specifier; assert(!right->type); free(right); } - declspec->attrs = append_attr(declspec->attrs, attr); if (declspec->stgclass == STG_NONE) declspec->stgclass = stgclass; else if (stgclass != STG_NONE) error_loc("only one storage class can be specified\n"); - - /* apply attributes to type */ - if (type && declspec->attrs) - { - attr_list_t *attrs; - declspec->type = duptype(type, 1); - attrs = map_attrs(type->attrs, NULL); - declspec->type->attrs = append_attr_list(attrs, declspec->attrs); - declspec->attrs = NULL; - } + declspec->qualifier |= qual; + declspec->func_specifier |= func_specifier; return declspec; } -static attr_t *make_attr(enum attr_type type) -{ - attr_t *a = xmalloc(sizeof(attr_t)); - a->type = type; - a->u.ival = 0; - return a; -} - -static attr_t *make_attrv(enum attr_type type, unsigned int val) -{ - attr_t *a = xmalloc(sizeof(attr_t)); - a->type = type; - a->u.ival = val; - return a; -} - -static attr_t *make_attrp(enum attr_type type, void *val) -{ - attr_t *a = xmalloc(sizeof(attr_t)); - a->type = type; - a->u.pval = val; - return a; -} - static expr_list_t *append_expr(expr_list_t *list, expr_t *expr) { if (!expr) return list; @@ -1425,19 +1564,19 @@ static expr_list_t *append_expr(expr_list_t *list, expr_t *expr) return list; } -static type_t *append_array(type_t *chain, expr_t *expr) +static void append_array(declarator_t *decl, expr_t *expr) { type_t *array; if (!expr) - return chain; + return; /* An array is always a reference pointer unless explicitly marked otherwise * (regardless of what the default pointer attribute is). */ array = type_new_array(NULL, NULL, FALSE, expr->is_const ? expr->cval : 0, - expr->is_const ? NULL : expr, NULL, FC_RP); + expr->is_const ? NULL : expr, NULL); - return append_chain_type(chain, array); + append_chain_type(decl, array, 0); } static struct list type_pool = LIST_INIT(type_pool); @@ -1511,32 +1650,67 @@ static int is_allowed_range_type(const type_t *type) } } -static type_t *get_array_or_ptr_ref(type_t *type) +static type_t *get_chain_ref(type_t *type) { if (is_ptr(type)) - return type_pointer_get_ref(type); + return type_pointer_get_ref_type(type); else if (is_array(type)) - return type_array_get_element(type); + return type_array_get_element_type(type); + else if (is_func(type)) + return type_function_get_rettype(type); return NULL; } -static type_t *append_chain_type(type_t *chain, type_t *type) +static type_t *get_chain_end(type_t *type) +{ + type_t *inner; + while ((inner = get_chain_ref(type))) + type = inner; + return type; +} + +static void append_chain_type(declarator_t *decl, type_t *type, enum type_qualifier qual) { type_t *chain_type; - if (!chain) - return type; - for (chain_type = chain; get_array_or_ptr_ref(chain_type); chain_type = get_array_or_ptr_ref(chain_type)) - ; + if (!decl->type) + { + decl->type = type; + decl->qualifier = qual; + return; + } + chain_type = get_chain_end(decl->type); if (is_ptr(chain_type)) - chain_type->details.pointer.ref = type; + { + chain_type->details.pointer.ref.type = type; + chain_type->details.pointer.ref.qualifier = qual; + } else if (is_array(chain_type)) - chain_type->details.array.elem = type; + { + chain_type->details.array.elem.type = type; + chain_type->details.array.elem.qualifier = qual; + } + else if (is_func(chain_type)) + { + chain_type->details.function->retval->declspec.type = type; + chain_type->details.function->retval->declspec.qualifier = qual; + } else assert(0); - return chain; + if (!is_func(chain_type)) + type->attrs = move_attr(type->attrs, chain_type->attrs, ATTR_CALLCONV); +} + +static void append_chain_callconv( struct location where, type_t *chain, char *callconv ) +{ + type_t *chain_end; + + if (chain && (chain_end = get_chain_end(chain))) + chain_end->attrs = append_attr( chain_end->attrs, attr_ptr( where, ATTR_CALLCONV, callconv ) ); + else + error_loc("calling convention applied to non-function type\n"); } static warning_list_t *append_warning(warning_list_t *list, int num) @@ -1554,7 +1728,7 @@ static warning_list_t *append_warning(warning_list_t *list, int num) return list; } -static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const declarator_t *decl, +static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, declarator_t *decl, int top) { var_t *v = decl->var; @@ -1562,59 +1736,51 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl expr_list_t *lengs = get_attrp(attrs, ATTR_LENGTHIS); expr_t *dim; type_t **ptype; - type_t *func_type = decl ? decl->func_type : NULL; type_t *type = decl_spec->type; - if (is_attr(type->attrs, ATTR_INLINE)) + if (decl_spec->func_specifier & FUNCTION_SPECIFIER_INLINE) { - if (!func_type) + if (!decl || !is_func(decl->type)) error_loc("inline attribute applied to non-function type\n"); - else - { - type_t *t; - /* move inline attribute from return type node to function node */ - for (t = func_type; is_ptr(t); t = type_pointer_get_ref(t)) - ; - t->attrs = move_attr(t->attrs, type->attrs, ATTR_INLINE); - } } /* add type onto the end of the pointers in pident->type */ - v->type = append_chain_type(decl ? decl->type : NULL, type); - v->stgclass = decl_spec->stgclass; + append_chain_type(decl, type, decl_spec->qualifier); + v->declspec = *decl_spec; + v->declspec.type = decl->type; + v->declspec.qualifier = decl->qualifier; v->attrs = attrs; + v->is_defined = type->defined && !type->defined_in_import; + + if (is_attr(type->attrs, ATTR_CALLCONV) && !is_func(type)) + error_loc("calling convention applied to non-function type\n"); /* check for pointer attribute being applied to non-pointer, non-array * type */ - if (!is_array(v->type)) + if (!is_array(v->declspec.type)) { int ptr_attr = get_attrv(v->attrs, ATTR_POINTERTYPE); const type_t *ptr = NULL; - /* pointer attributes on the left side of the type belong to the function - * pointer, if one is being declared */ - type_t **pt = func_type ? &func_type : &v->type; - for (ptr = *pt; ptr && !ptr_attr; ) + for (ptr = v->declspec.type; ptr && !ptr_attr; ) { ptr_attr = get_attrv(ptr->attrs, ATTR_POINTERTYPE); if (!ptr_attr && type_is_alias(ptr)) - ptr = type_alias_get_aliasee(ptr); + ptr = type_alias_get_aliasee_type(ptr); else break; } if (is_ptr(ptr)) { if (ptr_attr && ptr_attr != FC_UP && - type_get_type(type_pointer_get_ref(ptr)) == TYPE_INTERFACE) - warning_loc_info(&v->loc_info, - "%s: pointer attribute applied to interface " - "pointer type has no effect\n", v->name); - if (!ptr_attr && top && (*pt)->details.pointer.def_fc != FC_RP) + type_get_type(type_pointer_get_ref_type(ptr)) == TYPE_INTERFACE) + warning_at( &v->where, "%s: pointer attribute applied to interface pointer type has no effect\n", v->name ); + if (!ptr_attr && top) { /* FIXME: this is a horrible hack to cope with the issue that we * store an offset to the typeformat string in the type object, but * two typeformat strings may be written depending on whether the * pointer is a toplevel parameter or not */ - *pt = duptype(*pt, 1); + v->declspec.type = duptype(v->declspec.type, 1); } } else if (ptr_attr) @@ -1625,16 +1791,16 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl { type_t *t = type; - if (!is_ptr(v->type) && !is_array(v->type)) + if (!is_ptr(v->declspec.type) && !is_array(v->declspec.type)) error_loc("'%s': [string] attribute applied to non-pointer, non-array type\n", v->name); for (;;) { if (is_ptr(t)) - t = type_pointer_get_ref(t); + t = type_pointer_get_ref_type(t); else if (is_array(t)) - t = type_array_get_element(t); + t = type_array_get_element_type(t); else break; } @@ -1651,15 +1817,15 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl if (is_attr(v->attrs, ATTR_V1ENUM)) { - if (type_get_type_detect_alias(v->type) != TYPE_ENUM) + if (type_get_type_detect_alias(v->declspec.type) != TYPE_ENUM) error_loc("'%s': [v1_enum] attribute applied to non-enum type\n", v->name); } - if (is_attr(v->attrs, ATTR_RANGE) && !is_allowed_range_type(v->type)) + if (is_attr(v->attrs, ATTR_RANGE) && !is_allowed_range_type(v->declspec.type)) error_loc("'%s': [range] attribute applied to non-integer type\n", v->name); - ptype = &v->type; + ptype = &v->declspec.type; if (sizes) LIST_FOR_EACH_ENTRY(dim, sizes, expr_t, entry) { if (dim->type != EXPR_VOID) @@ -1672,24 +1838,24 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl else *ptype = type_new_array((*ptype)->name, type_array_get_element(*ptype), FALSE, - 0, dim, NULL, 0); + 0, dim, NULL); } else if (is_ptr(*ptype)) *ptype = type_new_array((*ptype)->name, type_pointer_get_ref(*ptype), TRUE, - 0, dim, NULL, pointer_default); + 0, dim, NULL); else error_loc("%s: size_is attribute applied to illegal type\n", v->name); } if (is_ptr(*ptype)) - ptype = &(*ptype)->details.pointer.ref; + ptype = &(*ptype)->details.pointer.ref.type; else if (is_array(*ptype)) - ptype = &(*ptype)->details.array.elem; + ptype = &(*ptype)->details.array.elem.type; else error_loc("%s: too many expressions in size_is attribute\n", v->name); } - ptype = &v->type; + ptype = &v->declspec.type; if (lengs) LIST_FOR_EACH_ENTRY(dim, lengs, expr_t, entry) { if (dim->type != EXPR_VOID) @@ -1700,49 +1866,22 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl type_array_get_element(*ptype), type_array_is_decl_as_ptr(*ptype), type_array_get_dim(*ptype), - type_array_get_conformance(*ptype), - dim, type_array_get_ptr_default_fc(*ptype)); + type_array_get_conformance(*ptype), dim); } else error_loc("%s: length_is attribute applied to illegal type\n", v->name); } if (is_ptr(*ptype)) - ptype = &(*ptype)->details.pointer.ref; + ptype = &(*ptype)->details.pointer.ref.type; else if (is_array(*ptype)) - ptype = &(*ptype)->details.array.elem; + ptype = &(*ptype)->details.array.elem.type; else error_loc("%s: too many expressions in length_is attribute\n", v->name); } - /* v->type is currently pointing to the type on the left-side of the - * declaration, so we need to fix this up so that it is the return type of the - * function and make v->type point to the function side of the declaration */ - if (func_type) - { - type_t *ft, *t; - type_t *return_type = v->type; - v->type = func_type; - for (ft = v->type; is_ptr(ft); ft = type_pointer_get_ref(ft)) - ; - assert(type_get_type_detect_alias(ft) == TYPE_FUNCTION); - ft->details.function->retval = make_var(xstrdup("_RetVal")); - ft->details.function->retval->type = return_type; - /* move calling convention attribute, if present, from pointer nodes to - * function node */ - for (t = v->type; is_ptr(t); t = type_pointer_get_ref(t)) - ft->attrs = move_attr(ft->attrs, t->attrs, ATTR_CALLCONV); - } - else - { - type_t *t; - for (t = v->type; is_ptr(t); t = type_pointer_get_ref(t)) - if (is_attr(t->attrs, ATTR_CALLCONV)) - error_loc("calling convention applied to non-function-pointer type\n"); - } - if (decl->bits) - v->type = type_new_bitfield(v->type, decl->bits); + v->declspec.type = type_new_bitfield(v->declspec.type, decl->bits); return v; } @@ -1762,24 +1901,24 @@ static var_list_t *set_var_types(attr_list_t *attrs, decl_spec_t *decl_spec, dec return var_list; } -static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface) +typeref_list_t *append_typeref(typeref_list_t *list, typeref_t *ref) { - if (!iface) return list; + if (!ref) return list; if (!list) { list = xmalloc( sizeof(*list) ); list_init( list ); } - list_add_tail( list, &iface->entry ); + list_add_tail( list, &ref->entry ); return list; } -static ifref_t *make_ifref(type_t *iface) +typeref_t *make_typeref(type_t *type) { - ifref_t *l = xmalloc(sizeof(ifref_t)); - l->iface = iface; - l->attrs = NULL; - return l; + typeref_t *ref = xmalloc(sizeof(typeref_t)); + ref->type = type; + ref->attrs = NULL; + return ref; } var_list_t *append_var(var_list_t *list, var_t *var) @@ -1810,11 +1949,11 @@ var_t *make_var(char *name) { var_t *v = xmalloc(sizeof(var_t)); v->name = name; - v->type = NULL; + init_declspec(&v->declspec, NULL); v->attrs = NULL; v->eval = NULL; - v->stgclass = STG_NONE; - init_loc_info(&v->loc_info); + init_location( &v->where, NULL, NULL ); + v->is_defined = 1; return v; } @@ -1822,11 +1961,10 @@ static var_t *copy_var(var_t *src, char *name, map_attrs_filter_t attr_filter) { var_t *v = xmalloc(sizeof(var_t)); v->name = name; - v->type = src->type; + v->declspec = src->declspec; v->attrs = map_attrs(src->attrs, attr_filter); v->eval = src->eval; - v->stgclass = src->stgclass; - v->loc_info = src->loc_info; + v->where = src->where; return v; } @@ -1846,20 +1984,22 @@ static declarator_t *make_declarator(var_t *var) declarator_t *d = xmalloc(sizeof(*d)); d->var = var ? var : make_var(NULL); d->type = NULL; - d->func_type = NULL; + d->qualifier = 0; d->bits = NULL; return d; } static type_t *make_safearray(type_t *type) { - return type_new_array(NULL, type_new_alias(type, "SAFEARRAY"), TRUE, 0, - NULL, NULL, FC_RP); + decl_spec_t ds = {.type = type}; + ds.type = type_new_alias(&ds, "SAFEARRAY"); + return type_new_array(NULL, &ds, TRUE, 0, NULL, NULL); } static typelib_t *make_library(const char *name, const attr_list_t *attrs) { typelib_t *typelib = xmalloc(sizeof(*typelib)); + memset(typelib, 0, sizeof(*typelib)); typelib->name = xstrdup(name); typelib->attrs = attrs; list_init( &typelib->importlibs ); @@ -1915,6 +2055,43 @@ static void pop_namespace(const char *name) current_namespace = current_namespace->parent; } +static void push_namespaces(str_list_t *names) +{ + const struct str_list_entry_t *name; + LIST_FOR_EACH_ENTRY(name, names, const struct str_list_entry_t, entry) + push_namespace(name->str); +} + +static void pop_namespaces(str_list_t *names) +{ + const struct str_list_entry_t *name; + LIST_FOR_EACH_ENTRY_REV(name, names, const struct str_list_entry_t, entry) + pop_namespace(name->str); +} + +static void push_parameters_namespace(const char *name) +{ + struct namespace *namespace; + + if (!(namespace = find_sub_namespace(current_namespace, name))) + { + namespace = xmalloc(sizeof(*namespace)); + namespace->name = xstrdup(name); + namespace->parent = current_namespace; + list_add_tail(¤t_namespace->children, &namespace->entry); + list_init(&namespace->children); + memset(namespace->type_hash, 0, sizeof(namespace->type_hash)); + } + + parameters_namespace = namespace; +} + +static void pop_parameters_namespace(const char *name) +{ + assert(!strcmp(parameters_namespace->name, name) && parameters_namespace->parent); + parameters_namespace = NULL; +} + struct rtype { const char *name; type_t *type; @@ -1936,79 +2113,29 @@ type_t *reg_type(type_t *type, const char *name, struct namespace *namespace, in nt = xmalloc(sizeof(struct rtype)); nt->name = name; if (is_global_namespace(namespace)) + { type->c_name = name; + type->qualified_name = name; + } else - type->c_name = format_namespace(namespace, "__x_", "_C", name); + { + type->c_name = format_namespace(namespace, "__x_", "_C", name, use_abi_namespace ? "ABI" : NULL); + type->qualified_name = format_namespace(namespace, "", "::", name, use_abi_namespace ? "ABI" : NULL); + } nt->type = type; nt->t = t; nt->next = namespace->type_hash[hash]; namespace->type_hash[hash] = nt; - if ((t == tsSTRUCT || t == tsUNION)) - fix_incomplete_types(type); return type; } -static int is_incomplete(const type_t *t) +static type_t *reg_typedefs( struct location where, decl_spec_t *decl_spec, declarator_list_t *decls, attr_list_t *attrs ) { - return !t->defined && - (type_get_type_detect_alias(t) == TYPE_STRUCT || - type_get_type_detect_alias(t) == TYPE_UNION || - type_get_type_detect_alias(t) == TYPE_ENCAPSULATED_UNION); -} - -void add_incomplete(type_t *t) -{ - struct typenode *tn = xmalloc(sizeof *tn); - tn->type = t; - list_add_tail(&incomplete_types, &tn->entry); -} - -static void fix_type(type_t *t) -{ - if (type_is_alias(t) && is_incomplete(t)) { - type_t *ot = type_alias_get_aliasee(t); - fix_type(ot); - if (type_get_type_detect_alias(ot) == TYPE_STRUCT || - type_get_type_detect_alias(ot) == TYPE_UNION || - type_get_type_detect_alias(ot) == TYPE_ENCAPSULATED_UNION) - t->details.structure = ot->details.structure; - t->defined = ot->defined; - } -} - -static void fix_incomplete(void) -{ - struct typenode *tn, *next; - - LIST_FOR_EACH_ENTRY_SAFE(tn, next, &incomplete_types, struct typenode, entry) { - fix_type(tn->type); - list_remove(&tn->entry); - free(tn); - } -} - -static void fix_incomplete_types(type_t *complete_type) -{ - struct typenode *tn, *next; - - LIST_FOR_EACH_ENTRY_SAFE(tn, next, &incomplete_types, struct typenode, entry) - { - if (type_is_equal(complete_type, tn->type)) - { - tn->type->details.structure = complete_type->details.structure; - list_remove(&tn->entry); - free(tn); - } - } -} - -static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, attr_list_t *attrs) -{ - const declarator_t *decl; + declarator_t *decl; type_t *type = decl_spec->type; if (is_attr(attrs, ATTR_UUID) && !is_attr(attrs, ATTR_PUBLIC)) - attrs = append_attr( attrs, make_attr(ATTR_PUBLIC) ); + attrs = append_attr( attrs, attr_int( where, ATTR_PUBLIC, 0 ) ); /* We must generate names for tagless enum, struct or union. Typedef-ing a tagless enum, struct or union means we want the typedef @@ -2019,22 +2146,26 @@ static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, at type_get_type_detect_alias(type) == TYPE_ENCAPSULATED_UNION) { if (!type->name) + { type->name = gen_name(); + if (!is_attr(attrs, ATTR_PUBLIC)) + attrs = append_attr( attrs, attr_int( where, ATTR_PUBLIC, 0 ) ); + } /* replace existing attributes when generating a typelib */ if (do_typelib) type->attrs = attrs; } -#ifdef __REACTOS__ /* r53187 / 5bf224e */ +#ifdef __REACTOS__ /* r53187 / 5bf224e */ /* Append the SWITCHTYPE attribute to a non-encapsulated union if it does not already have it. */ if (type_get_type_detect_alias(type) == TYPE_UNION && is_attr(attrs, ATTR_SWITCHTYPE) && !is_attr(type->attrs, ATTR_SWITCHTYPE)) - type->attrs = append_attr(type->attrs, make_attrp(ATTR_SWITCHTYPE, get_attrp(attrs, ATTR_SWITCHTYPE))); + type->attrs = append_attr(type->attrs, attr_ptr( where, ATTR_SWITCHTYPE, get_attrp(attrs, ATTR_SWITCHTYPE) )); #endif - LIST_FOR_EACH_ENTRY( decl, decls, const declarator_t, entry ) + LIST_FOR_EACH_ENTRY( decl, decls, declarator_t, entry ) { if (decl->var->name) { @@ -2052,17 +2183,14 @@ static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, at * FIXME: We may consider string separated type tables for each input * for cleaner solution. */ - if (cur && input_name == cur->loc_info.input_name) - error_loc("%s: redefinition error; original definition was at %s:%d\n", - cur->name, cur->loc_info.input_name, - cur->loc_info.line_number); + if (cur && input_name == cur->where.input_name) + error_loc( "%s: redefinition error; original definition was at %s:%d\n", + cur->name, cur->where.input_name, cur->where.first_line ); name = declare_var(attrs, decl_spec, decl, 0); - cur = type_new_alias(name->type, name->name); + cur = type_new_alias(&name->declspec, name->name); cur->attrs = attrs; - if (is_incomplete(cur)) - add_incomplete(cur); reg_type(cur, cur->name, current_namespace, 0); } } @@ -2086,26 +2214,34 @@ type_t *find_type(const char *name, struct namespace *namespace, int t) return NULL; } -static type_t *find_type_or_error(const char *name, int t) +static type_t *find_type_or_error(struct namespace *namespace, const char *name) { - type_t *type = find_type(name, NULL, t); - if (!type) { - error_loc("type '%s' not found\n", name); - return NULL; - } - return type; + type_t *type; + if (!(type = find_type(name, namespace, 0)) && + !(type = find_type(name, parameters_namespace, 0))) + { + error_loc("type '%s' not found in %s namespace\n", name, namespace && namespace->name ? namespace->name : "global"); + return NULL; + } + return type; } -static type_t *find_type_or_error2(char *name, int t) +static struct namespace *find_namespace_or_error(struct namespace *parent, const char *name) { - type_t *tp = find_type_or_error(name, t); - free(name); - return tp; + struct namespace *namespace = NULL; + + if (!winrt_mode) + error_loc("namespaces are only supported in winrt mode.\n"); + else if (!(namespace = find_sub_namespace(parent, name))) + error_loc("namespace '%s' not found in '%s'\n", name, parent->name); + + return namespace; } int is_type(const char *name) { - return find_type(name, current_namespace, 0) != NULL; + return find_type(name, current_namespace, 0) != NULL || + find_type(name, parameters_namespace, 0); } type_t *get_type(enum type_type type, char *name, struct namespace *namespace, int t) @@ -2166,330 +2302,21 @@ var_t *find_const(const char *name, int f) return cur->var; } -static char *gen_name(void) +char *gen_name(void) { - static const char format[] = "__WIDL_%s_generated_name_%08lX"; static unsigned long n = 0; static const char *file_id; - static size_t size; - char *name; if (! file_id) { - char *dst = dup_basename(input_idl_name, ".idl"); + char *dst = replace_extension( idl_name, ".idl", "" ); file_id = dst; for (; *dst; ++dst) if (! isalnum((unsigned char) *dst)) *dst = '_'; - - size = sizeof format - 7 + strlen(file_id) + 8; } - - name = xmalloc(size); - sprintf(name, format, file_id, n++); - return name; -} - -struct allowed_attr -{ - unsigned int dce_compatible : 1; - unsigned int acf : 1; - unsigned int on_interface : 1; - unsigned int on_function : 1; - unsigned int on_arg : 1; - unsigned int on_type : 1; - unsigned int on_enum : 1; - unsigned int on_struct : 2; - unsigned int on_union : 1; - unsigned int on_field : 1; - unsigned int on_library : 1; - unsigned int on_dispinterface : 1; - unsigned int on_module : 1; - unsigned int on_coclass : 1; - const char *display_name; -}; - -struct allowed_attr allowed_attr[] = -{ - /* attr { D ACF I Fn ARG T En St Un Fi L DI M C } */ - /* ATTR_AGGREGATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "aggregatable" }, - /* ATTR_ALLOCATE */ { 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "allocate" }, - /* ATTR_ANNOTATION */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "annotation" }, - /* ATTR_APPOBJECT */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "appobject" }, - /* ATTR_ASYNC */ { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "async" }, - /* ATTR_ASYNCUUID */ { 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, "async_uuid" }, - /* ATTR_AUTO_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "auto_handle" }, - /* ATTR_BINDABLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "bindable" }, - /* ATTR_BROADCAST */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "broadcast" }, - /* ATTR_CALLAS */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "call_as" }, - /* ATTR_CALLCONV */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, - /* ATTR_CASE */ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "case" }, - /* ATTR_CODE */ { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "code" }, - /* ATTR_COMMSTATUS */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "comm_status" }, - /* ATTR_CONST */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "const" }, - /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" }, - /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, "control" }, - /* ATTR_DECODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "decode" }, - /* ATTR_DEFAULT */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, "default" }, - /* ATTR_DEFAULTBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultbind" }, - /* ATTR_DEFAULTCOLLELEM */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultcollelem" }, - /* ATTR_DEFAULTVALUE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "defaultvalue" }, - /* ATTR_DEFAULTVTABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "defaultvtable" }, - /* ATTR_DISABLECONSISTENCYCHECK */{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "disable_consistency_check" }, - /* ATTR_DISPINTERFACE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, - /* ATTR_DISPLAYBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "displaybind" }, - /* ATTR_DLLNAME */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "dllname" }, - /* ATTR_DUAL */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "dual" }, - /* ATTR_ENABLEALLOCATE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "enable_allocate" }, - /* ATTR_ENCODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "encode" }, - /* ATTR_ENDPOINT */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "endpoint" }, - /* ATTR_ENTRY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "entry" }, - /* ATTR_EXPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "explicit_handle" }, - /* ATTR_FAULTSTATUS */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "fault_status" }, - /* ATTR_FORCEALLOCATE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "force_allocate" }, - /* ATTR_HANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "handle" }, - /* ATTR_HELPCONTEXT */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, "helpcontext" }, - /* ATTR_HELPFILE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "helpfile" }, - /* ATTR_HELPSTRING */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, "helpstring" }, - /* ATTR_HELPSTRINGCONTEXT */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, "helpstringcontext" }, - /* ATTR_HELPSTRINGDLL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "helpstringdll" }, - /* ATTR_HIDDEN */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, "hidden" }, - /* ATTR_ID */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, "id" }, - /* ATTR_IDEMPOTENT */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "idempotent" }, - /* ATTR_IGNORE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "ignore" }, - /* ATTR_IIDIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, "iid_is" }, - /* ATTR_IMMEDIATEBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "immediatebind" }, - /* ATTR_IMPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "implicit_handle" }, - /* ATTR_IN */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" }, - /* ATTR_INLINE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inline" }, - /* ATTR_INPUTSYNC */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" }, - /* ATTR_LENGTHIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, "length_is" }, - /* ATTR_LIBLCID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "lcid" }, - /* ATTR_LICENSED */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "licensed" }, - /* ATTR_LOCAL */ { 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "local" }, - /* ATTR_MAYBE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "maybe" }, - /* ATTR_MESSAGE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "message" }, - /* ATTR_NOCODE */ { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nocode" }, - /* ATTR_NONBROWSABLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonbrowsable" }, - /* ATTR_NONCREATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "noncreatable" }, - /* ATTR_NONEXTENSIBLE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nonextensible" }, - /* ATTR_NOTIFY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify" }, - /* ATTR_NOTIFYFLAG */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "notify_flag" }, - /* ATTR_OBJECT */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "object" }, - /* ATTR_ODL */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "odl" }, - /* ATTR_OLEAUTOMATION */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "oleautomation" }, - /* ATTR_OPTIMIZE */ { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optimize" }, - /* ATTR_OPTIONAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "optional" }, - /* ATTR_OUT */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "out" }, - /* ATTR_PARAMLCID */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "lcid" }, - /* ATTR_PARTIALIGNORE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "partial_ignore" }, - /* ATTR_POINTERDEFAULT */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "pointer_default" }, - /* ATTR_POINTERTYPE */ { 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, "ref, unique or ptr" }, - /* ATTR_PROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "progid" }, - /* ATTR_PROPGET */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propget" }, - /* ATTR_PROPPUT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propput" }, - /* ATTR_PROPPUTREF */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "propputref" }, - /* ATTR_PROXY */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "proxy" }, - /* ATTR_PUBLIC */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "public" }, - /* ATTR_RANGE */ { 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, "range" }, - /* ATTR_READONLY */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, "readonly" }, - /* ATTR_REPRESENTAS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "represent_as" }, - /* ATTR_REQUESTEDIT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "requestedit" }, - /* ATTR_RESTRICTED */ { 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, "restricted" }, - /* ATTR_RETVAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "retval" }, - /* ATTR_SIZEIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, "size_is" }, - /* ATTR_SOURCE */ { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "source" }, - /* ATTR_STRICTCONTEXTHANDLE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "strict_context_handle" }, - /* ATTR_STRING */ { 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, "string" }, - /* ATTR_SWITCHIS */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, "switch_is" }, - /* ATTR_SWITCHTYPE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, "switch_type" }, - /* ATTR_THREADING */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "threading" }, - /* ATTR_TRANSMITAS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "transmit_as" }, - /* ATTR_UIDEFAULT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "uidefault" }, - /* ATTR_USESGETLASTERROR */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "usesgetlasterror" }, - /* ATTR_USERMARSHAL */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "user_marshal" }, - /* ATTR_UUID */ { 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, "uuid" }, - /* ATTR_V1ENUM */ { 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, "v1_enum" }, - /* ATTR_VARARG */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "vararg" }, - /* ATTR_VERSION */ { 1, 0, 1, 0, 0, 1, 1, 2, 0, 0, 1, 0, 0, 1, "version" }, - /* ATTR_VIPROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "vi_progid" }, - /* ATTR_WIREMARSHAL */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "wire_marshal" }, -}; - -const char *get_attr_display_name(enum attr_type type) -{ - return allowed_attr[type].display_name; -} - -static attr_list_t *check_iface_attrs(const char *name, attr_list_t *attrs) -{ - const attr_t *attr; - if (!attrs) return attrs; - LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry) - { - if (!allowed_attr[attr->type].on_interface) - error_loc("inapplicable attribute %s for interface %s\n", - allowed_attr[attr->type].display_name, name); - if (attr->type == ATTR_IMPLICIT_HANDLE) - { - const var_t *var = attr->u.pval; - if (type_get_type( var->type) == TYPE_BASIC && - type_basic_get_type( var->type ) == TYPE_BASIC_HANDLE) - continue; - if (is_aliaschain_attr( var->type, ATTR_HANDLE )) - continue; - error_loc("attribute %s requires a handle type in interface %s\n", - allowed_attr[attr->type].display_name, name); - } - } - return attrs; -} - -static attr_list_t *check_function_attrs(const char *name, attr_list_t *attrs) -{ - const attr_t *attr; - if (!attrs) return attrs; - LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry) - { - if (!allowed_attr[attr->type].on_function) - error_loc("inapplicable attribute %s for function %s\n", - allowed_attr[attr->type].display_name, name); - } - return attrs; -} - -static void check_arg_attrs(const var_t *arg) -{ - const attr_t *attr; - - if (arg->attrs) - { - LIST_FOR_EACH_ENTRY(attr, arg->attrs, const attr_t, entry) - { - if (!allowed_attr[attr->type].on_arg) - error_loc("inapplicable attribute %s for argument %s\n", - allowed_attr[attr->type].display_name, arg->name); - } - } -} - -static attr_list_t *check_typedef_attrs(attr_list_t *attrs) -{ - const attr_t *attr; - if (!attrs) return attrs; - LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry) - { - if (!allowed_attr[attr->type].on_type) - error_loc("inapplicable attribute %s for typedef\n", - allowed_attr[attr->type].display_name); - } - return attrs; -} - -static attr_list_t *check_enum_attrs(attr_list_t *attrs) -{ - const attr_t *attr; - if (!attrs) return attrs; - LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry) - { - if (!allowed_attr[attr->type].on_enum) - error_loc("inapplicable attribute %s for enum\n", - allowed_attr[attr->type].display_name); - } - return attrs; -} - -static attr_list_t *check_struct_attrs(attr_list_t *attrs) -{ - int mask = winrt_mode ? 3 : 1; - const attr_t *attr; - if (!attrs) return attrs; - LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry) - { - if (!(allowed_attr[attr->type].on_struct & mask)) - error_loc("inapplicable attribute %s for struct\n", - allowed_attr[attr->type].display_name); - } - return attrs; -} - -static attr_list_t *check_union_attrs(attr_list_t *attrs) -{ - const attr_t *attr; - if (!attrs) return attrs; - LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry) - { - if (!allowed_attr[attr->type].on_union) - error_loc("inapplicable attribute %s for union\n", - allowed_attr[attr->type].display_name); - } - return attrs; -} - -static attr_list_t *check_field_attrs(const char *name, attr_list_t *attrs) -{ - const attr_t *attr; - if (!attrs) return attrs; - LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry) - { - if (!allowed_attr[attr->type].on_field) - error_loc("inapplicable attribute %s for field %s\n", - allowed_attr[attr->type].display_name, name); - } - return attrs; -} - -static attr_list_t *check_library_attrs(const char *name, attr_list_t *attrs) -{ - const attr_t *attr; - if (!attrs) return attrs; - LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry) - { - if (!allowed_attr[attr->type].on_library) - error_loc("inapplicable attribute %s for library %s\n", - allowed_attr[attr->type].display_name, name); - } - return attrs; -} - -static attr_list_t *check_dispiface_attrs(const char *name, attr_list_t *attrs) -{ - const attr_t *attr; - if (!attrs) return attrs; - LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry) - { - if (!allowed_attr[attr->type].on_dispinterface) - error_loc("inapplicable attribute %s for dispinterface %s\n", - allowed_attr[attr->type].display_name, name); - } - return attrs; -} - -static attr_list_t *check_module_attrs(const char *name, attr_list_t *attrs) -{ - const attr_t *attr; - if (!attrs) return attrs; - LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry) - { - if (!allowed_attr[attr->type].on_module) - error_loc("inapplicable attribute %s for module %s\n", - allowed_attr[attr->type].display_name, name); - } - return attrs; -} - -static attr_list_t *check_coclass_attrs(const char *name, attr_list_t *attrs) -{ - const attr_t *attr; - if (!attrs) return attrs; - LIST_FOR_EACH_ENTRY(attr, attrs, const attr_t, entry) - { - if (!allowed_attr[attr->type].on_coclass) - error_loc("inapplicable attribute %s for coclass %s\n", - allowed_attr[attr->type].display_name, name); - } - return attrs; + return strmake("__WIDL_%s_generated_name_%08lX", file_id, n++); } static int is_allowed_conf_type(const type_t *type) @@ -2530,7 +2357,15 @@ static int is_allowed_conf_type(const type_t *type) case TYPE_FUNCTION: case TYPE_INTERFACE: case TYPE_BITFIELD: + case TYPE_RUNTIMECLASS: + case TYPE_DELEGATE: return FALSE; + case TYPE_APICONTRACT: + case TYPE_PARAMETERIZED_TYPE: + case TYPE_PARAMETER: + /* not supposed to be here */ + assert(0); + break; } return FALSE; } @@ -2542,7 +2377,7 @@ static int is_ptr_guid_type(const type_t *type) /* second, make sure it is a pointer to something of size sizeof(GUID), * i.e. 16 bytes */ - return (type_memsize(type_pointer_get_ref(type)) == 16); + return (type_memsize(type_pointer_get_ref_type(type)) == 16); } static void check_conformance_expr_list(const char *attr_name, const var_t *arg, const type_t *container_type, expr_list_t *expr_list) @@ -2557,8 +2392,7 @@ static void check_conformance_expr_list(const char *attr_name, const var_t *arg, { const type_t *expr_type = expr_resolve_type(&expr_loc, container_type, dim); if (!is_allowed_conf_type(expr_type)) - error_loc_info(&arg->loc_info, "expression must resolve to integral type <= 32bits for attribute %s\n", - attr_name); + error_at( &arg->where, "expression must resolve to integral type <= 32bits for attribute %s\n", attr_name ); } } } @@ -2569,7 +2403,7 @@ static void check_remoting_fields(const var_t *var, type_t *type); static void check_field_common(const type_t *container_type, const char *container_name, const var_t *arg) { - type_t *type = arg->type; + type_t *type = arg->declspec.type; int more_to_do; const char *container_type_name; const char *var_type; @@ -2599,10 +2433,8 @@ static void check_field_common(const type_t *container_type, } if (is_attr(arg->attrs, ATTR_LENGTHIS) && - (is_attr(arg->attrs, ATTR_STRING) || is_aliaschain_attr(arg->type, ATTR_STRING))) - error_loc_info(&arg->loc_info, - "string and length_is specified for argument %s are mutually exclusive attributes\n", - arg->name); + (is_attr(arg->attrs, ATTR_STRING) || is_aliaschain_attr(arg->declspec.type, ATTR_STRING))) + error_at( &arg->where, "string and length_is specified for argument %s are mutually exclusive attributes\n", arg->name ); if (is_attr(arg->attrs, ATTR_SIZEIS)) { @@ -2625,7 +2457,7 @@ static void check_field_common(const type_t *container_type, expr_loc.attr = "iid_is"; expr_type = expr_resolve_type(&expr_loc, container_type, expr); if (!expr_type || !is_ptr_guid_type(expr_type)) - error_loc_info(&arg->loc_info, "expression must resolve to pointer to GUID type for attribute iid_is\n"); + error_at( &arg->where, "expression must resolve to pointer to GUID type for attribute iid_is\n" ); } } if (is_attr(arg->attrs, ATTR_SWITCHIS)) @@ -2639,8 +2471,7 @@ static void check_field_common(const type_t *container_type, expr_loc.attr = "switch_is"; expr_type = expr_resolve_type(&expr_loc, container_type, expr); if (!expr_type || !is_allowed_conf_type(expr_type)) - error_loc_info(&arg->loc_info, "expression must resolve to integral type <= 32bits for attribute %s\n", - expr_loc.attr); + error_at( &arg->where, "expression must resolve to integral type <= 32bits for attribute %s\n", expr_loc.attr ); } } @@ -2680,39 +2511,43 @@ static void check_field_common(const type_t *container_type, default: break; } - error_loc_info(&arg->loc_info, "%s \'%s\' of %s \'%s\' %s\n", - var_type, arg->name, container_type_name, container_name, reason); + error_at( &arg->where, "%s \'%s\' of %s \'%s\' %s\n", var_type, arg->name, container_type_name, container_name, reason ); break; } case TGT_CTXT_HANDLE: case TGT_CTXT_HANDLE_POINTER: if (type_get_type(container_type) != TYPE_FUNCTION) - error_loc_info(&arg->loc_info, - "%s \'%s\' of %s \'%s\' cannot be a context handle\n", - var_type, arg->name, container_type_name, - container_name); + error_at( &arg->where, "%s \'%s\' of %s \'%s\' cannot be a context handle\n", + var_type, arg->name, container_type_name, container_name ); break; case TGT_STRING: { const type_t *t = type; while (is_ptr(t)) - t = type_pointer_get_ref(t); + t = type_pointer_get_ref_type(t); if (is_aliaschain_attr(t, ATTR_RANGE)) - warning_loc_info(&arg->loc_info, "%s: range not verified for a string of ranged types\n", arg->name); + warning_at( &arg->where, "%s: range not verified for a string of ranged types\n", arg->name ); break; } case TGT_POINTER: - type = type_pointer_get_ref(type); - more_to_do = TRUE; + if (type_get_type(type_pointer_get_ref_type(type)) != TYPE_VOID || + !type->name || strcmp(type->name, "HANDLE")) + { + type = type_pointer_get_ref_type(type); + more_to_do = TRUE; + } break; case TGT_ARRAY: - type = type_array_get_element(type); + type = type_array_get_element_type(type); more_to_do = TRUE; break; + case TGT_ENUM: + type = type_get_real_type(type); + if (!type_is_complete(type)) + error_at( &arg->where, "undefined type declaration \"enum %s\"\n", type->name ); case TGT_USER_TYPE: case TGT_IFACE_POINTER: case TGT_BASIC: - case TGT_ENUM: case TGT_RANGE: /* nothing to do */ break; @@ -2737,13 +2572,18 @@ static void check_remoting_fields(const var_t *var, type_t *type) if (type_is_complete(type)) fields = type_struct_get_fields(type); else - error_loc_info(&var->loc_info, "undefined type declaration %s\n", type->name); + error_at( &var->where, "undefined type declaration \"struct %s\"\n", type->name ); } else if (type_get_type(type) == TYPE_UNION || type_get_type(type) == TYPE_ENCAPSULATED_UNION) - fields = type_union_get_cases(type); + { + if (type_is_complete(type)) + fields = type_union_get_cases(type); + else + error_at( &var->where, "undefined type declaration \"union %s\"\n", type->name ); + } if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) - if (field->type) check_field_common(type, type->name, field); + if (field->declspec.type) check_field_common(type, type->name, field); } /* checks that arguments for a function make sense for marshalling and unmarshalling */ @@ -2752,9 +2592,12 @@ static void check_remoting_args(const var_t *func) const char *funcname = func->name; const var_t *arg; - if (func->type->details.function->args) LIST_FOR_EACH_ENTRY( arg, func->type->details.function->args, const var_t, entry ) + if (!type_function_get_args(func->declspec.type)) + return; + + LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), const var_t, entry ) { - const type_t *type = arg->type; + const type_t *type = arg->declspec.type; /* check that [out] parameters have enough pointer levels */ if (is_attr(arg->attrs, ATTR_OUT)) @@ -2768,10 +2611,10 @@ static void check_remoting_args(const var_t *func) case TGT_UNION: case TGT_CTXT_HANDLE: case TGT_USER_TYPE: - error_loc_info(&arg->loc_info, "out parameter \'%s\' of function \'%s\' is not a pointer\n", arg->name, funcname); + error_at( &arg->where, "out parameter \'%s\' of function \'%s\' is not a pointer\n", arg->name, funcname ); break; case TGT_IFACE_POINTER: - error_loc_info(&arg->loc_info, "out interface pointer \'%s\' of function \'%s\' is not a double pointer\n", arg->name, funcname); + error_at( &arg->where, "out interface pointer \'%s\' of function \'%s\' is not a double pointer\n", arg->name, funcname ); break; case TGT_STRING: if (is_array(type)) @@ -2782,7 +2625,7 @@ static void check_remoting_args(const var_t *func) if (!type_array_has_conformance(type) && type_array_get_dim(type)) break; } if (is_attr( arg->attrs, ATTR_IN )) break; - error_loc_info(&arg->loc_info, "out parameter \'%s\' of function \'%s\' cannot be an unsized string\n", arg->name, funcname); + error_at( &arg->where, "out parameter \'%s\' of function \'%s\' cannot be an unsized string\n", arg->name, funcname ); break; case TGT_INVALID: /* already error'd before we get here */ @@ -2794,16 +2637,16 @@ static void check_remoting_args(const var_t *func) } } - check_field_common(func->type, funcname, arg); + check_field_common(func->declspec.type, funcname, arg); } - if (type_get_type(type_function_get_rettype(func->type)) != TYPE_VOID) + if (type_get_type(type_function_get_rettype(func->declspec.type)) != TYPE_VOID) { var_t var; var = *func; - var.type = type_function_get_rettype(func->type); + var.declspec.type = type_function_get_rettype(func->declspec.type); var.name = xstrdup("return value"); - check_field_common(func->type, funcname, &var); + check_field_common(func->declspec.type, funcname, &var); free(var.name); } } @@ -2819,15 +2662,36 @@ static void add_explicit_handle_if_necessary(const type_t *iface, var_t *func) * "[in] handle_t IDL_handle" as the first parameter to the * function */ var_t *idl_handle = make_var(xstrdup("IDL_handle")); - idl_handle->attrs = append_attr(NULL, make_attr(ATTR_IN)); - idl_handle->type = find_type_or_error("handle_t", 0); - type_function_add_head_arg(func->type, idl_handle); + idl_handle->attrs = append_attr( NULL, attr_int( iface->where, ATTR_IN, 0 ) ); + idl_handle->declspec.type = find_type_or_error(NULL, "handle_t"); + type_function_add_head_arg(func->declspec.type, idl_handle); } } static void check_functions(const type_t *iface, int is_inside_library) { const statement_t *stmt; + /* check for duplicates */ + if (is_attr(iface->attrs, ATTR_DISPINTERFACE)) + { + var_list_t *methods = type_dispiface_get_methods(iface); + var_t *func, *func_iter; + + if (methods) LIST_FOR_EACH_ENTRY( func, methods, var_t, entry ) + { + LIST_FOR_EACH_ENTRY( func_iter, methods, var_t, entry ) + { + if (func == func_iter) break; + if (strcmp(func->name, func_iter->name)) continue; + if (is_attr(func->attrs, ATTR_EVENTADD) != is_attr(func_iter->attrs, ATTR_EVENTADD)) continue; + if (is_attr(func->attrs, ATTR_EVENTREMOVE) != is_attr(func_iter->attrs, ATTR_EVENTREMOVE)) continue; + if (is_attr(func->attrs, ATTR_PROPGET) != is_attr(func_iter->attrs, ATTR_PROPGET)) continue; + if (is_attr(func->attrs, ATTR_PROPPUT) != is_attr(func_iter->attrs, ATTR_PROPPUT)) continue; + if (is_attr(func->attrs, ATTR_PROPPUTREF) != is_attr(func_iter->attrs, ATTR_PROPPUTREF)) continue; + error_at( &func->where, "duplicated function \'%s\'\n", func->name ); + } + } + } if (is_attr(iface->attrs, ATTR_EXPLICIT_HANDLE)) { STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) @@ -2847,14 +2711,6 @@ static void check_functions(const type_t *iface, int is_inside_library) } } -static char *concat_str(const char *prefix, const char *str) -{ - char *ret = xmalloc(strlen(prefix) + strlen(str) + 1); - strcpy(ret, prefix); - strcat(ret, str); - return ret; -} - static int async_iface_attrs(attr_list_t *attrs, const attr_t *attr) { switch(attr->type) @@ -2862,7 +2718,7 @@ static int async_iface_attrs(attr_list_t *attrs, const attr_t *attr) case ATTR_UUID: return 0; case ATTR_ASYNCUUID: - append_attr(attrs, make_attrp(ATTR_UUID, attr->u.pval)); + append_attr( attrs, attr_ptr( attr->where, ATTR_UUID, attr->u.pval ) ); return 0; default: return 1; @@ -2888,46 +2744,70 @@ static void check_async_uuid(type_t *iface) if (!is_attr(iface->attrs, ATTR_ASYNCUUID)) return; - inherit = iface->details.iface->inherit; + inherit = type_iface_get_inherit(iface); if (inherit && strcmp(inherit->name, "IUnknown")) - inherit = inherit->details.iface->async_iface; + inherit = type_iface_get_async_iface(inherit); if (!inherit) error_loc("async_uuid applied to an interface with incompatible parent\n"); - async_iface = get_type(TYPE_INTERFACE, concat_str("Async", iface->name), iface->namespace, 0); - async_iface->attrs = map_attrs(iface->attrs, async_iface_attrs); + async_iface = type_interface_declare(strmake("Async%s", iface->name), iface->namespace); STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) { var_t *begin_func, *finish_func, *func = stmt->u.var, *arg; var_list_t *begin_args = NULL, *finish_args = NULL, *args; - args = func->type->details.function->args; + if (is_attr(func->attrs, ATTR_CALLAS)) continue; + + args = type_function_get_args(func->declspec.type); if (args) LIST_FOR_EACH_ENTRY(arg, args, var_t, entry) { if (is_attr(arg->attrs, ATTR_IN) || !is_attr(arg->attrs, ATTR_OUT)) - begin_args = append_var(begin_args, copy_var(arg, strdup(arg->name), arg_in_attrs)); + begin_args = append_var(begin_args, copy_var(arg, xstrdup(arg->name), arg_in_attrs)); if (is_attr(arg->attrs, ATTR_OUT)) - finish_args = append_var(finish_args, copy_var(arg, strdup(arg->name), arg_out_attrs)); + finish_args = append_var(finish_args, copy_var(arg, xstrdup(arg->name), arg_out_attrs)); } - begin_func = copy_var(func, concat_str("Begin_", func->name), NULL); - begin_func->type = type_new_function(begin_args); - begin_func->type->attrs = func->attrs; - begin_func->type->details.function->retval = func->type->details.function->retval; + begin_func = copy_var(func, strmake("Begin_%s", func->name), NULL); + begin_func->declspec.type = type_new_function(begin_args); + begin_func->declspec.type->attrs = func->attrs; + begin_func->declspec.type->details.function->retval = func->declspec.type->details.function->retval; stmts = append_statement(stmts, make_statement_declaration(begin_func)); - finish_func = copy_var(func, concat_str("Finish_", func->name), NULL); - finish_func->type = type_new_function(finish_args); - finish_func->type->attrs = func->attrs; - finish_func->type->details.function->retval = func->type->details.function->retval; + finish_func = copy_var(func, strmake("Finish_%s", func->name), NULL); + finish_func->declspec.type = type_new_function(finish_args); + finish_func->declspec.type->attrs = func->attrs; + finish_func->declspec.type->details.function->retval = func->declspec.type->details.function->retval; stmts = append_statement(stmts, make_statement_declaration(finish_func)); } - type_interface_define(async_iface, inherit, stmts); + type_interface_define(async_iface, map_attrs(iface->attrs, async_iface_attrs), inherit, stmts, NULL, &iface->where); iface->details.iface->async_iface = async_iface->details.iface->async_iface = async_iface; } +static statement_list_t *append_parameterized_type_stmts(statement_list_t *stmts) +{ + statement_t *stmt, *next; + + if (stmts && parameterized_type_stmts) LIST_FOR_EACH_ENTRY_SAFE(stmt, next, parameterized_type_stmts, statement_t, entry) + { + switch(stmt->type) + { + case STMT_TYPE: + stmt->u.type = type_parameterized_type_specialize_define(stmt->u.type); + stmt->is_defined = 1; + list_remove(&stmt->entry); + stmts = append_statement(stmts, stmt); + break; + default: + assert(0); /* should not be there */ + break; + } + } + + return stmts; +} + static void check_statements(const statement_list_t *stmts, int is_inside_library) { const statement_t *stmt; @@ -2960,6 +2840,7 @@ static void check_statements(const statement_list_t *stmts, int is_inside_librar static void check_all_user_types(const statement_list_t *stmts) { const statement_t *stmt; + const var_t *v; if (stmts) LIST_FOR_EACH_ENTRY(stmt, stmts, const statement_t, entry) { @@ -2971,29 +2852,15 @@ static void check_all_user_types(const statement_list_t *stmts) const statement_t *stmt_func; STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(stmt->u.type)) { const var_t *func = stmt_func->u.var; - check_for_additional_prototype_types(func->type->details.function->args); + if (type_function_get_args(func->declspec.type)) + LIST_FOR_EACH_ENTRY( v, type_function_get_args(func->declspec.type), const var_t, entry ) + check_for_additional_prototype_types(v->declspec.type); + check_for_additional_prototype_types(type_function_get_rettype(func->declspec.type)); } } } } -int is_valid_uuid(const char *s) -{ - int i; - - for (i = 0; i < 36; ++i) - if (i == 8 || i == 13 || i == 18 || i == 23) - { - if (s[i] != '-') - return FALSE; - } - else - if (!isxdigit(s[i])) - return FALSE; - - return s[i] == '\0'; -} - static statement_t *make_statement(enum statement_type type) { statement_t *stmt = xmalloc(sizeof(*stmt)); @@ -3005,6 +2872,7 @@ static statement_t *make_statement_type_decl(type_t *type) { statement_t *stmt = make_statement(STMT_TYPE); stmt->u.type = type; + stmt->is_defined = type->defined && !type->defined_in_import; return stmt; } @@ -3019,16 +2887,16 @@ static statement_t *make_statement_declaration(var_t *var) { statement_t *stmt = make_statement(STMT_DECLARATION); stmt->u.var = var; - if (var->stgclass == STG_EXTERN && var->eval) + if (var->declspec.stgclass == STG_EXTERN && var->eval) warning("'%s' initialised and declared extern\n", var->name); if (is_const_decl(var)) { if (var->eval) reg_const(var); } - else if (type_get_type(var->type) == TYPE_FUNCTION) + else if (type_get_type(var->declspec.type) == TYPE_FUNCTION) check_function_attrs(var->name, var->attrs); - else if (var->stgclass == STG_NONE || var->stgclass == STG_REGISTER) + else if (var->declspec.stgclass == STG_NONE || var->declspec.stgclass == STG_REGISTER) error_loc("instantiation of data is illegal\n"); return stmt; } @@ -3075,27 +2943,22 @@ static statement_t *make_statement_module(type_t *type) return stmt; } -static statement_t *make_statement_typedef(declarator_list_t *decls) +static statement_t *make_statement_typedef(declarator_list_t *decls, bool is_defined) { declarator_t *decl, *next; statement_t *stmt; - type_list_t **type_list; if (!decls) return NULL; stmt = make_statement(STMT_TYPEDEF); stmt->u.type_list = NULL; - type_list = &stmt->u.type_list; + stmt->is_defined = is_defined; LIST_FOR_EACH_ENTRY_SAFE( decl, next, decls, declarator_t, entry ) { var_t *var = decl->var; - type_t *type = find_type_or_error(var->name, 0); - *type_list = xmalloc(sizeof(type_list_t)); - (*type_list)->type = type; - (*type_list)->next = NULL; - - type_list = &(*type_list)->next; + type_t *type = find_type_or_error(current_namespace, var->name); + stmt->u.type_list = append_typeref(stmt->u.type_list, make_typeref(type)); free(decl); free(var); } @@ -3103,15 +2966,22 @@ static statement_t *make_statement_typedef(declarator_list_t *decls) return stmt; } -static statement_list_t *append_statements(statement_list_t *l1, statement_list_t *l2) +static statement_t *make_statement_parameterized_type(type_t *type, typeref_list_t *params) { - if (!l2) return l1; - if (!l1 || l1 == l2) return l2; - list_move_tail (l1, l2); - return l1; + statement_t *stmt = make_statement(STMT_TYPE); + stmt->u.type = type_parameterized_type_specialize_partial(type, params); + return stmt; } -static attr_list_t *append_attribs(attr_list_t *l1, attr_list_t *l2) +static statement_t *make_statement_delegate(type_t *ret, var_list_t *args) +{ + declarator_t *decl = make_declarator(make_var(xstrdup("Invoke"))); + decl_spec_t *spec = make_decl_spec(ret, NULL, NULL, STG_NONE, 0, 0); + append_chain_type(decl, type_new_function(args), 0); + return make_statement_declaration(declare_var(NULL, spec, decl, FALSE)); +} + +static statement_list_t *append_statements(statement_list_t *l1, statement_list_t *l2) { if (!l2) return l1; if (!l1 || l1 == l2) return l2; @@ -3131,16 +3001,20 @@ static statement_list_t *append_statement(statement_list_t *list, statement_t *s return list; } -void init_loc_info(loc_info_t *i) +type_t *find_parameterized_type(type_t *type, typeref_list_t *params) { - i->input_name = input_name ? input_name : "stdin"; - i->line_number = line_number; - i->near_text = parser_text; -} + char *name = format_parameterized_type_name(type, params); -static void check_def(const type_t *t) -{ - if (t->defined) - error_loc("%s: redefinition error; original definition was at %s:%d\n", - t->name, t->loc_info.input_name, t->loc_info.line_number); + if (parameters_namespace) + { + assert(type->type_type == TYPE_PARAMETERIZED_TYPE); + type = type_parameterized_type_specialize_partial(type, params); + } + else if ((type = find_type(name, type->namespace, 0))) + assert(type->type_type != TYPE_PARAMETERIZED_TYPE); + else + error_loc("parameterized type '%s' not declared\n", name); + + free(name); + return type; } diff --git a/sdk/tools/widl/proxy.c b/sdk/tools/widl/proxy.c index eefd6216881..1a75cf0aaaf 100644 --- a/sdk/tools/widl/proxy.c +++ b/sdk/tools/widl/proxy.c @@ -20,13 +20,9 @@ */ #include "config.h" -#include "wine/port.h" #include #include -#ifdef HAVE_UNISTD_H -# include -#endif #include #include @@ -65,9 +61,9 @@ static void write_stubdesc(int expr_eval_routines) print_proxy( "{0}, 0, 0, %s, 0,\n", expr_eval_routines ? "ExprEvalRoutines" : "0"); print_proxy( "__MIDL_TypeFormatString.Format,\n"); print_proxy( "1, /* -error bounds_check flag */\n"); - print_proxy( "0x%x, /* Ndr library version */\n", get_stub_mode() == MODE_Oif ? 0x50002 : 0x10001); + print_proxy( "0x%x, /* Ndr library version */\n", interpreted_mode ? 0x50002 : 0x10001); print_proxy( "0,\n"); - print_proxy( "0x50100a4, /* MIDL Version 5.1.164 */\n"); + print_proxy( "0x50200ca, /* MIDL Version 5.2.202 */\n"); print_proxy( "0,\n"); print_proxy("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines"); print_proxy( "0, /* notify & notify_flag routine table */\n"); @@ -87,19 +83,17 @@ static void init_proxy(const statement_list_t *stmts) error("Could not open %s for output\n", proxy_name); print_proxy( "/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n", PACKAGE_VERSION, input_name); print_proxy( "\n"); +#ifdef __REACTOS__ print_proxy( "#define __midl_proxy\n\n"); - print_proxy( "#ifdef __REACTOS__\n"); print_proxy( "#define WIN32_NO_STATUS\n"); print_proxy( "#define WIN32_LEAN_AND_MEAN\n"); print_proxy( "#endif\n\n"); - +#else + print_proxy( "#define __midl_proxy\n"); +#endif print_proxy( "#include \"objbase.h\"\n"); print_proxy( "\n"); - print_proxy( "#ifndef DECLSPEC_HIDDEN\n"); - print_proxy( "#define DECLSPEC_HIDDEN\n"); - print_proxy( "#endif\n"); - print_proxy( "\n"); } static void clear_output_vars( const var_list_t *args ) @@ -111,15 +105,15 @@ static void clear_output_vars( const var_list_t *args ) { if (is_attr(arg->attrs, ATTR_IN)) continue; if (!is_attr(arg->attrs, ATTR_OUT)) continue; - if (is_ptr(arg->type)) + if (is_ptr(arg->declspec.type)) { - if (type_get_type(type_pointer_get_ref(arg->type)) == TYPE_BASIC) continue; - if (type_get_type(type_pointer_get_ref(arg->type)) == TYPE_ENUM) continue; + if (type_get_type(type_pointer_get_ref_type(arg->declspec.type)) == TYPE_BASIC) continue; + if (type_get_type(type_pointer_get_ref_type(arg->declspec.type)) == TYPE_ENUM) continue; } print_proxy( "if (%s) MIDL_memset( %s, 0, ", arg->name, arg->name ); - if (is_array(arg->type) && type_array_has_conformance(arg->type)) + if (is_array(arg->declspec.type) && type_array_has_conformance(arg->declspec.type)) { - write_expr( proxy, type_array_get_conformance(arg->type), 1, 1, NULL, NULL, "" ); + write_expr( proxy, type_array_get_conformance(arg->declspec.type), 1, 1, NULL, NULL, "" ); fprintf( proxy, " * " ); } fprintf( proxy, "sizeof( *%s ));\n", arg->name ); @@ -153,7 +147,7 @@ static int need_delegation_indirect(const type_t *iface) static void free_variable( const var_t *arg, const char *local_var_prefix ) { unsigned int type_offset = arg->typestring_offset; - type_t *type = arg->type; + type_t *type = arg->declspec.type; write_parameter_conf_or_var_exprs(proxy, indent, local_var_prefix, PHASE_FREE, arg, FALSE); @@ -197,20 +191,20 @@ static void proxy_free_variables( var_list_t *args, const char *local_var_prefix static void gen_proxy(type_t *iface, const var_t *func, int idx, unsigned int proc_offset) { - var_t *retval = type_function_get_retval(func->type); - int has_ret = !is_void(retval->type); + var_t *retval = type_function_get_retval(func->declspec.type); + int has_ret = !is_void(retval->declspec.type); int has_full_pointer = is_full_pointer_function(func); - const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV); - const var_list_t *args = type_get_function_args(func->type); + const char *callconv = get_attrp(func->declspec.type->attrs, ATTR_CALLCONV); + const var_list_t *args = type_function_get_args(func->declspec.type); if (!callconv) callconv = "STDMETHODCALLTYPE"; indent = 0; if (is_interpreted_func( iface, func )) { - if (get_stub_mode() == MODE_Oif && !is_callas( func->attrs )) return; - write_type_decl_left(proxy, retval->type); + if (!is_callas( func->attrs )) return; + write_type_decl_left(proxy, &retval->declspec); print_proxy( " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(func)); - write_args(proxy, args, iface->name, 1, TRUE); + write_args(proxy, args, iface->name, 1, TRUE, NAME_DEFAULT); print_proxy( ")\n"); write_client_call_routine( proxy, iface, func, "Object", proc_offset ); return; @@ -225,9 +219,9 @@ static void gen_proxy(type_t *iface, const var_t *func, int idx, print_proxy( "}\n"); print_proxy( "\n"); - write_type_decl_left(proxy, retval->type); + write_type_decl_left(proxy, &retval->declspec); print_proxy( " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(func)); - write_args(proxy, args, iface->name, 1, TRUE); + write_args(proxy, args, iface->name, 1, TRUE, NAME_DEFAULT); print_proxy( ")\n"); print_proxy( "{\n"); indent ++; @@ -235,12 +229,12 @@ static void gen_proxy(type_t *iface, const var_t *func, int idx, /* local variables */ if (has_ret) { print_proxy( "%s", "" ); - write_type_decl(proxy, retval->type, retval->name); + write_type_decl(proxy, &retval->declspec, retval->name); fprintf( proxy, ";\n" ); } print_proxy( "RPC_MESSAGE _RpcMessage;\n" ); if (has_ret) { - if (decl_indirect(retval->type)) + if (decl_indirect(retval->declspec.type)) print_proxy("void *_p_%s = &%s;\n", retval->name, retval->name); } print_proxy( "\n"); @@ -252,7 +246,7 @@ static void gen_proxy(type_t *iface, const var_t *func, int idx, write_full_pointer_init(proxy, indent, func, FALSE); /* FIXME: trace */ - clear_output_vars( type_get_function_args(func->type) ); + clear_output_vars( type_function_get_args(func->declspec.type) ); print_proxy( "RpcTryExcept\n" ); print_proxy( "{\n" ); @@ -285,9 +279,9 @@ static void gen_proxy(type_t *iface, const var_t *func, int idx, if (has_ret) { - if (decl_indirect(retval->type)) + if (decl_indirect(retval->declspec.type)) print_proxy("MIDL_memset(&%s, 0, sizeof(%s));\n", retval->name, retval->name); - else if (is_ptr(retval->type) || is_array(retval->type)) + else if (is_ptr(retval->declspec.type) || is_array(retval->declspec.type)) print_proxy("%s = 0;\n", retval->name); write_remoting_arguments(proxy, indent, func, "", PASS_RETURN, PHASE_UNMARSHAL); } @@ -307,7 +301,8 @@ static void gen_proxy(type_t *iface, const var_t *func, int idx, print_proxy( "{\n" ); if (has_ret) { indent++; - proxy_free_variables( type_get_function_args(func->type), "" ); + proxy_free_variables( type_function_get_args(func->declspec.type), "" ); + print_proxy( "/* coverity[uninit_use_in_call:SUPPRESS] */\n" ); print_proxy( "_RetVal = NdrProxyErrorHandler(RpcExceptionCode());\n" ); indent--; } @@ -326,7 +321,7 @@ static void gen_stub(type_t *iface, const var_t *func, const char *cas, unsigned int proc_offset) { const var_t *arg; - int has_ret = !is_void(type_function_get_rettype(func->type)); + int has_ret = !is_void(type_function_get_rettype(func->declspec.type)); int has_full_pointer = is_full_pointer_function(func); if (is_interpreted_func( iface, func )) return; @@ -395,10 +390,10 @@ static void gen_stub(type_t *iface, const var_t *func, const char *cas, else fprintf(proxy, "__frame->_This->lpVtbl->%s", get_name(func)); fprintf(proxy, "(__frame->_This"); - if (type_get_function_args(func->type)) + if (type_function_get_args(func->declspec.type)) { - LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry ) - fprintf(proxy, ", %s__frame->%s", is_array(arg->type) && !type_array_is_decl_as_ptr(arg->type) ? "*" :"" , arg->name); + LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), const var_t, entry ) + fprintf(proxy, ", %s__frame->%s", is_array(arg->declspec.type) && !type_array_is_decl_as_ptr(arg->declspec.type) ? "*" :"" , arg->name); } fprintf(proxy, ");\n"); fprintf(proxy, "\n"); @@ -407,7 +402,7 @@ static void gen_stub(type_t *iface, const var_t *func, const char *cas, write_remoting_arguments(proxy, indent, func, "__frame->", PASS_OUT, PHASE_BUFFERSIZE); - if (!is_void(type_function_get_rettype(func->type))) + if (!is_void(type_function_get_rettype(func->declspec.type))) write_remoting_arguments(proxy, indent, func, "__frame->", PASS_RETURN, PHASE_BUFFERSIZE); print_proxy("NdrStubGetBuffer(This, _pRpcChannelBuffer, &__frame->_StubMsg);\n"); @@ -416,7 +411,7 @@ static void gen_stub(type_t *iface, const var_t *func, const char *cas, fprintf(proxy, "\n"); /* marshall the return value */ - if (!is_void(type_function_get_rettype(func->type))) + if (!is_void(type_function_get_rettype(func->declspec.type))) write_remoting_arguments(proxy, indent, func, "__frame->", PASS_RETURN, PHASE_MARSHAL); indent--; @@ -438,16 +433,16 @@ static void gen_stub(type_t *iface, const var_t *func, const char *cas, static void gen_stub_thunk( type_t *iface, const var_t *func, unsigned int proc_offset ) { - int has_ret = !is_void( type_function_get_rettype( func->type )); + int has_ret = !is_void( type_function_get_rettype( func->declspec.type )); const var_t *arg, *callas = is_callas( func->attrs ); - const var_list_t *args = type_get_function_args( func->type ); + const var_list_t *args = type_function_get_args( func->declspec.type ); indent = 0; print_proxy( "void __RPC_API %s_%s_Thunk( PMIDL_STUB_MESSAGE pStubMsg )\n", iface->name, get_name(func) ); print_proxy( "{\n"); indent++; - write_func_param_struct( proxy, iface, func->type, + write_func_param_struct( proxy, iface, func->declspec.type, "*pParamStruct = (struct _PARAM_STRUCT *)pStubMsg->StackTop", has_ret ); print_proxy( "%s%s_%s_Stub( pParamStruct->This", has_ret ? "pParamStruct->_RetVal = " : "", iface->name, callas->name ); @@ -477,7 +472,7 @@ int count_methods(const type_t *iface) return count; } -static const statement_t * get_callas_source(const type_t * iface, const var_t * def) +const statement_t *get_callas_source(const type_t *iface, const var_t *def) { const statement_t * source; STATEMENTS_FOR_EACH_FUNC( source, type_iface_get_stmts(iface)) { @@ -577,7 +572,7 @@ static int write_stub_methods(type_t *iface, int skip) if (i) fprintf(proxy,",\n"); if (skip || missing) print_proxy("STUB_FORWARDING_FUNCTION"); else if (is_interpreted_func( iface, func )) - print_proxy( "(PRPC_STUB_FUNCTION)%s", get_stub_mode() == MODE_Oif ? "NdrStubCall2" : "NdrStubCall" ); + print_proxy( "(PRPC_STUB_FUNCTION)%s", interpreted_mode ? "NdrStubCall2" : "NdrStubCall" ); else print_proxy( "%s_%s_Stub", iface->name, fname); i++; } @@ -628,14 +623,14 @@ static void write_proxy(type_t *iface, unsigned int *proc_offset) if (!is_local(func->attrs)) { const var_t *cas = is_callas(func->attrs); const char *cname = cas ? cas->name : NULL; - int idx = func->type->details.function->idx; + int idx = func->func_idx; if (cname) { const statement_t *stmt2; STATEMENTS_FOR_EACH_FUNC(stmt2, type_iface_get_stmts(iface)) { const var_t *m = stmt2->u.var; if (!strcmp(m->name, cname)) { - idx = m->type->details.function->idx; + idx = m->func_idx; break; } } @@ -669,7 +664,7 @@ static void write_proxy(type_t *iface, unsigned int *proc_offset) print_proxy( "};\n\n" ); /* proxy info */ - if (get_stub_mode() == MODE_Oif) + if (interpreted_mode) { print_proxy( "static const MIDL_STUBLESS_PROXY_INFO %s_ProxyInfo =\n", iface->name ); print_proxy( "{\n" ); @@ -686,13 +681,13 @@ static void write_proxy(type_t *iface, unsigned int *proc_offset) /* proxy vtable */ print_proxy( "static %sCINTERFACE_PROXY_VTABLE(%d) _%sProxyVtbl =\n", - (get_stub_mode() != MODE_Os || need_delegation_indirect(iface)) ? "" : "const ", + (interpreted_mode || need_delegation_indirect(iface)) ? "" : "const ", count, iface->name); print_proxy( "{\n"); indent++; print_proxy( "{\n"); indent++; - if (get_stub_mode() == MODE_Oif) print_proxy( "&%s_ProxyInfo,\n", iface->name ); + if (interpreted_mode) print_proxy( "&%s_ProxyInfo,\n", iface->name ); print_proxy( "&IID_%s,\n", iface->name); indent--; print_proxy( "},\n"); @@ -767,7 +762,7 @@ static void write_proxy(type_t *iface, unsigned int *proc_offset) print_proxy( "{\n"); indent++; print_proxy( "%s_%s\n", - iface->details.iface->async_iface == iface ? "CStdAsyncStubBuffer" : "CStdStubBuffer", + type_iface_get_async_iface(iface) == iface ? "CStdAsyncStubBuffer" : "CStdStubBuffer", need_delegation_indirect(iface) ? "DELEGATING_METHODS" : "METHODS"); indent--; print_proxy( "}\n"); @@ -820,7 +815,7 @@ int need_inline_stubs(const type_t *iface) { const statement_t *stmt; - if (get_stub_mode() == MODE_Os) return 1; + if (!interpreted_mode) return 1; STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) { @@ -836,7 +831,7 @@ static int need_proxy_and_inline_stubs(const type_t *iface) const statement_t *stmt; if (!need_proxy( iface )) return 0; - if (get_stub_mode() == MODE_Os) return 1; + if (!interpreted_mode) return 1; STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) { @@ -868,8 +863,8 @@ static void write_proxy_stmts(const statement_list_t *stmts, unsigned int *proc_ if (need_proxy(iface)) { write_proxy(iface, proc_offset); - if (iface->details.iface->async_iface) - write_proxy(iface->details.iface->async_iface, proc_offset); + if (type_iface_get_async_iface(iface)) + write_proxy(type_iface_get_async_iface(iface), proc_offset); } } } @@ -879,9 +874,9 @@ static int cmp_iid( const void *ptr1, const void *ptr2 ) { const type_t * const *iface1 = ptr1; const type_t * const *iface2 = ptr2; - const UUID *uuid1 = get_attrp( (*iface1)->attrs, ATTR_UUID ); - const UUID *uuid2 = get_attrp( (*iface2)->attrs, ATTR_UUID ); - return memcmp( uuid1, uuid2, sizeof(UUID) ); + const struct uuid *uuid1 = get_attrp( (*iface1)->attrs, ATTR_UUID ); + const struct uuid *uuid2 = get_attrp( (*iface2)->attrs, ATTR_UUID ); + return memcmp( uuid1, uuid2, sizeof(*uuid1) ); } static void build_iface_list( const statement_list_t *stmts, type_t **ifaces[], int *count ) @@ -898,9 +893,9 @@ static void build_iface_list( const statement_list_t *stmts, type_t **ifaces[], { *ifaces = xrealloc( *ifaces, (*count + 1) * sizeof(**ifaces) ); (*ifaces)[(*count)++] = iface; - if (iface->details.iface->async_iface) + if (type_iface_get_async_iface(iface)) { - iface = iface->details.iface->async_iface; + iface = type_iface_get_async_iface(iface); *ifaces = xrealloc( *ifaces, (*count + 1) * sizeof(**ifaces) ); (*ifaces)[(*count)++] = iface; } @@ -930,10 +925,10 @@ static void write_proxy_routines(const statement_list_t *stmts) const type_t * delegate_to; print_proxy( "#ifndef __REDQ_RPCPROXY_H_VERSION__\n"); - print_proxy( "#define __REQUIRED_RPCPROXY_H_VERSION__ %u\n", get_stub_mode() == MODE_Oif ? 475 : 440); + print_proxy( "#define __REQUIRED_RPCPROXY_H_VERSION__ %u\n", interpreted_mode ? 475 : 440); print_proxy( "#endif\n"); print_proxy( "\n"); - if (get_stub_mode() == MODE_Oif) print_proxy( "#define USE_STUBLESS_PROXY\n"); + if (interpreted_mode) print_proxy( "#define USE_STUBLESS_PROXY\n"); print_proxy( "#include \"rpcproxy.h\"\n"); print_proxy( "#ifndef __RPCPROXY_H_VERSION__\n"); print_proxy( "#error This code needs a newer version of rpcproxy.h\n"); @@ -1037,10 +1032,10 @@ static void write_proxy_routines(const statement_list_t *stmts) fprintf(proxy, "}\n"); fprintf(proxy, "\n"); - table_version = get_stub_mode() == MODE_Oif ? 2 : 1; + table_version = interpreted_mode ? 2 : 1; for (i = 0; i < count; i++) { - if (interfaces[i]->details.iface->async_iface != interfaces[i]) continue; + if (type_iface_get_async_iface(interfaces[i]) != interfaces[i]) continue; if (table_version != 6) { fprintf(proxy, "static const IID *_AsyncInterfaceTable[] =\n"); @@ -1057,7 +1052,7 @@ static void write_proxy_routines(const statement_list_t *stmts) fprintf(proxy, "\n"); } - fprintf(proxy, "const ExtendedProxyFileInfo %s_ProxyFileInfo DECLSPEC_HIDDEN =\n", file_id); + fprintf(proxy, "const ExtendedProxyFileInfo %s_ProxyFileInfo =\n", file_id); fprintf(proxy, "{\n"); fprintf(proxy, " (const PCInterfaceProxyVtblList*)_%s_ProxyVtblList,\n", file_id); fprintf(proxy, " (const PCInterfaceStubVtblList*)_%s_StubVtblList,\n", file_id); diff --git a/sdk/tools/widl/register.c b/sdk/tools/widl/register.c index 718d444cc7a..c5600c9e7ea 100644 --- a/sdk/tools/widl/register.c +++ b/sdk/tools/widl/register.c @@ -19,13 +19,9 @@ */ #include "config.h" -#include "wine/port.h" #include #include -#ifdef HAVE_UNISTD_H -# include -#endif #include #include @@ -38,13 +34,14 @@ static int indent; -static const char *format_uuid( const UUID *uuid ) +static const char *format_uuid( const struct uuid *uuid ) { static char buffer[40]; - sprintf( buffer, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", - uuid->Data1, uuid->Data2, uuid->Data3, - uuid->Data4[0], uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], - uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], uuid->Data4[7] ); + snprintf( buffer, sizeof(buffer), + "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", + uuid->Data1, uuid->Data2, uuid->Data3, + uuid->Data4[0], uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], + uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], uuid->Data4[7] ); return buffer; } @@ -80,8 +77,8 @@ static const type_t *find_ps_factory( const statement_list_t *stmts ) static void write_interface( const type_t *iface, const type_t *ps_factory ) { - const UUID *uuid = get_attrp( iface->attrs, ATTR_UUID ); - const UUID *ps_uuid = get_attrp( ps_factory->attrs, ATTR_UUID ); + const struct uuid *uuid = get_attrp( iface->attrs, ATTR_UUID ); + const struct uuid *ps_uuid = get_attrp( ps_factory->attrs, ATTR_UUID ); if (!uuid) return; if (!is_object( iface )) return; @@ -113,14 +110,12 @@ static void write_interfaces( const statement_list_t *stmts, const type_t *ps_fa static void write_typelib_interface( const type_t *iface, const typelib_t *typelib ) { - const UUID *typelib_uuid = get_attrp( typelib->attrs, ATTR_UUID ); - const UUID *uuid = get_attrp( iface->attrs, ATTR_UUID ); + const struct uuid *typelib_uuid = get_attrp( typelib->attrs, ATTR_UUID ); + const struct uuid *uuid = get_attrp( iface->attrs, ATTR_UUID ); unsigned int version = get_attrv( typelib->attrs, ATTR_VERSION ); if (!uuid) return; if (!is_object( iface )) return; - if (!is_attr( iface->attrs, ATTR_OLEAUTOMATION ) && !is_attr( iface->attrs, ATTR_DISPINTERFACE )) - return; put_str( indent, "'%s' = s '%s'\n", format_uuid( uuid ), iface->name ); put_str( indent, "{\n" ); indent++; @@ -137,18 +132,15 @@ static void write_typelib_interface( const type_t *iface, const typelib_t *typel static void write_typelib_interfaces( const typelib_t *typelib ) { - const statement_t *stmt; + unsigned int i; - if (typelib->stmts) LIST_FOR_EACH_ENTRY( stmt, typelib->stmts, const statement_t, entry ) - { - if (stmt->type == STMT_TYPE && type_get_type( stmt->u.type ) == TYPE_INTERFACE) - write_typelib_interface( stmt->u.type, typelib ); - } + for (i = 0; i < typelib->reg_iface_count; ++i) + write_typelib_interface( typelib->reg_ifaces[i], typelib ); } static int write_coclass( const type_t *class, const typelib_t *typelib ) { - const UUID *uuid = get_attrp( class->attrs, ATTR_UUID ); + const struct uuid *uuid = get_attrp( class->attrs, ATTR_UUID ); const char *descr = get_attrp( class->attrs, ATTR_HELPSTRING ); const char *progid = get_attrp( class->attrs, ATTR_PROGID ); const char *vi_progid = get_attrp( class->attrs, ATTR_VIPROGID ); @@ -166,7 +158,7 @@ static int write_coclass( const type_t *class, const typelib_t *typelib ) if (progid) put_str( indent, "ProgId = s '%s'\n", progid ); if (typelib) { - const UUID *typelib_uuid = get_attrp( typelib->attrs, ATTR_UUID ); + const struct uuid *typelib_uuid = get_attrp( typelib->attrs, ATTR_UUID ); put_str( indent, "TypeLib = s '%s'\n", format_uuid( typelib_uuid )); if (!version) version = get_attrv( typelib->attrs, ATTR_VERSION ); } @@ -190,9 +182,26 @@ static void write_coclasses( const statement_list_t *stmts, const typelib_t *typ } } +static void write_runtimeclasses_registry( const statement_list_t *stmts ) +{ + const statement_t *stmt; + const type_t *type; + + if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry ) + { + if (stmt->type != STMT_TYPE) continue; + if (type_get_type((type = stmt->u.type)) != TYPE_RUNTIMECLASS) continue; + if (!get_attrp(type->attrs, ATTR_ACTIVATABLE) && !get_attrp(type->attrs, ATTR_STATIC)) continue; + put_str( indent, "ForceRemove %s\n", format_namespace( type->namespace, "", ".", type->name, NULL ) ); + put_str( indent++, "{\n" ); + put_str( indent, "val 'DllPath' = s '%%MODULE%%'\n" ); + put_str( --indent, "}\n" ); + } +} + static int write_progid( const type_t *class ) { - const UUID *uuid = get_attrp( class->attrs, ATTR_UUID ); + const struct uuid *uuid = get_attrp( class->attrs, ATTR_UUID ); const char *descr = get_attrp( class->attrs, ATTR_HELPSTRING ); const char *progid = get_attrp( class->attrs, ATTR_PROGID ); const char *vi_progid = get_attrp( class->attrs, ATTR_VIPROGID ); @@ -241,22 +250,47 @@ void write_regscript( const statement_list_t *stmts ) init_output_buffer(); - put_str( indent, "HKCR\n" ); - put_str( indent++, "{\n" ); + if (winrt_mode) + { + put_str( indent, "HKLM\n" ); + put_str( indent++, "{\n" ); + put_str( indent, "NoRemove Software\n" ); + put_str( indent++, "{\n" ); + put_str( indent, "NoRemove Microsoft\n" ); + put_str( indent++, "{\n" ); + put_str( indent, "NoRemove WindowsRuntime\n" ); + put_str( indent++, "{\n" ); + put_str( indent, "NoRemove ActivatableClassId\n" ); + put_str( indent++, "{\n" ); + write_runtimeclasses_registry( stmts ); + put_str( --indent, "}\n" ); + put_str( --indent, "}\n" ); + put_str( --indent, "}\n" ); + put_str( --indent, "}\n" ); + put_str( --indent, "}\n" ); + } + else + { + put_str( indent, "HKCR\n" ); + put_str( indent++, "{\n" ); - put_str( indent, "NoRemove Interface\n" ); - put_str( indent++, "{\n" ); - ps_factory = find_ps_factory( stmts ); - if (ps_factory) write_interfaces( stmts, ps_factory ); - put_str( --indent, "}\n" ); + ps_factory = find_ps_factory( stmts ); + if (ps_factory) + { + put_str( indent, "NoRemove Interface\n" ); + put_str( indent++, "{\n" ); + write_interfaces( stmts, ps_factory ); + put_str( --indent, "}\n" ); + } - put_str( indent, "NoRemove CLSID\n" ); - put_str( indent++, "{\n" ); - write_coclasses( stmts, NULL ); - put_str( --indent, "}\n" ); + put_str( indent, "NoRemove CLSID\n" ); + put_str( indent++, "{\n" ); + write_coclasses( stmts, NULL ); + put_str( --indent, "}\n" ); - write_progids( stmts ); - put_str( --indent, "}\n" ); + write_progids( stmts ); + put_str( --indent, "}\n" ); + } if (strendswith( regscript_name, ".res" )) /* create a binary resource file */ { @@ -286,7 +320,12 @@ void write_typelib_regscript( const statement_list_t *stmts ) if (count && !strendswith( typelib_name, ".res" )) error( "Cannot store multiple typelibs into %s\n", typelib_name ); else - create_msft_typelib( stmt->u.lib ); + { + if (old_typelib) + create_sltg_typelib( stmt->u.lib ); + else + create_msft_typelib( stmt->u.lib ); + } count++; } if (count && strendswith( typelib_name, ".res" )) flush_output_resources( typelib_name ); @@ -294,7 +333,7 @@ void write_typelib_regscript( const statement_list_t *stmts ) void output_typelib_regscript( const typelib_t *typelib ) { - const UUID *typelib_uuid = get_attrp( typelib->attrs, ATTR_UUID ); + const struct uuid *typelib_uuid = get_attrp( typelib->attrs, ATTR_UUID ); const char *descr = get_attrp( typelib->attrs, ATTR_HELPSTRING ); const expr_t *lcid_expr = get_attrp( typelib->attrs, ATTR_LIBLCID ); unsigned int version = get_attrv( typelib->attrs, ATTR_VERSION ); @@ -320,11 +359,8 @@ void output_typelib_regscript( const typelib_t *typelib ) expr = get_attrp( typelib->attrs, ATTR_ID ); if (expr) { - sprintf(id_part, "\\%d", expr->cval); -#ifndef __REACTOS__ - resname = xmalloc( strlen(typelib_name) + 20 ); - sprintf(resname, "%s\\%d", typelib_name, expr->cval); -#endif + snprintf(id_part, sizeof(id_part), "\\%d", expr->cval); + resname = strmake("%s\\%d", typelib_name, expr->cval); } put_str( indent, "'%x' { %s = s '%%MODULE%%%s' }\n", lcid_expr ? lcid_expr->cval : 0, pointer_size == 8 ? "win64" : "win32", id_part ); diff --git a/sdk/tools/widl/server.c b/sdk/tools/widl/server.c index d165bbb0490..8bc179f1438 100644 --- a/sdk/tools/widl/server.c +++ b/sdk/tools/widl/server.c @@ -19,13 +19,9 @@ */ #include "config.h" -#include "wine/port.h" #include #include -#ifdef HAVE_UNISTD_H -# include -#endif #include #include @@ -55,6 +51,7 @@ static void write_function_stub(const type_t *iface, const var_t *func, unsigned unsigned char explicit_fc, implicit_fc; int has_full_pointer = is_full_pointer_function(func); const var_t *handle_var = get_func_handle_var( iface, func, &explicit_fc, &implicit_fc ); + type_t *ret_type = type_function_get_rettype(func->declspec.type); if (is_interpreted_func( iface, func )) return; @@ -72,10 +69,12 @@ static void write_function_stub(const type_t *iface, const var_t *func, unsigned print_server("static void __finally_%s_%s(", iface->name, get_name(func)); fprintf(server," struct __frame_%s_%s *__frame )\n{\n", iface->name, get_name(func)); + if (interpreted_mode) print_server("NdrCorrelationFree(&__frame->_StubMsg);\n"); + indent++; write_remoting_arguments(server, indent, func, "__frame->", PASS_OUT, PHASE_FREE); - if (!is_void(type_function_get_rettype(func->type))) + if (!is_void(ret_type)) write_remoting_arguments(server, indent, func, "__frame->", PASS_RETURN, PHASE_FREE); if (has_full_pointer) @@ -90,6 +89,7 @@ static void write_function_stub(const type_t *iface, const var_t *func, unsigned fprintf(server, "{\n"); indent++; print_server("struct __frame_%s_%s __f, * const __frame = &__f;\n", iface->name, get_name(func)); + if (interpreted_mode) print_server("ULONG _NdrCorrCache[256];\n"); if (has_out_arg_or_return(func)) print_server("RPC_STATUS _Status;\n"); fprintf(server, "\n"); @@ -116,11 +116,13 @@ static void write_function_stub(const type_t *iface, const var_t *func, unsigned print_server("RpcTryExcept\n"); print_server("{\n"); indent++; + if (interpreted_mode) + print_server("NdrCorrelationInitialize(&__frame->_StubMsg, _NdrCorrCache, sizeof(_NdrCorrCache), 0);\n" ); if (has_full_pointer) write_full_pointer_init(server, indent, func, TRUE); - if (type_get_function_args(func->type)) + if (type_function_get_args(func->declspec.type)) { print_server("if ((_pRpcMessage->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)\n"); indent++; @@ -154,35 +156,42 @@ static void write_function_stub(const type_t *iface, const var_t *func, unsigned assign_stub_out_args(server, indent, func, "__frame->"); /* Call the real server function */ - print_server("%s%s%s", - is_void(type_function_get_rettype(func->type)) ? "" : "__frame->_RetVal = ", - prefix_server, get_name(func)); + if (is_context_handle(ret_type)) + { + print_server("__frame->_RetVal = NDRSContextUnmarshall((char*)0, _pRpcMessage->DataRepresentation);\n"); + print_server("*(("); + write_type_decl(server, type_function_get_ret(func->declspec.type), NULL); + fprintf(server, "*)NDRSContextValue(__frame->_RetVal)) = "); + } + else + print_server("%s", is_void(ret_type) ? "" : "__frame->_RetVal = "); + fprintf(server, "%s%s", prefix_server, get_name(func)); - if (type_get_function_args(func->type)) + if (type_function_get_args(func->declspec.type)) { int first_arg = 1; fprintf(server, "(\n"); indent++; - LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) + LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry ) { if (first_arg) first_arg = 0; else fprintf(server, ",\n"); - if (is_context_handle(var->type)) + if (is_context_handle(var->declspec.type)) { /* if the context_handle attribute appears in the chain of types * without pointers being followed, then the context handle must * be direct, otherwise it is a pointer */ - const char *ch_ptr = is_aliaschain_attr(var->type, ATTR_CONTEXTHANDLE) ? "*" : ""; + const char *ch_ptr = is_aliaschain_attr(var->declspec.type, ATTR_CONTEXTHANDLE) ? "*" : ""; print_server("("); - write_type_decl_left(server, var->type); + write_type_decl_left(server, &var->declspec); fprintf(server, ")%sNDRSContextValue(__frame->%s)", ch_ptr, var->name); } else { - print_server("%s__frame->%s", is_array(var->type) && !type_array_is_decl_as_ptr(var->type) ? "*" : "", var->name); + print_server("%s__frame->%s", is_array(var->declspec.type) && !type_array_is_decl_as_ptr(var->declspec.type) ? "*" : "", var->name); } } fprintf(server, ");\n"); @@ -197,7 +206,7 @@ static void write_function_stub(const type_t *iface, const var_t *func, unsigned { write_remoting_arguments(server, indent, func, "__frame->", PASS_OUT, PHASE_BUFFERSIZE); - if (!is_void(type_function_get_rettype(func->type))) + if (!is_void(ret_type)) write_remoting_arguments(server, indent, func, "__frame->", PASS_RETURN, PHASE_BUFFERSIZE); print_server("_pRpcMessage->BufferLength = __frame->_StubMsg.BufferLength;\n"); @@ -216,7 +225,7 @@ static void write_function_stub(const type_t *iface, const var_t *func, unsigned write_remoting_arguments(server, indent, func, "__frame->", PASS_OUT, PHASE_MARSHAL); /* marshall the return value */ - if (!is_void(type_function_get_rettype(func->type))) + if (!is_void(ret_type)) write_remoting_arguments(server, indent, func, "__frame->", PASS_RETURN, PHASE_MARSHAL); indent--; @@ -269,7 +278,7 @@ static void write_dispatchtable(type_t *iface) { var_t *func = stmt->u.var; if (is_interpreted_func( iface, func )) - print_server("%s,\n", get_stub_mode() == MODE_Oif ? "NdrServerCall2" : "NdrServerCall"); + print_server("NdrServerCall2,\n"); else print_server("%s_%s,\n", iface->name, get_name(func)); method_count++; @@ -299,7 +308,7 @@ static void write_routinetable(type_t *iface) { var_t *func = stmt->u.var; if (is_local( func->attrs )) continue; - print_server( "(SERVER_ROUTINE)%s%s,\n", prefix_server, get_name(func)); + print_server( "(void *)%s%s,\n", prefix_server, get_name(func)); } indent--; print_server( "};\n\n" ); @@ -376,9 +385,9 @@ static void write_stubdescriptor(type_t *iface, int expr_eval_routines) print_server("0,\n"); print_server("__MIDL_TypeFormatString.Format,\n"); print_server("1, /* -error bounds_check flag */\n"); - print_server("0x%x, /* Ndr library version */\n", get_stub_mode() == MODE_Oif ? 0x50002 : 0x10001); + print_server("0x%x, /* Ndr library version */\n", interpreted_mode ? 0x50002 : 0x10001); print_server("0,\n"); - print_server("0x50100a4, /* MIDL Version 5.1.164 */\n"); + print_server("0x50200ca, /* MIDL Version 5.2.202 */\n"); print_server("0,\n"); print_server("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines"); print_server("0, /* notify & notify_flag routine table */\n"); @@ -395,7 +404,7 @@ static void write_stubdescriptor(type_t *iface, int expr_eval_routines) static void write_serverinterfacedecl(type_t *iface) { unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION); - UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); + struct uuid *uuid = get_attrp(iface->attrs, ATTR_UUID); const str_list_t *endpoints = get_attrp(iface->attrs, ATTR_ENDPOINT); if (endpoints) write_endpoints( server, iface->name, endpoints ); @@ -429,10 +438,10 @@ static void write_serverinterfacedecl(type_t *iface) indent--; print_server("};\n"); if (old_names) - print_server("RPC_IF_HANDLE %s_ServerIfHandle DECLSPEC_HIDDEN = (RPC_IF_HANDLE)& %s___RpcServerInterface;\n", + print_server("RPC_IF_HANDLE %s_ServerIfHandle = (RPC_IF_HANDLE)& %s___RpcServerInterface;\n", iface->name, iface->name); else - print_server("RPC_IF_HANDLE %s%s_v%d_%d_s_ifspec DECLSPEC_HIDDEN = (RPC_IF_HANDLE)& %s___RpcServerInterface;\n", + print_server("RPC_IF_HANDLE %s%s_v%d_%d_s_ifspec = (RPC_IF_HANDLE)& %s___RpcServerInterface;\n", prefix_server, iface->name, MAJORVERSION(ver), MINORVERSION(ver), iface->name); fprintf(server, "\n"); } @@ -449,10 +458,6 @@ static void init_server(void) print_server("#include \n"); fprintf(server, "\n"); print_server("#include \"%s\"\n", header_name); - print_server("\n"); - print_server( "#ifndef DECLSPEC_HIDDEN\n"); - print_server( "#define DECLSPEC_HIDDEN\n"); - print_server( "#endif\n"); print_server( "\n"); } diff --git a/sdk/tools/widl/typegen.c b/sdk/tools/widl/typegen.c index 2aeb6ebca44..c29bbba1c1c 100644 --- a/sdk/tools/widl/typegen.c +++ b/sdk/tools/widl/typegen.c @@ -20,13 +20,9 @@ */ #include "config.h" -#include "wine/port.h" #include #include -#ifdef HAVE_UNISTD_H -# include -#endif #include #include #include @@ -48,6 +44,7 @@ static const type_t *current_structure; static const var_t *current_func; +static const var_t *current_arg; static const type_t *current_iface; static struct list expr_eval_routines = LIST_INIT(expr_eval_routines); @@ -67,6 +64,7 @@ enum type_context TYPE_CONTEXT_PARAM, TYPE_CONTEXT_CONTAINER, TYPE_CONTEXT_CONTAINER_NO_POINTERS, + TYPE_CONTEXT_RETVAL, }; /* parameter flags in Oif mode */ @@ -82,20 +80,26 @@ static const unsigned short IsSimpleRef = 0x0100; /* static const unsigned short IsDontCallFreeInst = 0x0200; */ /* static const unsigned short SaveForAsyncFinish = 0x0400; */ +/* robust flags in correlation descriptors */ +static const unsigned short RobustEarly = 0x0001; +/* static const unsigned short RobustSplit = 0x0002; */ +static const unsigned short RobustIsIIdIs = 0x0004; +/* static const unsigned short RobustDontCheck = 0x0008; */ + static unsigned int field_memsize(const type_t *type, unsigned int *offset); static unsigned int fields_memsize(const var_list_t *fields, unsigned int *align); -static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type, +static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, int toplevel_attrs, type_t *type, const char *name, unsigned int *typestring_offset); -static unsigned int write_struct_tfs(FILE *file, type_t *type, const char *name, unsigned int *tfsoff); -static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type, - const char *name, int write_ptr, unsigned int *tfsoff); static const var_t *find_array_or_string_in_struct(const type_t *type); -static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs, +static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs, int toplevel_attrs, type_t *type, enum type_context context, const char *name, unsigned int *typestring_offset); +static unsigned int write_type_tfs(FILE *file, const attr_list_t *attrs, int toplevel_attrs, + type_t *type, const char *name, + enum type_context context, + unsigned int *typeformat_offset); static unsigned int get_required_buffer_size_type( const type_t *type, const char *name, - const attr_list_t *attrs, int toplevel_param, - unsigned int *alignment ); + const attr_list_t *attrs, int toplevel_attrs, int toplevel_param, unsigned int *alignment ); static unsigned int get_function_buffer_size( const var_t *func, enum pass pass ); static const char *string_of_type(unsigned char type) @@ -188,19 +192,6 @@ static const char *string_of_type(unsigned char type) } } -static void *get_aliaschain_attrp(const type_t *type, enum attr_type attr) -{ - const type_t *t = type; - for (;;) - { - if (is_attr(t->attrs, attr)) - return get_attrp(t->attrs, attr); - else if (type_is_alias(t)) - t = type_alias_get_aliasee(t); - else return NULL; - } -} - unsigned char get_basic_fc(const type_t *type) { int sign = type_basic_get_sign(type); @@ -250,23 +241,26 @@ static unsigned char get_basic_fc_signed(const type_t *type) static inline unsigned int clamp_align(unsigned int align) { - unsigned int packing = (pointer_size == 4) ? win32_packing : win64_packing; if(align > packing) align = packing; return align; } -unsigned char get_pointer_fc(const type_t *type, const attr_list_t *attrs, int toplevel_param) +static unsigned char get_pointer_fc(const type_t *type, const attr_list_t *attrs, + int toplevel_attrs, int toplevel_param) { const type_t *t; int pointer_type; assert(is_ptr(type) || is_array(type)); - pointer_type = get_attrv(attrs, ATTR_POINTERTYPE); - if (pointer_type) - return pointer_type; + if (toplevel_attrs) + { + pointer_type = get_attrv(attrs, ATTR_POINTERTYPE); + if (pointer_type) + return pointer_type; + } - for (t = type; type_is_alias(t); t = type_alias_get_aliasee(t)) + for (t = type; type_is_alias(t); t = type_alias_get_aliasee_type(t)) { pointer_type = get_attrv(t->attrs, ATTR_POINTERTYPE); if (pointer_type) @@ -275,19 +269,20 @@ unsigned char get_pointer_fc(const type_t *type, const attr_list_t *attrs, int t if (toplevel_param) return FC_RP; - else if (is_ptr(type)) - return type_pointer_get_default_fc(type); - else - return type_array_get_ptr_default_fc(type); + + if ((pointer_type = get_attrv(current_iface->attrs, ATTR_POINTERDEFAULT))) + return pointer_type; + + return FC_UP; } static unsigned char get_pointer_fc_context( const type_t *type, const attr_list_t *attrs, - enum type_context context ) + int toplevel_attrs, enum type_context context ) { - int pointer_fc = get_pointer_fc(type, attrs, context == TYPE_CONTEXT_TOPLEVELPARAM); + int pointer_fc = get_pointer_fc(type, attrs, toplevel_attrs, context == TYPE_CONTEXT_TOPLEVELPARAM); if (pointer_fc == FC_UP && is_attr( attrs, ATTR_OUT ) && - context == TYPE_CONTEXT_PARAM && is_object( current_iface )) + (context == TYPE_CONTEXT_PARAM || context == TYPE_CONTEXT_RETVAL) && is_object( current_iface )) pointer_fc = FC_OP; return pointer_fc; @@ -315,7 +310,7 @@ static type_t *get_user_type(const type_t *t, const char **pname) } if (type_is_alias(t)) - t = type_alias_get_aliasee(t); + t = type_alias_get_aliasee_type(t); else return NULL; } @@ -350,10 +345,12 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att return TGT_RANGE; return TGT_ENUM; case TYPE_POINTER: - if (type_get_type(type_pointer_get_ref(type)) == TYPE_INTERFACE || - (type_get_type(type_pointer_get_ref(type)) == TYPE_VOID && is_attr(attrs, ATTR_IIDIS))) + if (type_get_type(type_pointer_get_ref_type(type)) == TYPE_INTERFACE || + type_get_type(type_pointer_get_ref_type(type)) == TYPE_RUNTIMECLASS || + type_get_type(type_pointer_get_ref_type(type)) == TYPE_DELEGATE || + (type_get_type(type_pointer_get_ref_type(type)) == TYPE_VOID && is_attr(attrs, ATTR_IIDIS))) return TGT_IFACE_POINTER; - else if (is_aliaschain_attr(type_pointer_get_ref(type), ATTR_CONTEXTHANDLE)) + else if (is_aliaschain_attr(type_pointer_get_ref_type(type), ATTR_CONTEXTHANDLE)) return TGT_CTXT_HANDLE_POINTER; else return TGT_POINTER; @@ -371,6 +368,14 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att case TYPE_VOID: case TYPE_ALIAS: case TYPE_BITFIELD: + case TYPE_RUNTIMECLASS: + case TYPE_DELEGATE: + break; + case TYPE_APICONTRACT: + case TYPE_PARAMETERIZED_TYPE: + case TYPE_PARAMETER: + /* not supposed to be here */ + assert(0); break; } return TGT_INVALID; @@ -378,13 +383,13 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att static int cant_be_null(const var_t *v) { - switch (typegen_detect_type(v->type, v->attrs, TDT_IGNORE_STRINGS)) + switch (typegen_detect_type(v->declspec.type, v->attrs, TDT_IGNORE_STRINGS)) { case TGT_ARRAY: - if (!type_array_is_decl_as_ptr( v->type )) return 0; + if (!type_array_is_decl_as_ptr( v->declspec.type )) return 0; /* fall through */ case TGT_POINTER: - return (get_pointer_fc(v->type, v->attrs, TRUE) == FC_RP); + return (get_pointer_fc(v->declspec.type, v->attrs, TRUE, TRUE) == FC_RP); case TGT_CTXT_HANDLE_POINTER: return TRUE; default: @@ -404,7 +409,7 @@ static int get_padding(const var_list_t *fields) LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry) { - type_t *ft = f->type; + type_t *ft = f->declspec.type; unsigned int align = 0; unsigned int size = type_memsize_and_alignment(ft, &align); align = clamp_align(align); @@ -416,49 +421,86 @@ static int get_padding(const var_list_t *fields) return ROUNDING(offset, salign); } -static unsigned int get_stack_size( const var_t *var, int *by_value ) +static unsigned int get_stack_size( const var_t *var, unsigned int *stack_align, int *by_value ) { - unsigned int stack_size; - int by_val; + unsigned int stack_size, align = 0; + int by_val = 0; - switch (typegen_detect_type( var->type, var->attrs, TDT_ALL_TYPES )) + switch (typegen_detect_type( var->declspec.type, var->attrs, TDT_ALL_TYPES )) { case TGT_BASIC: + if (target.cpu == CPU_ARM) + { + switch (type_basic_get_type( var->declspec.type )) + { + case TYPE_BASIC_FLOAT: + case TYPE_BASIC_DOUBLE: + case TYPE_BASIC_INT64: + case TYPE_BASIC_HYPER: + align = 8; + break; + default: + break; + } + } + /* fall through */ case TGT_ENUM: case TGT_RANGE: case TGT_STRUCT: case TGT_UNION: case TGT_USER_TYPE: - stack_size = type_memsize( var->type ); - by_val = (pointer_size < 8 || stack_size <= pointer_size); /* FIXME: should be platform-specific */ + stack_size = type_memsize_and_alignment( var->declspec.type, &align ); + switch (target.cpu) + { + case CPU_x86_64: + case CPU_ARM64EC: + by_val = (stack_size == 1 || stack_size == 2 || stack_size == 4 || stack_size == 8); + break; + case CPU_ARM64: + by_val = (stack_size <= 2 * pointer_size); + break; + case CPU_ARM: + by_val = 1; + break; + case CPU_i386: + align = pointer_size; + by_val = 1; + break; + } break; default: - by_val = 0; break; } - if (!by_val) stack_size = pointer_size; + if (align < pointer_size) align = pointer_size; + if (!by_val) stack_size = align = pointer_size; + if (by_value) *by_value = by_val; - return ROUND_SIZE( stack_size, pointer_size ); + if (stack_align) *stack_align = align; + return ROUND_SIZE( stack_size, align ); } static unsigned char get_contexthandle_flags( const type_t *iface, const attr_list_t *attrs, - const type_t *type ) + const type_t *type, int is_return ) { unsigned char flags = 0; + int is_out; if (is_attr(iface->attrs, ATTR_STRICTCONTEXTHANDLE)) flags |= NDR_STRICT_CONTEXT_HANDLE; if (is_ptr(type) && !is_attr( type->attrs, ATTR_CONTEXTHANDLE ) && !is_attr( attrs, ATTR_CONTEXTHANDLE )) - flags |= 0x80; + flags |= HANDLE_PARAM_IS_VIA_PTR; - if (is_attr(attrs, ATTR_IN)) + if (is_return) return flags | HANDLE_PARAM_IS_OUT | HANDLE_PARAM_IS_RETURN; + + is_out = is_attr(attrs, ATTR_OUT); + if (is_attr(attrs, ATTR_IN) || !is_out) { - flags |= 0x40; - if (!is_attr(attrs, ATTR_OUT)) flags |= NDR_CONTEXT_HANDLE_CANNOT_BE_NULL; + flags |= HANDLE_PARAM_IS_IN; + if (!is_out) flags |= NDR_CONTEXT_HANDLE_CANNOT_BE_NULL; } - if (is_attr(attrs, ATTR_OUT)) flags |= 0x20; + if (is_out) flags |= HANDLE_PARAM_IS_OUT; return flags; } @@ -490,14 +532,14 @@ unsigned char get_struct_fc(const type_t *type) if (fields) LIST_FOR_EACH_ENTRY( field, fields, var_t, entry ) { - type_t *t = field->type; + type_t *t = field->declspec.type; enum typegen_type typegen_type; typegen_type = typegen_detect_type(t, field->attrs, TDT_IGNORE_STRINGS); if (typegen_type == TGT_ARRAY && !type_array_is_decl_as_ptr(t)) { - if (is_string_type(field->attrs, field->type)) + if (is_string_type(field->attrs, field->declspec.type)) { if (is_conformant_array(t)) has_conformance = 1; @@ -505,10 +547,10 @@ unsigned char get_struct_fc(const type_t *type) continue; } - if (is_array(type_array_get_element(field->type))) + if (is_array(type_array_get_element_type(field->declspec.type))) return FC_BOGUS_STRUCT; - if (type_array_has_conformance(field->type)) + if (type_array_has_conformance(field->declspec.type)) { has_conformance = 1; if (list_next(fields, &field->entry)) @@ -518,7 +560,7 @@ unsigned char get_struct_fc(const type_t *type) if (type_array_has_variance(t)) has_variance = 1; - t = type_array_get_element(t); + t = type_array_get_element_type(t); typegen_type = typegen_detect_type(t, field->attrs, TDT_IGNORE_STRINGS); } @@ -537,7 +579,7 @@ unsigned char get_struct_fc(const type_t *type) break; case TGT_POINTER: case TGT_ARRAY: - if (get_pointer_fc(t, field->attrs, FALSE) == FC_RP || pointer_size != 4) + if (get_pointer_fc(t, field->attrs, TRUE, FALSE) == FC_RP || pointer_size != 4) return FC_BOGUS_STRUCT; has_pointer = 1; break; @@ -614,13 +656,13 @@ unsigned char get_struct_fc(const type_t *type) return FC_STRUCT; } -static unsigned char get_array_fc(const type_t *type) +static unsigned char get_array_fc(const type_t *type, const attr_list_t *attrs) { unsigned char fc; const expr_t *size_is; const type_t *elem_type; - elem_type = type_array_get_element(type); + elem_type = type_array_get_element_type(type); size_is = type_array_get_conformance(type); if (!size_is) @@ -644,7 +686,7 @@ static unsigned char get_array_fc(const type_t *type) fc = FC_CVARRAY; } - switch (typegen_detect_type(elem_type, NULL, TDT_IGNORE_STRINGS)) + switch (typegen_detect_type(elem_type, attrs, TDT_IGNORE_STRINGS)) { case TGT_USER_TYPE: fc = FC_BOGUS_ARRAY; @@ -676,7 +718,7 @@ static unsigned char get_array_fc(const type_t *type) /* ref pointers cannot just be block copied. unique pointers to * interfaces need special treatment. either case means the array is * complex */ - if (get_pointer_fc(elem_type, NULL, FALSE) == FC_RP || pointer_size != 4) + if (get_pointer_fc(elem_type, attrs, FALSE, FALSE) == FC_RP || pointer_size != 4) fc = FC_BOGUS_ARRAY; break; case TGT_RANGE: @@ -700,23 +742,23 @@ static int is_non_complex_struct(const type_t *type) get_struct_fc(type) != FC_BOGUS_STRUCT); } -static int type_has_pointers(const type_t *type) +static int type_has_pointers(const type_t *type, const attr_list_t *attrs) { - switch (typegen_detect_type(type, NULL, TDT_IGNORE_STRINGS)) + switch (typegen_detect_type(type, attrs, TDT_IGNORE_STRINGS)) { case TGT_USER_TYPE: return FALSE; case TGT_POINTER: return TRUE; case TGT_ARRAY: - return type_array_is_decl_as_ptr(type) || type_has_pointers(type_array_get_element(type)); + return type_array_is_decl_as_ptr(type) || type_has_pointers(type_array_get_element_type(type), attrs); case TGT_STRUCT: { var_list_t *fields = type_struct_get_fields(type); const var_t *field; if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) { - if (type_has_pointers(field->type)) + if (type_has_pointers(field->declspec.type, attrs)) return TRUE; } break; @@ -728,7 +770,7 @@ static int type_has_pointers(const type_t *type) fields = type_union_get_cases(type); if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) { - if (field->type && type_has_pointers(field->type)) + if (field->declspec.type && type_has_pointers(field->declspec.type, attrs)) return TRUE; } break; @@ -747,33 +789,87 @@ static int type_has_pointers(const type_t *type) return FALSE; } -static int type_has_full_pointer(const type_t *type, const attr_list_t *attrs, - int toplevel_param) +struct visited_struct_array { - switch (typegen_detect_type(type, NULL, TDT_IGNORE_STRINGS)) + const type_t **structs; + size_t count; + size_t capacity; +}; + +static inline int array_reserve(void **elements, size_t *capacity, size_t count, size_t size) +{ + size_t new_capacity, max_capacity; + void *new_elements; + + if (count <= *capacity) + return TRUE; + + max_capacity = ~(size_t)0 / size; + if (count > max_capacity) + return FALSE; + + new_capacity = max(4, *capacity); + while (new_capacity < count && new_capacity <= max_capacity / 2) + new_capacity *= 2; + if (new_capacity < count) + new_capacity = max_capacity; + + if (!(new_elements = realloc(*elements, new_capacity * size))) + return FALSE; + + *elements = new_elements; + *capacity = new_capacity; + return TRUE; +} + +static int type_has_full_pointer_recurse(const type_t *type, const attr_list_t *attrs, int toplevel_attrs, + int toplevel_param, struct visited_struct_array *visited_structs) +{ + switch (typegen_detect_type(type, attrs, TDT_IGNORE_STRINGS)) { case TGT_USER_TYPE: return FALSE; case TGT_POINTER: - if (get_pointer_fc(type, attrs, toplevel_param) == FC_FP) + if (get_pointer_fc(type, attrs, toplevel_attrs, toplevel_param) == FC_FP) return TRUE; else - return FALSE; + return type_has_full_pointer_recurse(type_pointer_get_ref_type(type), attrs, FALSE, FALSE, visited_structs); case TGT_ARRAY: - if (get_pointer_fc(type, attrs, toplevel_param) == FC_FP) + if (get_pointer_fc(type, attrs, toplevel_attrs, toplevel_param) == FC_FP) return TRUE; else - return type_has_full_pointer(type_array_get_element(type), NULL, FALSE); + return type_has_full_pointer_recurse(type_array_get_element_type(type), attrs, FALSE, FALSE, visited_structs); case TGT_STRUCT: { + unsigned int i; + int ret = FALSE; var_list_t *fields = type_struct_get_fields(type); const var_t *field; + + for (i = 0; i < visited_structs->count; i++) + { + if (visited_structs->structs[i] == type) + { + /* Found struct we visited already, abort to prevent infinite loop. + * Can't be at the first struct we visit, so we can skip cleanup and just return */ + return FALSE; + } + } + + array_reserve((void**)&visited_structs->structs, &visited_structs->capacity, visited_structs->count + 1, sizeof(struct type_t*)); + visited_structs->structs[visited_structs->count] = type; + + visited_structs->count++; if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) { - if (type_has_full_pointer(field->type, field->attrs, FALSE)) - return TRUE; + if (type_has_full_pointer_recurse(field->declspec.type, field->attrs, TRUE, FALSE, visited_structs)) + { + ret = TRUE; + break; + } } - break; + visited_structs->count--; + return ret; } case TGT_UNION: { @@ -782,7 +878,7 @@ static int type_has_full_pointer(const type_t *type, const attr_list_t *attrs, fields = type_union_get_cases(type); if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) { - if (field->type && type_has_full_pointer(field->type, field->attrs, FALSE)) + if (field->declspec.type && type_has_full_pointer_recurse(field->declspec.type, field->attrs, TRUE, FALSE, visited_structs)) return TRUE; } break; @@ -801,6 +897,15 @@ static int type_has_full_pointer(const type_t *type, const attr_list_t *attrs, return FALSE; } +static int type_has_full_pointer(const type_t *type, const attr_list_t *attrs, int toplevel_attrs, int toplevel_param) +{ + int ret; + struct visited_struct_array visited_structs = {0}; + ret = type_has_full_pointer_recurse(type, attrs, toplevel_attrs, toplevel_param, &visited_structs); + free(visited_structs.structs); + return ret; +} + static unsigned short user_type_offset(const char *name) { user_type_t *ut; @@ -832,9 +937,9 @@ static void guard_rec(type_t *type) type->typestring_offset = 1; } -static int is_embedded_complex(const type_t *type) +static int is_embedded_complex(const type_t *type, const attr_list_t *attrs) { - switch (typegen_detect_type(type, NULL, TDT_ALL_TYPES)) + switch (typegen_detect_type(type, attrs, TDT_IGNORE_STRINGS)) { case TGT_USER_TYPE: case TGT_STRUCT: @@ -852,7 +957,7 @@ static const char *get_context_handle_type_name(const type_t *type) const type_t *t; for (t = type; is_ptr(t) || type_is_alias(t); - t = type_is_alias(t) ? type_alias_get_aliasee(t) : type_pointer_get_ref(t)) + t = type_is_alias(t) ? type_alias_get_aliasee_type(t) : type_pointer_get_ref_type(t)) if (is_attr(t->attrs, ATTR_CONTEXTHANDLE)) return t->name; assert(0); @@ -902,16 +1007,16 @@ static void write_var_init(FILE *file, int indent, const type_t *t, const char * void write_parameters_init(FILE *file, int indent, const var_t *func, const char *local_var_prefix) { - const var_t *var = type_function_get_retval(func->type); + const var_t *var = type_function_get_retval(func->declspec.type); - if (!is_void(var->type)) - write_var_init(file, indent, var->type, var->name, local_var_prefix); + if (!is_void(var->declspec.type)) + write_var_init(file, indent, var->declspec.type, var->name, local_var_prefix); - if (!type_get_function_args(func->type)) + if (!type_function_get_args(func->declspec.type)) return; - LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) - write_var_init(file, indent, var->type, var->name, local_var_prefix); + LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry ) + write_var_init(file, indent, var->declspec.type, var->name, local_var_prefix); fprintf(file, "\n"); } @@ -956,7 +1061,8 @@ int decl_indirect(const type_t *t) } static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned short *flags, - unsigned int *stack_size, unsigned int *typestring_offset ) + unsigned int *stack_size, unsigned int *stack_align, + unsigned int *typestring_offset ) { unsigned int alignment, server_size = 0, buffer_size = 0; unsigned char fc = 0; @@ -968,30 +1074,26 @@ static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned else if (!is_in && !is_out) is_in = TRUE; *flags = 0; - *stack_size = get_stack_size( var, &is_byval ); + *stack_size = get_stack_size( var, stack_align, &is_byval ); *typestring_offset = var->typestring_offset; if (is_in) *flags |= IsIn; if (is_out) *flags |= IsOut; if (is_return) *flags |= IsReturn; - if (!is_string_type( var->attrs, var->type )) - buffer_size = get_required_buffer_size_type( var->type, NULL, var->attrs, TRUE, &alignment ); + if (!is_string_type( var->attrs, var->declspec.type )) + buffer_size = get_required_buffer_size_type( var->declspec.type, NULL, var->attrs, TRUE, TRUE, &alignment ); - switch (typegen_detect_type( var->type, var->attrs, TDT_ALL_TYPES )) + switch (typegen_detect_type( var->declspec.type, var->attrs, TDT_ALL_TYPES )) { case TGT_BASIC: *flags |= IsBasetype; - fc = get_basic_fc_signed( var->type ); - if (fc == FC_BIND_PRIMITIVE) - { - buffer_size = 4; /* actually 0 but avoids setting MustSize */ - fc = FC_LONG; - } + fc = get_basic_fc_signed( var->declspec.type ); + if (fc == FC_BIND_PRIMITIVE) buffer_size = 4; /* actually 0 but avoids setting MustSize */ break; case TGT_ENUM: *flags |= IsBasetype; - fc = get_enum_fc( var->type ); + fc = get_enum_fc( var->declspec.type ); break; case TGT_RANGE: *flags |= IsByValue; @@ -1006,19 +1108,20 @@ static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned break; case TGT_ARRAY: *flags |= MustFree; - if (type_array_is_decl_as_ptr(var->type) && var->type->details.array.ptr_tfsoff && - get_pointer_fc( var->type, var->attrs, !is_return ) == FC_RP) + if (type_array_is_decl_as_ptr(var->declspec.type) + && type_array_get_ptr_tfsoff(var->declspec.type) + && get_pointer_fc(var->declspec.type, var->attrs, TRUE, !is_return) == FC_RP) { - *typestring_offset = var->type->typestring_offset; + *typestring_offset = var->declspec.type->typestring_offset; *flags |= IsSimpleRef; } break; case TGT_STRING: *flags |= MustFree; - if (is_declptr( var->type ) && get_pointer_fc( var->type, var->attrs, !is_return ) == FC_RP) + if (is_declptr( var->declspec.type ) && get_pointer_fc( var->declspec.type, var->attrs, TRUE, !is_return ) == FC_RP) { /* skip over pointer description straight to string description */ - if (is_conformant_array( var->type )) *typestring_offset += 4; + if (is_conformant_array( var->declspec.type )) *typestring_offset += 4; else *typestring_offset += 2; *flags |= IsSimpleRef; } @@ -1031,14 +1134,14 @@ static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned buffer_size = 20; break; case TGT_POINTER: - if (get_pointer_fc( var->type, var->attrs, !is_return ) == FC_RP) + if (get_pointer_fc( var->declspec.type, var->attrs, TRUE, !is_return ) == FC_RP) { - const type_t *ref = type_pointer_get_ref( var->type ); + const type_t *ref = type_pointer_get_ref_type( var->declspec.type ); if (!is_string_type( var->attrs, ref )) - buffer_size = get_required_buffer_size_type( ref, NULL, NULL, TRUE, &alignment ); + buffer_size = get_required_buffer_size_type( ref, NULL, var->attrs, FALSE, TRUE, &alignment ); - switch (typegen_detect_type( ref, NULL, TDT_ALL_TYPES )) + switch (typegen_detect_type( ref, var->attrs, TDT_ALL_TYPES )) { case TGT_BASIC: *flags |= IsSimpleRef | IsBasetype; @@ -1059,11 +1162,19 @@ static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned case TGT_UNION: case TGT_USER_TYPE: case TGT_RANGE: - case TGT_ARRAY: - *flags |= IsSimpleRef | MustFree; + *flags |= MustFree | IsSimpleRef; *typestring_offset = ref->typestring_offset; if (!is_in && is_out) server_size = type_memsize( ref ); break; + case TGT_ARRAY: + *flags |= MustFree; + if (!type_array_is_decl_as_ptr(ref)) + { + *flags |= IsSimpleRef; + *typestring_offset = ref->typestring_offset; + } + if (!is_in && is_out) server_size = type_memsize( ref ); + break; case TGT_STRING: case TGT_POINTER: case TGT_CTXT_HANDLE: @@ -1115,15 +1226,15 @@ static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned static unsigned char get_func_oi2_flags( const var_t *func ) { const var_t *var; - var_list_t *args = type_get_function_args( func->type ); - var_t *retval = type_function_get_retval( func->type ); + var_list_t *args = type_function_get_args( func->declspec.type ); + var_t *retval = type_function_get_retval( func->declspec.type ); unsigned char oi2_flags = 0x40; /* HasExtensions */ unsigned short flags; - unsigned int stack_size, typestring_offset; + unsigned int stack_size, stack_align, typestring_offset; if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry ) { - get_parameter_fc( var, 0, &flags, &stack_size, &typestring_offset ); + get_parameter_fc( var, 0, &flags, &stack_size, &stack_align, &typestring_offset ); if (flags & MustSize) { if (flags & IsIn) oi2_flags |= 0x02; /* ClientMustSize */ @@ -1131,10 +1242,10 @@ static unsigned char get_func_oi2_flags( const var_t *func ) } } - if (!is_void( retval->type )) + if (!is_void( retval->declspec.type )) { oi2_flags |= 0x04; /* HasRet */ - get_parameter_fc( retval, 1, &flags, &stack_size, &typestring_offset ); + get_parameter_fc( retval, 1, &flags, &stack_size, &stack_align, &typestring_offset ); if (flags & MustSize) oi2_flags |= 0x01; /* ServerMustSize */ } return oi2_flags; @@ -1144,10 +1255,11 @@ static unsigned int write_new_procformatstring_type(FILE *file, int indent, cons int is_return, unsigned int *stack_offset) { char buffer[128]; - unsigned int stack_size, typestring_offset; + unsigned int stack_size, stack_align, typestring_offset; unsigned short flags; - unsigned char fc = get_parameter_fc( var, is_return, &flags, &stack_size, &typestring_offset ); + unsigned char fc = get_parameter_fc( var, is_return, &flags, &stack_size, &stack_align, &typestring_offset ); + *stack_offset = ROUND_SIZE( *stack_offset, stack_align ); strcpy( buffer, "/* flags:" ); if (flags & MustSize) strcat( buffer, " must size," ); if (flags & MustFree) strcat( buffer, " must free," ); @@ -1158,7 +1270,7 @@ static unsigned int write_new_procformatstring_type(FILE *file, int indent, cons if (flags & IsBasetype) strcat( buffer, " base type," ); if (flags & IsByValue) strcat( buffer, " by value," ); if (flags & IsSimpleRef) strcat( buffer, " simple ref," ); - if (flags >> 13) sprintf( buffer + strlen(buffer), " srv size=%u,", (flags >> 13) * 8 ); + if (flags >> 13) snprintf( buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), " srv size=%u,", (flags >> 13) * 8 ); strcpy( buffer + strlen( buffer ) - 1, " */" ); print_file( file, indent, "NdrFcShort(0x%hx),\t%s\n", flags, buffer ); print_file( file, indent, "NdrFcShort(0x%x), /* stack offset = %u */\n", @@ -1171,12 +1283,12 @@ static unsigned int write_new_procformatstring_type(FILE *file, int indent, cons else print_file( file, indent, "NdrFcShort(0x%x), /* type offset = %u */\n", typestring_offset, typestring_offset ); - *stack_offset += max( stack_size, pointer_size ); + *stack_offset += stack_size; return 6; } static unsigned int write_old_procformatstring_type(FILE *file, int indent, const var_t *var, - int is_return, int is_interpreted) + int is_return) { unsigned int size; @@ -1185,8 +1297,8 @@ static unsigned int write_old_procformatstring_type(FILE *file, int indent, cons if (!is_in && !is_out) is_in = TRUE; - if (type_get_type(var->type) == TYPE_BASIC || - type_get_type(var->type) == TYPE_ENUM) + if (type_get_type(var->declspec.type) == TYPE_BASIC || + type_get_type(var->declspec.type) == TYPE_ENUM) { unsigned char fc; @@ -1195,13 +1307,13 @@ static unsigned int write_old_procformatstring_type(FILE *file, int indent, cons else print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n"); - if (type_get_type(var->type) == TYPE_ENUM) + if (type_get_type(var->declspec.type) == TYPE_ENUM) { - fc = get_enum_fc(var->type); + fc = get_enum_fc(var->declspec.type); } else { - fc = get_basic_fc_signed(var->type); + fc = get_basic_fc_signed(var->declspec.type); if (fc == FC_BIND_PRIMITIVE) fc = FC_IGNORE; @@ -1215,10 +1327,10 @@ static unsigned int write_old_procformatstring_type(FILE *file, int indent, cons { unsigned short offset = var->typestring_offset; - if (!is_interpreted && is_array(var->type) && - type_array_is_decl_as_ptr(var->type) && - var->type->details.array.ptr_tfsoff) - offset = var->type->typestring_offset; + if (is_array(var->declspec.type) + && type_array_is_decl_as_ptr(var->declspec.type) + && type_array_get_ptr_tfsoff(var->declspec.type)) + offset = var->declspec.type->typestring_offset; if (is_return) print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n"); @@ -1229,7 +1341,7 @@ static unsigned int write_old_procformatstring_type(FILE *file, int indent, cons else print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n"); - size = get_stack_size( var, NULL ); + size = get_stack_size( var, NULL, NULL ); print_file(file, indent, "0x%02x,\n", size / pointer_size ); print_file(file, indent, "NdrFcShort(0x%x), /* type offset = %u */\n", offset, offset); size = 4; /* includes param type prefix */ @@ -1240,9 +1352,7 @@ static unsigned int write_old_procformatstring_type(FILE *file, int indent, cons int is_interpreted_func( const type_t *iface, const var_t *func ) { const char *str; - const var_t *var; - const var_list_t *args = type_get_function_args( func->type ); - const type_t *ret_type = type_function_get_rettype( func->type ); + const type_t *ret_type = type_function_get_rettype( func->declspec.type ); if (type_get_type( ret_type ) == TYPE_BASIC) { @@ -1261,54 +1371,163 @@ int is_interpreted_func( const type_t *iface, const var_t *func ) break; } } - if (get_stub_mode() != MODE_Oif && args) - { - LIST_FOR_EACH_ENTRY( var, args, const var_t, entry ) - switch (type_get_type( var->type )) - { - case TYPE_BASIC: - switch (type_basic_get_type( var->type )) - { - /* floating point arguments are not supported in Oi mode */ - case TYPE_BASIC_FLOAT: return 0; - case TYPE_BASIC_DOUBLE: return 0; - default: break; - } - break; - /* unions passed by value are not supported in Oi mode */ - case TYPE_UNION: return 0; - case TYPE_ENCAPSULATED_UNION: return 0; - default: break; - } - } - if ((str = get_attrp( func->attrs, ATTR_OPTIMIZE ))) return !strcmp( str, "i" ); if ((str = get_attrp( iface->attrs, ATTR_OPTIMIZE ))) return !strcmp( str, "i" ); - return (get_stub_mode() != MODE_Os); + return interpreted_mode; } -static void write_proc_func_header( FILE *file, int indent, const type_t *iface, +/* replace consecutive params code by a repeat sequence: 0x9d code<1> repeat_count<2> */ +static unsigned int compress_params_array( unsigned char *params, unsigned int count ) +{ + unsigned int i, j; + + for (i = 0; i + 4 <= count; i++) + { + for (j = 1; i + j < count; j++) if (params[i + j] != params[i]) break; + if (j < 4) continue; + params[i] = 0x9d; + params[i + 2] = j & 0xff; + params[i + 3] = j >> 8; + memmove( params + i + 4, params + i + j, count - (i + j) ); + count -= j - 4; + i += 3; + } + return count; +} + +/* fill the parameters array for the procedure extra data on ARM platforms */ +static unsigned int fill_params_array( const type_t *iface, const var_t *func, + unsigned char *params, unsigned int count ) +{ + unsigned int reg_count = 0, float_count = 0, double_count = 0, stack_pos = 0, offset = 0; + var_list_t *args = type_function_get_args( func->declspec.type ); + enum type_basic_type type; + unsigned int size, pos, align; + var_t *var; + + memset( params, 0x9f /* padding */, count ); + + if (is_object( iface )) + { + params[0] = 0x80 + reg_count++; + offset += pointer_size; + } + + if (args) LIST_FOR_EACH_ENTRY( var, args, var_t, entry ) + { + type = TYPE_BASIC_LONG; + if (type_get_type( var->declspec.type ) == TYPE_BASIC) + type = type_basic_get_type( var->declspec.type ); + + size = get_stack_size( var, &align, NULL ); + offset = ROUND_SIZE( offset, align ); + pos = offset / pointer_size; + + if (target.cpu == CPU_ARM64) + { + switch (type) + { + case TYPE_BASIC_FLOAT: + case TYPE_BASIC_DOUBLE: + if (double_count >= 8) break; + params[pos] = 0x88 + double_count++; + offset += size; + continue; + + default: + reg_count = ROUND_SIZE( reg_count, align / pointer_size ); + if (reg_count > 8 - size / pointer_size) break; + while (size) + { + params[pos++] = 0x80 + reg_count++; + offset += pointer_size; + size -= pointer_size; + } + continue; + } + } + else /* CPU_ARM */ + { + switch (type) + { + case TYPE_BASIC_FLOAT: + if (!(float_count % 2)) float_count = max( float_count, double_count * 2 ); + if (float_count >= 16) + { + stack_pos = ROUND_SIZE( stack_pos, align ); + params[pos] = 0x100 - (offset - stack_pos) / pointer_size; + stack_pos += size; + } + else + { + params[pos] = 0x84 + float_count++; + } + offset += size; + continue; + + case TYPE_BASIC_DOUBLE: + double_count = max( double_count, (float_count + 1) / 2 ); + if (double_count >= 8) break; + params[pos] = 0x84 + 2 * double_count; + params[pos + 1] = 0x84 + 2 * double_count + 1; + double_count++; + offset += size; + continue; + + default: + reg_count = ROUND_SIZE( reg_count, align / pointer_size ); + if (reg_count <= 4 - size / pointer_size || !stack_pos) + { + while (size && reg_count < 4) + { + params[pos++] = 0x80 + reg_count++; + offset += pointer_size; + size -= pointer_size; + } + } + break; + } + } + + stack_pos = ROUND_SIZE( stack_pos, align ); + memset( params + pos, 0x100 - (offset - stack_pos) / pointer_size, size / pointer_size ); + stack_pos += size; + offset += size; + } + + while (count && params[count - 1] == 0x9f) count--; + return count; +} + +static void write_proc_func_interp( FILE *file, int indent, const type_t *iface, const var_t *func, unsigned int *offset, unsigned short num_proc ) { var_t *var; - var_list_t *args = type_get_function_args( func->type ); + var_list_t *args = type_function_get_args( func->declspec.type ); unsigned char explicit_fc, implicit_fc; unsigned char handle_flags; + var_t *retval = type_function_get_retval( func->declspec.type ); const var_t *handle_var = get_func_handle_var( iface, func, &explicit_fc, &implicit_fc ); unsigned char oi_flags = Oi_HAS_RPCFLAGS | Oi_USE_NEW_INIT_ROUTINES; + unsigned char oi2_flags = get_func_oi2_flags( func ); + unsigned char ext_flags = 0x01; /* HasNewCorrDesc */ unsigned int rpc_flags = get_rpc_flags( func->attrs ); unsigned int nb_args = 0; unsigned int stack_size = 0; + unsigned int stack_offset = 0; + unsigned int stack_align; + unsigned int extra_size = 0; unsigned short param_num = 0; unsigned short handle_stack_offset = 0; unsigned short handle_param_num = 0; + unsigned int size; if (is_full_pointer_function( func )) oi_flags |= Oi_FULL_PTR_USED; if (is_object( iface )) { - oi_flags |= Oi_OBJECT_PROC; - if (get_stub_mode() == MODE_Oif) oi_flags |= Oi_OBJ_USE_V2_INTERPRETER; + oi_flags |= Oi_OBJECT_PROC | Oi_OBJ_USE_V2_INTERPRETER; + stack_offset = pointer_size; stack_size += pointer_size; } @@ -1319,13 +1538,13 @@ static void write_proc_func_header( FILE *file, int indent, const type_t *iface, handle_stack_offset = stack_size; handle_param_num = param_num; } - stack_size += get_stack_size( var, NULL ); + size = get_stack_size( var, &stack_align, NULL ); + stack_size = ROUND_SIZE( stack_size, stack_align ); + stack_size += size; param_num++; - - if (var != handle_var || implicit_fc || explicit_fc != FC_BIND_PRIMITIVE) - nb_args++; + nb_args++; } - if (!is_void( type_function_get_rettype( func->type ))) + if (!is_void( retval->declspec.type )) { stack_size += pointer_size; nb_args++; @@ -1351,74 +1570,124 @@ static void write_proc_func_header( FILE *file, int indent, const type_t *iface, print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack offset = %hu */\n", handle_stack_offset, handle_stack_offset ); *offset += 4; + nb_args--; break; case FC_BIND_GENERIC: - handle_flags = type_memsize( handle_var->type ); + handle_flags = type_memsize( handle_var->declspec.type ); print_file( file, indent, "0x%02x,\t/* %s */\n", explicit_fc, string_of_type(explicit_fc) ); print_file( file, indent, "0x%02x,\n", handle_flags ); print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack offset = %hu */\n", handle_stack_offset, handle_stack_offset ); - print_file( file, indent, "0x%02x,\n", get_generic_handle_offset( handle_var->type ) ); + print_file( file, indent, "0x%02x,\n", get_generic_handle_offset( handle_var->declspec.type ) ); print_file( file, indent, "0x%x,\t/* FC_PAD */\n", FC_PAD); *offset += 6; break; case FC_BIND_CONTEXT: - handle_flags = get_contexthandle_flags( iface, handle_var->attrs, handle_var->type ); + handle_flags = get_contexthandle_flags( iface, handle_var->attrs, handle_var->declspec.type, 0 ); print_file( file, indent, "0x%02x,\t/* %s */\n", explicit_fc, string_of_type(explicit_fc) ); print_file( file, indent, "0x%02x,\n", handle_flags ); print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack offset = %hu */\n", handle_stack_offset, handle_stack_offset ); - print_file( file, indent, "0x%02x,\n", get_context_handle_offset( handle_var->type ) ); + print_file( file, indent, "0x%02x,\n", get_context_handle_offset( handle_var->declspec.type ) ); print_file( file, indent, "0x%02x,\t/* param %hu */\n", handle_param_num, handle_param_num ); *offset += 6; break; } } - if (get_stub_mode() == MODE_Oif) + if (is_attr( func->attrs, ATTR_NOTIFY )) ext_flags |= 0x08; /* HasNotify */ + if (is_attr( func->attrs, ATTR_NOTIFYFLAG )) ext_flags |= 0x10; /* HasNotify2 */ + if (iface == type_iface_get_async_iface(iface)) oi2_flags |= 0x20; + + size = get_function_buffer_size( func, PASS_IN ); + print_file( file, indent, "NdrFcShort(0x%x),\t/* client buffer = %u */\n", size, size ); + size = get_function_buffer_size( func, PASS_OUT ); + print_file( file, indent, "NdrFcShort(0x%x),\t/* server buffer = %u */\n", size, size ); + print_file( file, indent, "0x%02x,\n", oi2_flags ); + print_file( file, indent, "0x%02x,\t/* %u params */\n", nb_args, nb_args ); + *offset += 6; + extra_size = 8; + + switch (target.cpu) { - unsigned char oi2_flags = get_func_oi2_flags( func ); - unsigned char ext_flags = 0; - unsigned int size; + case CPU_x86_64: + case CPU_ARM64EC: + { + unsigned short pos = 0, fpu_mask = 0; - if (is_attr( func->attrs, ATTR_NOTIFY )) ext_flags |= 0x08; /* HasNotify */ - if (is_attr( func->attrs, ATTR_NOTIFYFLAG )) ext_flags |= 0x10; /* HasNotify2 */ - if (iface == iface->details.iface->async_iface) oi2_flags |= 0x20; - - size = get_function_buffer_size( func, PASS_IN ); - print_file( file, indent, "NdrFcShort(0x%x),\t/* client buffer = %u */\n", size, size ); - size = get_function_buffer_size( func, PASS_OUT ); - print_file( file, indent, "NdrFcShort(0x%x),\t/* server buffer = %u */\n", size, size ); - print_file( file, indent, "0x%02x,\n", oi2_flags ); - print_file( file, indent, "0x%02x,\t/* %u params */\n", nb_args, nb_args ); - print_file( file, indent, "0x%02x,\n", pointer_size == 8 ? 10 : 8 ); + extra_size += 2; + print_file( file, indent, "0x%02x,\n", extra_size ); print_file( file, indent, "0x%02x,\n", ext_flags ); print_file( file, indent, "NdrFcShort(0x0),\n" ); /* server corr hint */ print_file( file, indent, "NdrFcShort(0x0),\n" ); /* client corr hint */ print_file( file, indent, "NdrFcShort(0x0),\n" ); /* FIXME: notify index */ - *offset += 14; - if (pointer_size == 8) + if (is_object( iface )) pos += 2; + if (args) LIST_FOR_EACH_ENTRY( var, args, var_t, entry ) { - unsigned short pos = 0, fpu_mask = 0; - - if (is_object( iface )) pos += 2; - if (args) LIST_FOR_EACH_ENTRY( var, args, var_t, entry ) + if (type_get_type( var->declspec.type ) == TYPE_BASIC) { - if (type_get_type( var->type ) == TYPE_BASIC) + switch (type_basic_get_type( var->declspec.type )) { - switch (type_basic_get_type( var->type )) - { - case TYPE_BASIC_FLOAT: fpu_mask |= 1 << pos; break; - case TYPE_BASIC_DOUBLE: fpu_mask |= 2 << pos; break; - default: break; - } + case TYPE_BASIC_FLOAT: fpu_mask |= 1 << pos; break; + case TYPE_BASIC_DOUBLE: fpu_mask |= 2 << pos; break; + default: break; } - pos += 2; - if (pos >= 16) break; } - print_file( file, indent, "NdrFcShort(0x%x),\n", fpu_mask ); /* floating point mask */ - *offset += 2; + pos += 2; + if (pos >= 16) break; } + print_file( file, indent, "NdrFcShort(0x%x),\n", fpu_mask ); /* floating point mask */ + break; + } + case CPU_ARM: + case CPU_ARM64: + { + unsigned int i, len, count = stack_size / pointer_size; + unsigned char *params = xmalloc( count ); + + count = fill_params_array( iface, func, params, count ); + len = compress_params_array( params, count ); + + extra_size += 3 + len + !(len % 2); + print_file( file, indent, "0x%02x,\n", extra_size ); + print_file( file, indent, "0x%02x,\n", ext_flags ); + print_file( file, indent, "NdrFcShort(0x0),\n" ); /* server corr hint */ + print_file( file, indent, "NdrFcShort(0x0),\n" ); /* client corr hint */ + print_file( file, indent, "NdrFcShort(0x0),\n" ); /* FIXME: notify index */ + print_file( file, indent, "NdrFcShort(0x%02x),\n", count ); + print_file( file, indent, "0x%02x,\n", len ); + for (i = 0; i < len; i++) print_file( file, indent, "0x%02x,\n", params[i] ); + if (!(len % 2)) print_file( file, indent, "0x00,\n" ); + free( params ); + break; + } + case CPU_i386: + print_file( file, indent, "0x%02x,\n", extra_size ); + print_file( file, indent, "0x%02x,\n", ext_flags ); + print_file( file, indent, "NdrFcShort(0x0),\n" ); /* server corr hint */ + print_file( file, indent, "NdrFcShort(0x0),\n" ); /* client corr hint */ + print_file( file, indent, "NdrFcShort(0x0),\n" ); /* FIXME: notify index */ + break; + } + *offset += extra_size; + + /* emit argument data */ + if (args) LIST_FOR_EACH_ENTRY( var, args, var_t, entry ) + { + if (explicit_fc == FC_BIND_PRIMITIVE && var == handle_var) + { + stack_offset += pointer_size; + continue; + } + print_file( file, 0, "/* %u (parameter %s) */\n", *offset, var->name ); + *offset += write_new_procformatstring_type(file, indent, var, FALSE, &stack_offset); + } + + /* emit return value data */ + if (!is_void( retval->declspec.type )) + { + print_file( file, 0, "/* %u (return value) */\n", *offset ); + *offset += write_new_procformatstring_type(file, indent, retval, TRUE, &stack_offset); } } @@ -1426,54 +1695,38 @@ static void write_procformatstring_func( FILE *file, int indent, const type_t *i const var_t *func, unsigned int *offset, unsigned short num_proc ) { - unsigned int stack_offset = is_object( iface ) ? pointer_size : 0; - int is_interpreted = is_interpreted_func( iface, func ); - int is_new_style = is_interpreted && (get_stub_mode() == MODE_Oif); - var_t *retval = type_function_get_retval( func->type ); - unsigned char explicit_fc, implicit_fc; - const var_t *handle_var = get_func_handle_var( iface, func, &explicit_fc, &implicit_fc ); + var_t *retval; - if (is_interpreted) write_proc_func_header( file, indent, iface, func, offset, num_proc ); + if (is_interpreted_func( iface, func )) + { + write_proc_func_interp( file, indent, iface, func, offset, num_proc ); + return; + } /* emit argument data */ - if (type_get_function_args(func->type)) + if (type_function_get_args(func->declspec.type)) { const var_t *var; - LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) + LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry ) { - if (var != handle_var || implicit_fc || explicit_fc != FC_BIND_PRIMITIVE) - { - print_file( file, 0, "/* %u (parameter %s) */\n", *offset, var->name ); - if (is_new_style) - *offset += write_new_procformatstring_type(file, indent, var, FALSE, &stack_offset); - else - *offset += write_old_procformatstring_type(file, indent, var, FALSE, is_interpreted); - } - else - { - stack_offset += pointer_size; - } + print_file( file, 0, "/* %u (parameter %s) */\n", *offset, var->name ); + *offset += write_old_procformatstring_type(file, indent, var, FALSE); } } /* emit return value data */ - if (is_void(retval->type)) + retval = type_function_get_retval( func->declspec.type ); + if (is_void(retval->declspec.type)) { - if (!is_new_style) - { - print_file(file, 0, "/* %u (void) */\n", *offset); - print_file(file, indent, "0x5b,\t/* FC_END */\n"); - print_file(file, indent, "0x5c,\t/* FC_PAD */\n"); - *offset += 2; - } + print_file(file, 0, "/* %u (void) */\n", *offset); + print_file(file, indent, "0x5b,\t/* FC_END */\n"); + print_file(file, indent, "0x5c,\t/* FC_PAD */\n"); + *offset += 2; } else { print_file( file, 0, "/* %u (return value) */\n", *offset ); - if (is_new_style) - *offset += write_new_procformatstring_type(file, indent, retval, TRUE, &stack_offset); - else - *offset += write_old_procformatstring_type(file, indent, retval, TRUE, is_interpreted); + *offset += write_old_procformatstring_type(file, indent, retval, TRUE); } } @@ -1491,8 +1744,8 @@ static void for_each_iface(const statement_list_t *stmts, iface = stmt->u.type; if (!pred(iface)) continue; proc(iface, file, indent, offset); - if (iface->details.iface->async_iface) - proc(iface->details.iface->async_iface, file, indent, offset); + if (type_iface_get_async_iface(iface)) + proc(type_iface_get_async_iface(iface), file, indent, offset); } } @@ -1505,7 +1758,11 @@ static void write_iface_procformatstring(type_t *iface, FILE *file, int indent, STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) { var_t *func = stmt->u.var; - if (is_local(func->attrs)) continue; + if (is_local(func->attrs)) + { + if (!get_callas_source(iface, func)) count++; + continue; + } write_procformatstring_func( file, indent, iface, func, offset, count++ ); } } @@ -1567,10 +1824,45 @@ static int write_base_type(FILE *file, const type_t *type, unsigned int *typestr return 1; } +static unsigned char get_correlation_type( const type_t *correlation_var ) +{ + unsigned char fc; + + switch (type_get_type(correlation_var)) + { + case TYPE_BASIC: + fc = get_basic_fc(correlation_var); + switch (fc) + { + case FC_SMALL: + case FC_USMALL: + case FC_SHORT: + case FC_USHORT: + case FC_LONG: + case FC_ULONG: + return fc; + case FC_CHAR: + return FC_SMALL; + case FC_BYTE: + return FC_USMALL; + case FC_WCHAR: + return FC_SHORT; + } + break; + case TYPE_ENUM: + return (get_enum_fc(correlation_var) == FC_ENUM32) ? FC_LONG : FC_SHORT; + case TYPE_POINTER: + return (pointer_size == 8) ? FC_HYPER : FC_LONG; + default: + break; + } + return 0; +} + /* write conformance / variance descriptor */ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type, unsigned int baseoff, const type_t *type, - const expr_t *expr) + const expr_t *expr, unsigned short robust_flags) { unsigned char operator_type = 0; unsigned char conftype = FC_NORMAL_CONFORMANCE; @@ -1582,8 +1874,10 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type, if (!expr) { print_file(file, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n"); - return 4; + robust_flags = 0; + goto done; } + robust_flags |= RobustEarly; if (expr->is_const) { @@ -1596,15 +1890,14 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type, FC_CONSTANT_CONFORMANCE, expr->cval); print_file(file, 2, "0x%x,\n", expr->cval >> 16); print_file(file, 2, "NdrFcShort(0x%hx),\n", (unsigned short)expr->cval); - - return 4; + goto done; } if (!cont_type) /* top-level conformance */ { conftype = FC_TOP_LEVEL_CONFORMANCE; conftype_string = "parameter"; - cont_type = current_func->type; + cont_type = current_func->declspec.type; name = current_func->name; iface = current_iface; } @@ -1660,25 +1953,28 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type, if (subexpr->type == EXPR_IDENTIFIER) { const type_t *correlation_variable = NULL; - unsigned char param_type = 0; + unsigned char param_type; unsigned int offset = 0; const var_t *var; struct expr_loc expr_loc; if (type_get_type(cont_type) == TYPE_FUNCTION) { - var_list_t *args = type_get_function_args( cont_type ); + var_list_t *args = type_function_get_args( cont_type ); if (is_object( iface )) offset += pointer_size; if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry ) { + unsigned int align, size = get_stack_size( var, &align, NULL ); + offset = ROUND_SIZE( offset, align ); if (var->name && !strcmp(var->name, subexpr->u.sval)) { expr_loc.v = var; - correlation_variable = var->type; + correlation_variable = var->declspec.type; break; } - offset += get_stack_size( var, NULL ); + offset += size; + if (var == current_arg) robust_flags &= ~RobustEarly; } } else @@ -1687,14 +1983,15 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type, if (fields) LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry ) { - unsigned int size = field_memsize( var->type, &offset ); + unsigned int size = field_memsize( var->declspec.type, &offset ); if (var->name && !strcmp(var->name, subexpr->u.sval)) { expr_loc.v = var; - correlation_variable = var->type; + correlation_variable = var->declspec.type; break; } offset += size; + if (offset > baseoff) robust_flags &= ~RobustEarly; } } @@ -1705,51 +2002,8 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type, offset -= baseoff; - if (type_get_type(correlation_variable) == TYPE_BASIC) - { - switch (get_basic_fc(correlation_variable)) - { - case FC_CHAR: - case FC_SMALL: - param_type = FC_SMALL; - break; - case FC_BYTE: - case FC_USMALL: - param_type = FC_USMALL; - break; - case FC_WCHAR: - case FC_SHORT: - param_type = FC_SHORT; - break; - case FC_USHORT: - param_type = FC_USHORT; - break; - case FC_LONG: - param_type = FC_LONG; - break; - case FC_ULONG: - param_type = FC_ULONG; - break; - default: - error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n", - get_basic_fc(correlation_variable)); - } - } - else if (type_get_type(correlation_variable) == TYPE_ENUM) - { - if (get_enum_fc(correlation_variable) == FC_ENUM32) - param_type = FC_LONG; - else - param_type = FC_SHORT; - } - else if (type_get_type(correlation_variable) == TYPE_POINTER) - { - if (pointer_size == 8) - param_type = FC_HYPER; - else - param_type = FC_LONG; - } - else + param_type = get_correlation_type( correlation_variable ); + if (!param_type) { error("write_conf_or_var_desc: non-arithmetic type used as correlation variable %s\n", subexpr->u.sval); @@ -1793,6 +2047,7 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type, eval->expr = expr; list_add_tail (&expr_eval_routines, &eval->entry); } + robust_flags &= ~RobustEarly; if (callback_offset > USHRT_MAX) error("Maximum number of callback routines reached\n"); @@ -1807,7 +2062,10 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type, print_file(file, 2, "0x0,\n" ); print_file(file, 2, "NdrFcShort(0x0),\n" ); } - return 4; +done: + if (!interpreted_mode) return 4; + print_file(file, 2, "NdrFcShort(0x%hx),\n", robust_flags); + return 6; } /* return size and start offset of a data field based on current offset */ @@ -1830,7 +2088,7 @@ static unsigned int fields_memsize(const var_list_t *fields, unsigned int *align LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry ) { unsigned int falign = 0; - unsigned int fsize = type_memsize_and_alignment(v->type, &falign); + unsigned int fsize = type_memsize_and_alignment(v->declspec.type, &falign); if (*align < falign) *align = falign; falign = clamp_align(falign); size = ROUND_SIZE(size, falign); @@ -1852,9 +2110,9 @@ static unsigned int union_memsize(const var_list_t *fields, unsigned int *pmaxa) if (fields) LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry ) { /* we could have an empty default field with NULL type */ - if (v->type) + if (v->declspec.type) { - size = type_memsize_and_alignment(v->type, &align); + size = type_memsize_and_alignment(v->declspec.type, &align); if (maxs < size) maxs = size; if (*pmaxa < align) *pmaxa = align; } @@ -1942,12 +2200,12 @@ unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align) { if (is_conformant_array(t)) { - type_memsize_and_alignment(type_array_get_element(t), align); + type_memsize_and_alignment(type_array_get_element_type(t), align); size = 0; } else size = type_array_get_dim(t) * - type_memsize_and_alignment(type_array_get_element(t), align); + type_memsize_and_alignment(type_array_get_element_type(t), align); } else /* declared as a pointer */ { @@ -1962,6 +2220,11 @@ unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align) case TYPE_MODULE: case TYPE_FUNCTION: case TYPE_BITFIELD: + case TYPE_APICONTRACT: + case TYPE_RUNTIMECLASS: + case TYPE_PARAMETERIZED_TYPE: + case TYPE_PARAMETER: + case TYPE_DELEGATE: /* these types should not be encountered here due to language * restrictions (interface, void, coclass, module), logical * restrictions (alias - due to type_get_type call above) or @@ -2027,8 +2290,8 @@ static unsigned int type_buffer_alignment(const type_t *t) if (!(fields = type_struct_get_fields(t))) break; LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry ) { - if (!var->type) continue; - align = type_buffer_alignment( var->type ); + if (!var->declspec.type) continue; + align = type_buffer_alignment( var->declspec.type ); if (max < align) max = align; } break; @@ -2036,8 +2299,8 @@ static unsigned int type_buffer_alignment(const type_t *t) if (!(fields = type_encapsulated_union_get_fields(t))) break; LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry ) { - if (!var->type) continue; - align = type_buffer_alignment( var->type ); + if (!var->declspec.type) continue; + align = type_buffer_alignment( var->declspec.type ); if (max < align) max = align; } break; @@ -2045,14 +2308,14 @@ static unsigned int type_buffer_alignment(const type_t *t) if (!(fields = type_union_get_cases(t))) break; LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry ) { - if (!var->type) continue; - align = type_buffer_alignment( var->type ); + if (!var->declspec.type) continue; + align = type_buffer_alignment( var->declspec.type ); if (max < align) max = align; } break; case TYPE_ARRAY: if (!type_array_is_decl_as_ptr(t)) - return type_buffer_alignment( type_array_get_element(t) ); + return type_buffer_alignment( type_array_get_element_type(t) ); /* else fall through */ case TYPE_POINTER: return 4; @@ -2063,6 +2326,11 @@ static unsigned int type_buffer_alignment(const type_t *t) case TYPE_MODULE: case TYPE_FUNCTION: case TYPE_BITFIELD: + case TYPE_APICONTRACT: + case TYPE_RUNTIMECLASS: + case TYPE_PARAMETERIZED_TYPE: + case TYPE_PARAMETER: + case TYPE_DELEGATE: /* these types should not be encountered here due to language * restrictions (interface, void, coclass, module), logical * restrictions (alias - due to type_get_type call above) or @@ -2075,12 +2343,12 @@ static unsigned int type_buffer_alignment(const type_t *t) int is_full_pointer_function(const var_t *func) { const var_t *var; - if (type_has_full_pointer(type_function_get_rettype(func->type), func->attrs, TRUE)) + if (type_has_full_pointer(type_function_get_rettype(func->declspec.type), func->attrs, TRUE, TRUE)) return TRUE; - if (!type_get_function_args(func->type)) + if (!type_function_get_args(func->declspec.type)) return FALSE; - LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) - if (type_has_full_pointer( var->type, var->attrs, TRUE )) + LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry ) + if (type_has_full_pointer( var->declspec.type, var->attrs, TRUE, TRUE )) return TRUE; return FALSE; } @@ -2099,7 +2367,7 @@ void write_full_pointer_free(FILE *file, int indent, const var_t *func) } static unsigned int write_nonsimple_pointer(FILE *file, const attr_list_t *attrs, - const type_t *type, + int toplevel_attrs, const type_t *type, enum type_context context, unsigned int offset, unsigned int *typeformat_offset) @@ -2110,7 +2378,7 @@ static unsigned int write_nonsimple_pointer(FILE *file, const attr_list_t *attrs int pointer_type; unsigned char flags = 0; - pointer_type = get_pointer_fc_context(type, attrs, context); + pointer_type = get_pointer_fc_context(type, attrs, toplevel_attrs, context); in_attr = is_attr(attrs, ATTR_IN); out_attr = is_attr(attrs, ATTR_OUT); @@ -2118,19 +2386,20 @@ static unsigned int write_nonsimple_pointer(FILE *file, const attr_list_t *attrs if (!is_interpreted_func(current_iface, current_func)) { - if (out_attr && !in_attr && pointer_type == FC_RP) + if (context == TYPE_CONTEXT_TOPLEVELPARAM && out_attr && !in_attr && pointer_type == FC_RP) flags |= FC_ALLOCED_ON_STACK; } - else if (get_stub_mode() == MODE_Oif) + else { if (context == TYPE_CONTEXT_TOPLEVELPARAM && is_ptr(type) && pointer_type == FC_RP) { - switch (typegen_detect_type(type_pointer_get_ref(type), NULL, TDT_ALL_TYPES)) + switch (typegen_detect_type(type_pointer_get_ref_type(type), attrs, TDT_ALL_TYPES)) { case TGT_STRING: case TGT_POINTER: case TGT_CTXT_HANDLE: case TGT_CTXT_HANDLE_POINTER: + case TGT_ARRAY: flags |= FC_ALLOCED_ON_STACK; break; case TGT_IFACE_POINTER: @@ -2145,7 +2414,7 @@ static unsigned int write_nonsimple_pointer(FILE *file, const attr_list_t *attrs if (is_ptr(type)) { - type_t *ref = type_pointer_get_ref(type); + type_t *ref = type_pointer_get_ref_type(type); if(is_declptr(ref) && !is_user_type(ref)) flags |= FC_POINTER_DEREF; if (pointer_type != FC_RP) { @@ -2176,7 +2445,7 @@ static unsigned int write_nonsimple_pointer(FILE *file, const attr_list_t *attrs return start_offset; } -static unsigned int write_simple_pointer(FILE *file, const attr_list_t *attrs, +static unsigned int write_simple_pointer(FILE *file, const attr_list_t *attrs, int toplevel_attrs, const type_t *type, enum type_context context) { unsigned char fc; @@ -2191,9 +2460,9 @@ static unsigned int write_simple_pointer(FILE *file, const attr_list_t *attrs, if (is_string_type(attrs, type)) error("write_simple_pointer: can't handle type %s which is a string type\n", type->name); - pointer_fc = get_pointer_fc_context(type, attrs, context); + pointer_fc = get_pointer_fc_context(type, attrs, toplevel_attrs, context); - ref = type_pointer_get_ref(type); + ref = type_pointer_get_ref_type(type); if (type_get_type(ref) == TYPE_ENUM) fc = get_enum_fc(ref); else @@ -2201,10 +2470,10 @@ static unsigned int write_simple_pointer(FILE *file, const attr_list_t *attrs, if (!is_interpreted_func(current_iface, current_func)) { - if (out_attr && !in_attr && pointer_fc == FC_RP) + if (context == TYPE_CONTEXT_TOPLEVELPARAM && out_attr && !in_attr && pointer_fc == FC_RP) flags |= FC_ALLOCED_ON_STACK; } - else if (get_stub_mode() == MODE_Oif) + else { if (context == TYPE_CONTEXT_TOPLEVELPARAM && fc == FC_ENUM16 && pointer_fc == FC_RP) flags |= FC_ALLOCED_ON_STACK; @@ -2220,18 +2489,19 @@ static unsigned int write_simple_pointer(FILE *file, const attr_list_t *attrs, static void print_start_tfs_comment(FILE *file, type_t *t, unsigned int tfsoff) { + const decl_spec_t ds = {.type = t}; print_file(file, 0, "/* %u (", tfsoff); - write_type_decl(file, t, NULL); + write_type_decl(file, &ds, NULL); print_file(file, 0, ") */\n"); } -static unsigned int write_pointer_tfs(FILE *file, const attr_list_t *attrs, +static unsigned int write_pointer_tfs(FILE *file, const attr_list_t *attrs, int toplevel_attrs, type_t *type, unsigned int ref_offset, enum type_context context, unsigned int *typestring_offset) { unsigned int offset = *typestring_offset; - type_t *ref = type_pointer_get_ref(type); + type_t *ref = type_pointer_get_ref_type(type); print_start_tfs_comment(file, type, offset); update_tfsoff(type, offset, file); @@ -2240,11 +2510,11 @@ static unsigned int write_pointer_tfs(FILE *file, const attr_list_t *attrs, { case TGT_BASIC: case TGT_ENUM: - *typestring_offset += write_simple_pointer(file, attrs, type, context); + *typestring_offset += write_simple_pointer(file, attrs, toplevel_attrs, type, context); break; default: if (ref_offset) - write_nonsimple_pointer(file, attrs, type, context, ref_offset, typestring_offset); + write_nonsimple_pointer(file, attrs, toplevel_attrs, type, context, ref_offset, typestring_offset); break; } @@ -2312,13 +2582,13 @@ static unsigned int write_user_tfs(FILE *file, type_t *type, unsigned int *tfsof else { if (!processed(utype)) - write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff); + write_type_tfs(file, NULL, FALSE, utype, utype->name, TYPE_CONTEXT_CONTAINER, tfsoff); absoff = utype->typestring_offset; } - if (type_get_type(utype) == TYPE_POINTER && get_pointer_fc(utype, NULL, FALSE) == FC_RP) + if (type_get_type(utype) == TYPE_POINTER && get_pointer_fc(utype, NULL, FALSE, FALSE) == FC_RP) flags = 0x40; - else if (type_get_type(utype) == TYPE_POINTER && get_pointer_fc(utype, NULL, FALSE) == FC_UP) + else if (type_get_type(utype) == TYPE_POINTER && get_pointer_fc(utype, NULL, FALSE, FALSE) == FC_UP) flags = 0x80; else flags = 0; @@ -2344,7 +2614,7 @@ static void write_member_type(FILE *file, const type_t *cont, const type_t *type, unsigned int *corroff, unsigned int *tfsoff) { - if (is_embedded_complex(type) && !is_conformant_array(type)) + if (is_embedded_complex(type, attrs) && !is_conformant_array(type)) { unsigned int absoff; short reloff; @@ -2352,7 +2622,7 @@ static void write_member_type(FILE *file, const type_t *cont, if (type_get_type(type) == TYPE_UNION && is_attr(attrs, ATTR_SWITCHIS)) { absoff = *corroff; - *corroff += 8; + *corroff += interpreted_mode ? 10 : 8; } else { @@ -2382,31 +2652,31 @@ static void write_member_type(FILE *file, const type_t *cont, static void write_array_element_type(FILE *file, const attr_list_t *attrs, const type_t *type, int cont_is_complex, unsigned int *tfsoff) { - type_t *elem = type_array_get_element(type); + type_t *elem = type_array_get_element_type(type); - if (!is_embedded_complex(elem) && is_ptr(elem)) + if (!is_embedded_complex(elem, attrs) && is_ptr(elem)) { - type_t *ref = type_pointer_get_ref(elem); + type_t *ref = type_pointer_get_ref_type(elem); if (processed(ref)) { - write_nonsimple_pointer(file, NULL, elem, TYPE_CONTEXT_CONTAINER, + write_nonsimple_pointer(file, attrs, FALSE, elem, TYPE_CONTEXT_CONTAINER, ref->typestring_offset, tfsoff); return; } if (cont_is_complex && is_string_type(attrs, elem)) { - write_string_tfs(file, NULL, elem, TYPE_CONTEXT_CONTAINER, NULL, tfsoff); + write_string_tfs(file, attrs, FALSE, elem, TYPE_CONTEXT_CONTAINER, NULL, tfsoff); return; } - if (!is_string_type(NULL, elem) && + if (!is_string_type(attrs, elem) && (type_get_type(ref) == TYPE_BASIC || type_get_type(ref) == TYPE_ENUM)) { - *tfsoff += write_simple_pointer(file, NULL, elem, TYPE_CONTEXT_CONTAINER); + *tfsoff += write_simple_pointer(file, attrs, FALSE, elem, TYPE_CONTEXT_CONTAINER); return; } } - write_member_type(file, type, cont_is_complex, NULL, elem, NULL, tfsoff); + write_member_type(file, type, cont_is_complex, attrs, elem, NULL, tfsoff); } static void write_end(FILE *file, unsigned int *tfsoff) @@ -2428,36 +2698,43 @@ static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff) if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry) { - type_t *ft = f->type; + type_t *ft = f->declspec.type; unsigned int size = field_memsize( ft, &offset ); if (type_get_type(ft) == TYPE_UNION && is_attr(f->attrs, ATTR_SWITCHIS)) { short reloff; unsigned int absoff = ft->typestring_offset; + unsigned char fc; + const expr_t *switch_is = get_attrp(f->attrs, ATTR_SWITCHIS); + struct expr_loc expr_loc = { .v = f }; + + fc = get_correlation_type( expr_resolve_type( &expr_loc, current_structure, switch_is )); + if (!fc) fc = FC_LONG; + if (is_attr(ft->attrs, ATTR_SWITCHTYPE)) - absoff += 8; /* we already have a corr descr, skip it */ - reloff = absoff - (*tfsoff + 6); + absoff += interpreted_mode ? 10 : 8; /* we already have a corr descr, skip it */ print_file(file, 0, "/* %d */\n", *tfsoff); print_file(file, 2, "0x%x,\t/* FC_NON_ENCAPSULATED_UNION */\n", FC_NON_ENCAPSULATED_UNION); - print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", FC_LONG); - write_conf_or_var_desc(file, current_structure, offset, ft, - get_attrp(f->attrs, ATTR_SWITCHIS)); + print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc)); + + *tfsoff += 2 + write_conf_or_var_desc(file, current_structure, offset, ft, switch_is, 0); + reloff = absoff - *tfsoff; print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", (unsigned short)reloff, reloff, absoff); - *tfsoff += 8; + *tfsoff += 2; } offset += size; } } static int write_pointer_description_offsets( - FILE *file, const attr_list_t *attrs, type_t *type, + FILE *file, const attr_list_t *attrs, int toplevel_attrs, type_t *type, unsigned int *offset_in_memory, unsigned int *offset_in_buffer, unsigned int *typestring_offset) { int written = 0; - if ((is_ptr(type) && type_get_type(type_pointer_get_ref(type)) != TYPE_INTERFACE) || + if ((is_ptr(type) && type_get_type(type_pointer_get_ref_type(type)) != TYPE_INTERFACE) || (is_array(type) && type_array_is_decl_as_ptr(type))) { if (offset_in_memory && offset_in_buffer) @@ -2482,15 +2759,15 @@ static int write_pointer_description_offsets( if (is_ptr(type)) { - type_t *ref = type_pointer_get_ref(type); + type_t *ref = type_pointer_get_ref_type(type); if (is_string_type(attrs, type)) - write_string_tfs(file, attrs, type, TYPE_CONTEXT_CONTAINER, NULL, typestring_offset); + write_string_tfs(file, attrs, toplevel_attrs, type, TYPE_CONTEXT_CONTAINER, NULL, typestring_offset); else if (processed(ref)) - write_nonsimple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER, + write_nonsimple_pointer(file, attrs, toplevel_attrs, type, TYPE_CONTEXT_CONTAINER, ref->typestring_offset, typestring_offset); else if (type_get_type(ref) == TYPE_BASIC || type_get_type(ref) == TYPE_ENUM) - *typestring_offset += write_simple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER); + *typestring_offset += write_simple_pointer(file, attrs, toplevel_attrs, type, TYPE_CONTEXT_CONTAINER); else error("write_pointer_description_offsets: type format string unknown\n"); } @@ -2501,7 +2778,8 @@ static int write_pointer_description_offsets( * pointer has to be written in-place here */ if (is_string_type(attrs, type)) offset += 4; - write_nonsimple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER, offset, typestring_offset); + write_nonsimple_pointer(file, attrs, toplevel_attrs, type, + TYPE_CONTEXT_CONTAINER, offset, typestring_offset); } return 1; @@ -2510,7 +2788,7 @@ static int write_pointer_description_offsets( if (is_array(type)) { return write_pointer_description_offsets( - file, attrs, type_array_get_element(type), offset_in_memory, + file, attrs, FALSE, type_array_get_element_type(type), offset_in_memory, offset_in_buffer, typestring_offset); } else if (is_non_complex_struct(type)) @@ -2523,13 +2801,13 @@ static int write_pointer_description_offsets( { unsigned int padding; unsigned int align = 0; - type_memsize_and_alignment(v->type, &align); + type_memsize_and_alignment(v->declspec.type, &align); padding = ROUNDING(*offset_in_memory, align); *offset_in_memory += padding; *offset_in_buffer += padding; } written += write_pointer_description_offsets( - file, v->attrs, v->type, offset_in_memory, offset_in_buffer, + file, v->attrs, TRUE, v->declspec.type, offset_in_memory, offset_in_buffer, typestring_offset); } } @@ -2549,7 +2827,7 @@ static int write_pointer_description_offsets( } static int write_no_repeat_pointer_descriptions( - FILE *file, const attr_list_t *attrs, type_t *type, + FILE *file, const attr_list_t *attrs, int toplevel_attrs, type_t *type, unsigned int *offset_in_memory, unsigned int *offset_in_buffer, unsigned int *typestring_offset) { @@ -2562,7 +2840,7 @@ static int write_no_repeat_pointer_descriptions( print_file(file, 2, "0x%02x, /* FC_PAD */\n", FC_PAD); *typestring_offset += 2; - return write_pointer_description_offsets(file, attrs, type, + return write_pointer_description_offsets(file, attrs, toplevel_attrs, type, offset_in_memory, offset_in_buffer, typestring_offset); } @@ -2575,13 +2853,13 @@ static int write_no_repeat_pointer_descriptions( { unsigned int padding; unsigned int align = 0; - type_memsize_and_alignment(v->type, &align); + type_memsize_and_alignment(v->declspec.type, &align); padding = ROUNDING(*offset_in_memory, align); *offset_in_memory += padding; *offset_in_buffer += padding; } written += write_no_repeat_pointer_descriptions( - file, v->attrs, v->type, + file, v->attrs, TRUE, v->declspec.type, offset_in_memory, offset_in_buffer, typestring_offset); } } @@ -2600,7 +2878,7 @@ static int write_no_repeat_pointer_descriptions( /* Note: if file is NULL return value is number of pointers to write, else * it is the number of type format characters written */ static int write_fixed_array_pointer_descriptions( - FILE *file, const attr_list_t *attrs, type_t *type, + FILE *file, const attr_list_t *attrs, int toplevel_attrs, type_t *type, unsigned int *offset_in_memory, unsigned int *offset_in_buffer, unsigned int *typestring_offset) { @@ -2613,14 +2891,14 @@ static int write_fixed_array_pointer_descriptions( /* unfortunately, this needs to be done in two passes to avoid * writing out redundant FC_FIXED_REPEAT descriptions */ pointer_count = write_pointer_description_offsets( - NULL, attrs, type_array_get_element(type), NULL, NULL, &temp); + NULL, attrs, FALSE, type_array_get_element_type(type), NULL, NULL, &temp); if (pointer_count > 0) { unsigned int increment_size; unsigned int offset_of_array_pointer_mem = 0; unsigned int offset_of_array_pointer_buf = 0; - increment_size = type_memsize(type_array_get_element(type)); + increment_size = type_memsize(type_array_get_element_type(type)); print_file(file, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", FC_FIXED_REPEAT); print_file(file, 2, "0x%02x, /* FC_PAD */\n", FC_PAD); @@ -2631,7 +2909,7 @@ static int write_fixed_array_pointer_descriptions( *typestring_offset += 10; pointer_count = write_pointer_description_offsets( - file, attrs, type, &offset_of_array_pointer_mem, + file, attrs, toplevel_attrs, type, &offset_of_array_pointer_mem, &offset_of_array_pointer_buf, typestring_offset); } } @@ -2644,13 +2922,13 @@ static int write_fixed_array_pointer_descriptions( { unsigned int padding; unsigned int align = 0; - type_memsize_and_alignment(v->type, &align); + type_memsize_and_alignment(v->declspec.type, &align); padding = ROUNDING(*offset_in_memory, align); *offset_in_memory += padding; *offset_in_buffer += padding; } pointer_count += write_fixed_array_pointer_descriptions( - file, v->attrs, v->type, offset_in_memory, offset_in_buffer, + file, v->attrs, TRUE, v->declspec.type, offset_in_memory, offset_in_buffer, typestring_offset); } } @@ -2684,14 +2962,14 @@ static int write_conformant_array_pointer_descriptions( /* unfortunately, this needs to be done in two passes to avoid * writing out redundant FC_VARIABLE_REPEAT descriptions */ pointer_count = write_pointer_description_offsets( - NULL, attrs, type_array_get_element(type), NULL, NULL, &temp); + NULL, attrs, FALSE, type_array_get_element_type(type), NULL, NULL, &temp); if (pointer_count > 0) { unsigned int increment_size; unsigned int offset_of_array_pointer_mem = offset_in_memory; unsigned int offset_of_array_pointer_buf = offset_in_memory; - increment_size = type_memsize(type_array_get_element(type)); + increment_size = type_memsize(type_array_get_element_type(type)); if (increment_size > USHRT_MAX) error("array size of %u bytes is too large\n", increment_size); @@ -2704,7 +2982,7 @@ static int write_conformant_array_pointer_descriptions( *typestring_offset += 8; pointer_count = write_pointer_description_offsets( - file, attrs, type_array_get_element(type), + file, attrs, FALSE, type_array_get_element_type(type), &offset_of_array_pointer_mem, &offset_of_array_pointer_buf, typestring_offset); } @@ -2728,12 +3006,12 @@ static int write_varying_array_pointer_descriptions( /* unfortunately, this needs to be done in two passes to avoid * writing out redundant FC_VARIABLE_REPEAT descriptions */ pointer_count = write_pointer_description_offsets( - NULL, attrs, type_array_get_element(type), NULL, NULL, &temp); + NULL, attrs, FALSE, type_array_get_element_type(type), NULL, NULL, &temp); if (pointer_count > 0) { unsigned int increment_size; - increment_size = type_memsize(type_array_get_element(type)); + increment_size = type_memsize(type_array_get_element_type(type)); if (increment_size > USHRT_MAX) error("array size of %u bytes is too large\n", increment_size); @@ -2746,7 +3024,7 @@ static int write_varying_array_pointer_descriptions( *typestring_offset += 8; pointer_count = write_pointer_description_offsets( - file, attrs, type_array_get_element(type), offset_in_memory, + file, attrs, FALSE, type_array_get_element_type(type), offset_in_memory, offset_in_buffer, typestring_offset); } } @@ -2759,20 +3037,20 @@ static int write_varying_array_pointer_descriptions( { unsigned int align = 0, padding; - if (is_array(v->type) && type_array_has_variance(v->type)) + if (is_array(v->declspec.type) && type_array_has_variance(v->declspec.type)) { *offset_in_buffer = ROUND_SIZE(*offset_in_buffer, 4); /* skip over variance and offset in buffer */ *offset_in_buffer += 8; } - type_memsize_and_alignment(v->type, &align); + type_memsize_and_alignment(v->declspec.type, &align); padding = ROUNDING(*offset_in_memory, align); *offset_in_memory += padding; *offset_in_buffer += padding; } pointer_count += write_varying_array_pointer_descriptions( - file, v->attrs, v->type, offset_in_memory, offset_in_buffer, + file, v->attrs, v->declspec.type, offset_in_memory, offset_in_buffer, typestring_offset); } } @@ -2791,7 +3069,7 @@ static int write_varying_array_pointer_descriptions( return pointer_count; } -static void write_pointer_description(FILE *file, const attr_list_t *attrs, type_t *type, +static void write_pointer_description(FILE *file, const attr_list_t *attrs, int toplevel_attrs, type_t *type, unsigned int *typestring_offset) { unsigned int offset_in_buffer; @@ -2804,7 +3082,7 @@ static void write_pointer_description(FILE *file, const attr_list_t *attrs, type offset_in_memory = 0; offset_in_buffer = 0; write_no_repeat_pointer_descriptions( - file, NULL, type, + file, attrs, toplevel_attrs, type, &offset_in_memory, &offset_in_buffer, typestring_offset); } @@ -2812,7 +3090,7 @@ static void write_pointer_description(FILE *file, const attr_list_t *attrs, type offset_in_memory = 0; offset_in_buffer = 0; write_fixed_array_pointer_descriptions( - file, NULL, type, + file, attrs, toplevel_attrs, type, &offset_in_memory, &offset_in_buffer, typestring_offset); /* pass 3: search for pointers in conformant only arrays (but don't descend @@ -2824,7 +3102,7 @@ static void write_pointer_description(FILE *file, const attr_list_t *attrs, type else if (type_get_type(type) == TYPE_STRUCT && get_struct_fc(type) == FC_CPSTRUCT) { - type_t *carray = find_array_or_string_in_struct(type)->type; + type_t *carray = find_array_or_string_in_struct(type)->declspec.type; write_conformant_array_pointer_descriptions( file, NULL, carray, type_memsize(type), typestring_offset); } @@ -2837,7 +3115,7 @@ static void write_pointer_description(FILE *file, const attr_list_t *attrs, type &offset_in_memory, &offset_in_buffer, typestring_offset); } -static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs, +static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs, int toplevel_attrs, type_t *type, enum type_context context, const char *name, unsigned int *typestring_offset) { @@ -2851,7 +3129,7 @@ static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs, if (is_declptr(type)) { unsigned char flag = is_conformant_array(type) ? 0 : FC_SIMPLE_POINTER; - int pointer_type = get_pointer_fc_context(type, attrs, context); + int pointer_type = get_pointer_fc_context(type, attrs, toplevel_attrs, context); if (!pointer_type) pointer_type = FC_RP; print_start_tfs_comment(file, type, *typestring_offset); @@ -2868,12 +3146,15 @@ static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs, } if (is_array(type)) - elem_type = type_array_get_element(type); + elem_type = type_array_get_element_type(type); else - elem_type = type_pointer_get_ref(type); + elem_type = type_pointer_get_ref_type(type); if (type_get_type(elem_type) == TYPE_POINTER && is_array(type)) - return write_array_tfs(file, attrs, type, name, typestring_offset); + { + write_array_tfs(file, attrs, toplevel_attrs, type, name, typestring_offset); + return start_offset; + } if (type_get_type(elem_type) != TYPE_BASIC) { @@ -2926,7 +3207,7 @@ static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs, (!type_array_is_decl_as_ptr(type) && current_structure ? type_memsize(current_structure) : 0), - type, type_array_get_conformance(type)); + type, type_array_get_conformance(type), 0); update_tfsoff(type, start_offset, file); return start_offset; @@ -2947,7 +3228,7 @@ static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs, } } -static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type, +static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, int toplevel_attrs, type_t *type, const char *name, unsigned int *typestring_offset) { const expr_t *length_is = type_array_get_variance(type); @@ -2956,21 +3237,18 @@ static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t unsigned int size; unsigned int start_offset; unsigned char fc; - int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE); unsigned int baseoff = !type_array_is_decl_as_ptr(type) && current_structure ? type_memsize(current_structure) : 0; - if (!pointer_type) - pointer_type = FC_RP; + if (!is_string_type(attrs, type_array_get_element_type(type))) + write_type_tfs(file, attrs, FALSE, type_array_get_element_type(type), + name, TYPE_CONTEXT_CONTAINER_NO_POINTERS, typestring_offset); - if (!is_string_type(attrs, type_array_get_element(type))) - write_embedded_types(file, attrs, type_array_get_element(type), name, FALSE, typestring_offset); - - size = type_memsize(is_conformant_array(type) ? type_array_get_element(type) : type); - align = type_buffer_alignment(is_conformant_array(type) ? type_array_get_element(type) : type); - fc = get_array_fc(type); + size = type_memsize(is_conformant_array(type) ? type_array_get_element_type(type) : type); + align = type_buffer_alignment(is_conformant_array(type) ? type_array_get_element_type(type) : type); + fc = get_array_fc(type, attrs); start_offset = *typestring_offset; update_tfsoff(type, start_offset, file); @@ -2996,11 +3274,11 @@ static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t if (is_conformant_array(type)) *typestring_offset += write_conf_or_var_desc(file, current_structure, baseoff, - type, size_is); + type, size_is, 0); if (fc == FC_SMVARRAY || fc == FC_LGVARRAY) { - unsigned int elsize = type_memsize(type_array_get_element(type)); + unsigned int elsize = type_memsize(type_array_get_element_type(type)); unsigned int dim = type_array_get_dim(type); if (fc == FC_LGVARRAY) @@ -3020,21 +3298,20 @@ static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t if (length_is) *typestring_offset - += write_conf_or_var_desc(file, current_structure, baseoff, - type, length_is); + += write_conf_or_var_desc(file, current_structure, baseoff, type, length_is, 0); - if (type_has_pointers(type_array_get_element(type)) && + if (type_has_pointers(type_array_get_element_type(type), attrs) && (type_array_is_decl_as_ptr(type) || !current_structure)) { print_file(file, 2, "0x%x,\t/* FC_PP */\n", FC_PP); print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD); *typestring_offset += 2; - write_pointer_description(file, is_string_type(attrs, type) ? attrs : NULL, type, typestring_offset); + write_pointer_description(file, attrs, toplevel_attrs, type, typestring_offset); print_file(file, 2, "0x%x,\t/* FC_END */\n", FC_END); *typestring_offset += 1; } - write_array_element_type(file, is_string_type(attrs, type) ? attrs : NULL, type, FALSE, typestring_offset); + write_array_element_type(file, attrs, type, FALSE, typestring_offset); write_end(file, typestring_offset); } else @@ -3042,14 +3319,10 @@ static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t unsigned int dim = size_is ? 0 : type_array_get_dim(type); print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)dim, dim); *typestring_offset += 2; - *typestring_offset - += write_conf_or_var_desc(file, current_structure, baseoff, - type, size_is); - *typestring_offset - += write_conf_or_var_desc(file, current_structure, baseoff, - type, length_is); + *typestring_offset += write_conf_or_var_desc(file, current_structure, baseoff, type, size_is, 0); + *typestring_offset += write_conf_or_var_desc(file, current_structure, baseoff, type, length_is, 0); - write_array_element_type(file, is_string_type(attrs, type) ? attrs : NULL, type, TRUE, typestring_offset); + write_array_element_type(file, attrs, type, TRUE, typestring_offset); write_end(file, typestring_offset); } @@ -3066,7 +3339,7 @@ static const var_t *find_array_or_string_in_struct(const type_t *type) return NULL; last_field = LIST_ENTRY( list_tail(fields), const var_t, entry ); - ft = last_field->type; + ft = last_field->declspec.type; if (is_conformant_array(ft) && !type_array_is_decl_as_ptr(ft)) return last_field; @@ -3089,7 +3362,7 @@ static void write_struct_members(FILE *file, const type_t *type, if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) { - type_t *ft = field->type; + type_t *ft = field->declspec.type; unsigned int align = 0; unsigned int size = type_memsize_and_alignment(ft, &align); align = clamp_align(align); @@ -3097,28 +3370,15 @@ static void write_struct_members(FILE *file, const type_t *type, if (!is_conformant_array(ft) || type_array_is_decl_as_ptr(ft)) { - if ((align - 1) & offset) + unsigned short aligned = ROUND_SIZE(offset, align); + if (aligned > offset) { - unsigned char fc = 0; - switch (align) - { - case 2: - fc = FC_ALIGNM2; - break; - case 4: - fc = FC_ALIGNM4; - break; - case 8: - fc = FC_ALIGNM8; - break; - default: - error("write_struct_members: cannot align type %d\n", type_get_type(ft)); - } + unsigned char fc = FC_STRUCTPAD1 + (aligned - offset) - 1; print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc)); - offset = ROUND_SIZE(offset, align); + offset = aligned; *typestring_offset += 1; } - write_member_type(file, type, is_complex, field->attrs, field->type, corroff, + write_member_type(file, type, is_complex, field->attrs, field->declspec.type, corroff, typestring_offset); offset += size; } @@ -3136,7 +3396,7 @@ static void write_struct_members(FILE *file, const type_t *type, write_end(file, typestring_offset); } -static unsigned int write_struct_tfs(FILE *file, type_t *type, +static unsigned int write_struct_tfs(FILE *file, type_t *type, const attr_list_t *attrs, const char *name, unsigned int *tfsoff) { const type_t *save_current_structure = current_structure; @@ -3161,15 +3421,15 @@ static unsigned int write_struct_tfs(FILE *file, type_t *type, name, USHRT_MAX, total_size - USHRT_MAX); if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry) - write_embedded_types(file, f->attrs, f->type, f->name, FALSE, tfsoff); + write_type_tfs(file, f->attrs, TRUE, f->declspec.type, f->name, TYPE_CONTEXT_CONTAINER_NO_POINTERS, tfsoff); array = find_array_or_string_in_struct(type); - if (array && !processed(array->type)) + if (array && !processed(array->declspec.type)) { - if(is_string_type(array->attrs, array->type)) - write_string_tfs(file, array->attrs, array->type, TYPE_CONTEXT_CONTAINER, array->name, tfsoff); + if(is_string_type(array->attrs, array->declspec.type)) + write_string_tfs(file, array->attrs, TRUE, array->declspec.type, TYPE_CONTEXT_CONTAINER, array->name, tfsoff); else - write_array_tfs(file, array->attrs, array->type, array->name, tfsoff); + write_array_tfs(file, array->attrs, TRUE, array->declspec.type, array->name, tfsoff); } corroff = *tfsoff; @@ -3185,7 +3445,7 @@ static unsigned int write_struct_tfs(FILE *file, type_t *type, if (array) { - unsigned int absoff = array->type->typestring_offset; + unsigned int absoff = array->declspec.type->typestring_offset; short reloff = absoff - *tfsoff; print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", reloff, reloff, absoff); @@ -3211,12 +3471,12 @@ static unsigned int write_struct_tfs(FILE *file, type_t *type, } else if ((fc == FC_PSTRUCT) || (fc == FC_CPSTRUCT) || - (fc == FC_CVSTRUCT && type_has_pointers(type))) + (fc == FC_CVSTRUCT && type_has_pointers(type, attrs))) { print_file(file, 2, "0x%x,\t/* FC_PP */\n", FC_PP); print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD); *tfsoff += 2; - write_pointer_description(file, NULL, type, tfsoff); + write_pointer_description(file, NULL, FALSE, type, tfsoff); print_file(file, 2, "0x%x,\t/* FC_END */\n", FC_END); *tfsoff += 1; } @@ -3231,15 +3491,15 @@ static unsigned int write_struct_tfs(FILE *file, type_t *type, type->ptrdesc = *tfsoff; if (fields) LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry) { - type_t *ft = f->type; + type_t *ft = f->declspec.type; switch (typegen_detect_type(ft, f->attrs, TDT_IGNORE_STRINGS)) { case TGT_POINTER: if (is_string_type(f->attrs, ft)) - write_string_tfs(file, f->attrs, ft, TYPE_CONTEXT_CONTAINER, f->name, tfsoff); + write_string_tfs(file, f->attrs, TRUE, ft, TYPE_CONTEXT_CONTAINER, f->name, tfsoff); else - write_pointer_tfs(file, f->attrs, ft, - type_pointer_get_ref(ft)->typestring_offset, + write_pointer_tfs(file, f->attrs, TRUE, ft, + type_pointer_get_ref_type(ft)->typestring_offset, TYPE_CONTEXT_CONTAINER, tfsoff); break; case TGT_ARRAY: @@ -3254,7 +3514,7 @@ static unsigned int write_struct_tfs(FILE *file, type_t *type, * pointer has to be written in-place here */ if (is_string_type(f->attrs, ft)) offset += 4; - write_nonsimple_pointer(file, f->attrs, ft, TYPE_CONTEXT_CONTAINER, offset, tfsoff); + write_nonsimple_pointer(file, f->attrs, TRUE, ft, TYPE_CONTEXT_CONTAINER, offset, tfsoff); } break; default: @@ -3327,8 +3587,8 @@ static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs, expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE); if (cases) nbranch += list_count(cases); - if (f->type) - write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff); + if (f->declspec.type) + write_type_tfs(file, f->attrs, TRUE, f->declspec.type, f->name, TYPE_CONTEXT_CONTAINER, tfsoff); } start_offset = *tfsoff; @@ -3337,7 +3597,7 @@ static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs, if (type_get_type(type) == TYPE_ENCAPSULATED_UNION) { const var_t *sv = type_union_get_switch_value(type); - const type_t *st = sv->type; + const type_t *st = sv->declspec.type; unsigned int align = 0; unsigned char fc; @@ -3369,8 +3629,8 @@ static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs, type_memsize_and_alignment(st, &align); if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry) { - if (f->type) - type_memsize_and_alignment(f->type, &align); + if (f->declspec.type) + type_memsize_and_alignment(f->declspec.type, &align); } print_file(file, 2, "0x%x,\t/* FC_ENCAPSULATED_UNION */\n", FC_ENCAPSULATED_UNION); @@ -3413,7 +3673,7 @@ static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs, print_file(file, 2, "0x%x,\t/* Switch type= %s */\n", fc, string_of_type(fc)); *tfsoff += 2; - *tfsoff += write_conf_or_var_desc(file, current_structure, 0, st, switch_is ); + *tfsoff += write_conf_or_var_desc(file, current_structure, 0, st, switch_is, 0); print_file(file, 2, "NdrFcShort(0x2),\t/* Offset= 2 (%u) */\n", *tfsoff + 2); *tfsoff += 2; print_file(file, 0, "/* %u */\n", *tfsoff); @@ -3425,7 +3685,7 @@ static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs, if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry) { - type_t *ft = f->type; + type_t *ft = f->declspec.type; expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE); int deflt = is_attr(f->attrs, ATTR_DEFAULT); expr_t *c; @@ -3482,13 +3742,13 @@ static unsigned int write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *t { print_file(file, 2, "0x2f, /* FC_IP */\n"); print_file(file, 2, "0x5c, /* FC_PAD */\n"); - *typeformat_offset - += write_conf_or_var_desc(file, current_structure, 0, type, iid) + 2; + *typeformat_offset += 2 + write_conf_or_var_desc(file, current_structure, 0, + type, iid, RobustIsIIdIs); } else { - const type_t *base = is_ptr(type) ? type_pointer_get_ref(type) : type; - const UUID *uuid = get_attrp(base->attrs, ATTR_UUID); + const type_t *base = is_ptr(type) ? type_pointer_get_ref_type(type) : type; + const struct uuid *uuid = get_attrp(base->attrs, ATTR_UUID); if (! uuid) error("%s: interface %s missing UUID\n", __FUNCTION__, base->name); @@ -3512,17 +3772,17 @@ static unsigned int write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *t static unsigned int write_contexthandle_tfs(FILE *file, const attr_list_t *attrs, type_t *type, - int toplevel_param, + enum type_context context, unsigned int *typeformat_offset) { unsigned int start_offset = *typeformat_offset; - unsigned char flags = get_contexthandle_flags( current_iface, attrs, type ); + unsigned char flags = get_contexthandle_flags( current_iface, attrs, type, context == TYPE_CONTEXT_RETVAL ); print_start_tfs_comment(file, type, start_offset); if (flags & 0x80) /* via ptr */ { - int pointer_type = get_pointer_fc( type, attrs, toplevel_param ); + int pointer_type = get_pointer_fc( type, attrs, TRUE, context == TYPE_CONTEXT_TOPLEVELPARAM ); if (!pointer_type) pointer_type = FC_RP; *typeformat_offset += 4; print_file(file, 2,"0x%x, 0x0,\t/* %s */\n", pointer_type, string_of_type(pointer_type) ); @@ -3532,8 +3792,7 @@ static unsigned int write_contexthandle_tfs(FILE *file, print_file(file, 2, "0x%02x,\t/* FC_BIND_CONTEXT */\n", FC_BIND_CONTEXT); print_file(file, 2, "0x%x,\t/* Context flags: ", flags); - /* return and can't be null values overlap */ - if (((flags & 0x21) != 0x21) && (flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL)) + if (flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL) print_file(file, 0, "can't be null, "); if (flags & NDR_CONTEXT_HANDLE_SERIALIZE) print_file(file, 0, "serialize, "); @@ -3541,13 +3800,13 @@ static unsigned int write_contexthandle_tfs(FILE *file, print_file(file, 0, "no serialize, "); if (flags & NDR_STRICT_CONTEXT_HANDLE) print_file(file, 0, "strict, "); - if ((flags & 0x21) == 0x20) - print_file(file, 0, "out, "); - if ((flags & 0x21) == 0x21) + if (flags & HANDLE_PARAM_IS_RETURN) print_file(file, 0, "return, "); - if (flags & 0x40) + if (flags & HANDLE_PARAM_IS_OUT) + print_file(file, 0, "out, "); + if (flags & HANDLE_PARAM_IS_IN) print_file(file, 0, "in, "); - if (flags & 0x80) + if (flags & HANDLE_PARAM_IS_VIA_PTR) print_file(file, 0, "via ptr, "); print_file(file, 0, "*/\n"); print_file(file, 2, "0x%x,\t/* rundown routine */\n", get_context_handle_offset( type )); @@ -3586,9 +3845,8 @@ static unsigned int write_range_tfs(FILE *file, const attr_list_t *attrs, return start_offset; } -static unsigned int write_type_tfs(FILE *file, int indent, - const attr_list_t *attrs, type_t *type, - const char *name, +static unsigned int write_type_tfs(FILE *file, const attr_list_t *attrs, int toplevel_attrs, + type_t *type, const char *name, enum type_context context, unsigned int *typeformat_offset) { @@ -3598,12 +3856,11 @@ static unsigned int write_type_tfs(FILE *file, int indent, { case TGT_CTXT_HANDLE: case TGT_CTXT_HANDLE_POINTER: - return write_contexthandle_tfs(file, attrs, type, - context == TYPE_CONTEXT_TOPLEVELPARAM, typeformat_offset); + return write_contexthandle_tfs(file, attrs, type, context, typeformat_offset); case TGT_USER_TYPE: return write_user_tfs(file, type, typeformat_offset); case TGT_STRING: - return write_string_tfs(file, attrs, type, context, name, typeformat_offset); + return write_string_tfs(file, attrs, toplevel_attrs, type, context, name, typeformat_offset); case TGT_ARRAY: { unsigned int off; @@ -3611,16 +3868,16 @@ static unsigned int write_type_tfs(FILE *file, int indent, if ((context != TYPE_CONTEXT_CONTAINER && context != TYPE_CONTEXT_CONTAINER_NO_POINTERS) || !is_conformant_array(type) || type_array_is_decl_as_ptr(type)) - off = write_array_tfs(file, attrs, type, name, typeformat_offset); + off = write_array_tfs(file, attrs, toplevel_attrs, type, name, typeformat_offset); else off = 0; if (context != TYPE_CONTEXT_CONTAINER && context != TYPE_CONTEXT_CONTAINER_NO_POINTERS) { int ptr_type; - ptr_type = get_pointer_fc(type, attrs, - context == TYPE_CONTEXT_TOPLEVELPARAM); - if (ptr_type != FC_RP || type_array_is_decl_as_ptr(type)) + ptr_type = get_pointer_fc_context(type, attrs, toplevel_attrs, context); + if (type_array_is_decl_as_ptr(type) + || (ptr_type != FC_RP && context == TYPE_CONTEXT_TOPLEVELPARAM)) { unsigned int absoff = type->typestring_offset; short reloff = absoff - (*typeformat_offset + 2); @@ -3633,12 +3890,12 @@ static unsigned int write_type_tfs(FILE *file, int indent, if (ptr_type != FC_RP) update_tfsoff( type, off, file ); *typeformat_offset += 4; } - type->details.array.ptr_tfsoff = off; + type_array_set_ptr_tfsoff(type, off); } return off; } case TGT_STRUCT: - return write_struct_tfs(file, type, name, typeformat_offset); + return write_struct_tfs(file, type, attrs, name, typeformat_offset); case TGT_UNION: return write_union_tfs(file, attrs, type, typeformat_offset); case TGT_ENUM: @@ -3657,8 +3914,7 @@ static unsigned int write_type_tfs(FILE *file, int indent, case TGT_POINTER: { enum type_context ref_context; - unsigned int toplevel_offset = *typeformat_offset; - type_t *ref = type_pointer_get_ref(type); + type_t *ref = type_pointer_get_ref_type(type); if (context == TYPE_CONTEXT_TOPLEVELPARAM) ref_context = TYPE_CONTEXT_PARAM; @@ -3667,22 +3923,10 @@ static unsigned int write_type_tfs(FILE *file, int indent, else ref_context = context; - if (is_string_type(attrs, ref)) - { - if (context != TYPE_CONTEXT_CONTAINER_NO_POINTERS) - write_pointer_tfs(file, attrs, type, *typeformat_offset + 4, context, typeformat_offset); - - offset = write_type_tfs(file, indent, attrs, ref, name, ref_context, typeformat_offset); - if (context == TYPE_CONTEXT_CONTAINER_NO_POINTERS) - return 0; - return (context == TYPE_CONTEXT_TOPLEVELPARAM) ? toplevel_offset : offset; - } - - offset = write_type_tfs( file, indent, attrs, type_pointer_get_ref(type), name, - ref_context, typeformat_offset); + offset = write_type_tfs( file, attrs, FALSE, ref, name, ref_context, typeformat_offset); if (context == TYPE_CONTEXT_CONTAINER_NO_POINTERS) return 0; - return write_pointer_tfs(file, attrs, type, offset, context, typeformat_offset); + return write_pointer_tfs(file, attrs, toplevel_attrs, type, offset, context, typeformat_offset); } case TGT_INVALID: break; @@ -3691,12 +3935,6 @@ static unsigned int write_type_tfs(FILE *file, int indent, return 0; } -static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type, - const char *name, int write_ptr, unsigned int *tfsoff) -{ - return write_type_tfs(file, 2, attrs, type, name, write_ptr ? TYPE_CONTEXT_CONTAINER : TYPE_CONTEXT_CONTAINER_NO_POINTERS, tfsoff); -} - static void process_tfs_iface(type_t *iface, FILE *file, int indent, unsigned int *offset) { const statement_list_t *stmts = type_iface_get_stmts(iface); @@ -3710,36 +3948,40 @@ static void process_tfs_iface(type_t *iface, FILE *file, int indent, unsigned in { case STMT_DECLARATION: { - const var_t *func = stmt->u.var; + const var_t *func; + const var_list_t *args; - if(stmt->u.var->stgclass != STG_NONE - || type_get_type_detect_alias(stmt->u.var->type) != TYPE_FUNCTION) + if(stmt->u.var->declspec.stgclass != STG_NONE + || type_get_type_detect_alias(stmt->u.var->declspec.type) != TYPE_FUNCTION) continue; - current_func = func; + current_func = func = stmt->u.var; if (is_local(func->attrs)) continue; - var = type_function_get_retval(func->type); - if (!is_void(var->type)) - var->typestring_offset = write_type_tfs( file, 2, func->attrs, var->type, func->name, - TYPE_CONTEXT_PARAM, offset); + current_arg = var = type_function_get_retval(func->declspec.type); + if (!is_void(var->declspec.type)) + var->typestring_offset = write_type_tfs( file, var->attrs, TRUE, var->declspec.type, func->name, + TYPE_CONTEXT_RETVAL, offset); - if (type_get_function_args(func->type)) - LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), var_t, entry ) - var->typestring_offset = write_type_tfs( file, 2, var->attrs, var->type, var->name, - TYPE_CONTEXT_TOPLEVELPARAM, offset ); + args = type_function_get_args(func->declspec.type); + if (args) LIST_FOR_EACH_ENTRY( var, args, var_t, entry ) + { + current_arg = var; + var->typestring_offset = write_type_tfs( file, var->attrs, TRUE, var->declspec.type, var->name, + TYPE_CONTEXT_TOPLEVELPARAM, offset ); + } break; } case STMT_TYPEDEF: { - const type_list_t *type_entry; - for (type_entry = stmt->u.type_list; type_entry; type_entry = type_entry->next) + typeref_t *ref; + if (stmt->u.type_list) LIST_FOR_EACH_ENTRY(ref, stmt->u.type_list, typeref_t, entry) { - if (is_attr(type_entry->type->attrs, ATTR_ENCODE) - || is_attr(type_entry->type->attrs, ATTR_DECODE)) - type_entry->type->typestring_offset = write_type_tfs( file, 2, - type_entry->type->attrs, type_entry->type, type_entry->type->name, + if (is_attr(ref->type->attrs, ATTR_ENCODE) + || is_attr(ref->type->attrs, ATTR_DECODE)) + ref->type->typestring_offset = write_type_tfs( file, + ref->type->attrs, TRUE, ref->type, ref->type->name, TYPE_CONTEXT_CONTAINER, offset); } break; @@ -3781,17 +4023,17 @@ void write_typeformatstring(FILE *file, const statement_list_t *stmts, type_pred print_file(file, indent, "\n"); } -static unsigned int get_required_buffer_size_type( - const type_t *type, const char *name, const attr_list_t *attrs, int toplevel_param, unsigned int *alignment) +static unsigned int get_required_buffer_size_type(const type_t *type, const char *name, + const attr_list_t *attrs, int toplevel_attrs, int toplevel_param, unsigned int *alignment) { *alignment = 0; - switch (typegen_detect_type(type, NULL, TDT_IGNORE_RANGES)) + switch (typegen_detect_type(type, attrs, TDT_IGNORE_RANGES)) { case TGT_USER_TYPE: { const char *uname = NULL; const type_t *utype = get_user_type(type, &uname); - return get_required_buffer_size_type(utype, uname, NULL, FALSE, alignment); + return get_required_buffer_size_type(utype, uname, NULL, FALSE, FALSE, alignment); } case TGT_BASIC: switch (get_basic_fc(type)) @@ -3861,10 +4103,10 @@ static unsigned int get_required_buffer_size_type( case TGT_POINTER: { unsigned int size, align; - const type_t *ref = type_pointer_get_ref(type); + const type_t *ref = type_pointer_get_ref_type(type); if (is_string_type( attrs, ref )) break; - if (!(size = get_required_buffer_size_type( ref, name, NULL, FALSE, &align ))) break; - if (get_pointer_fc(type, attrs, toplevel_param) != FC_RP) + if (!(size = get_required_buffer_size_type( ref, name, attrs, FALSE, FALSE, &align ))) break; + if (get_pointer_fc(type, attrs, toplevel_attrs, toplevel_param) != FC_RP) { size += 4 + align; align = 4; @@ -3874,16 +4116,13 @@ static unsigned int get_required_buffer_size_type( } case TGT_ARRAY: - if (get_pointer_fc(type, attrs, toplevel_param) == FC_RP) + switch (get_array_fc(type, attrs)) { - switch (get_array_fc(type)) - { - case FC_SMFARRAY: - case FC_LGFARRAY: - return type_array_get_dim(type) * - get_required_buffer_size_type(type_array_get_element(type), name, - NULL, FALSE, alignment); - } + case FC_SMFARRAY: + case FC_LGFARRAY: + return type_array_get_dim(type) * + get_required_buffer_size_type(type_array_get_element_type(type), name, + attrs, FALSE, FALSE, alignment); } break; @@ -3912,9 +4151,9 @@ static unsigned int get_required_buffer_size(const var_t *var, unsigned int *ali return 20; } - if (!is_string_type(var->attrs, var->type)) - return get_required_buffer_size_type(var->type, var->name, - var->attrs, TRUE, alignment); + if (!is_string_type(var->attrs, var->declspec.type)) + return get_required_buffer_size_type(var->declspec.type, var->name, + var->attrs, TRUE, TRUE, alignment); } return 0; } @@ -3924,19 +4163,19 @@ static unsigned int get_function_buffer_size( const var_t *func, enum pass pass const var_t *var; unsigned int total_size = 0, alignment; - if (type_get_function_args(func->type)) + if (type_function_get_args(func->declspec.type)) { - LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) + LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry ) { total_size += get_required_buffer_size(var, &alignment, pass); total_size += alignment; } } - if (pass == PASS_OUT && !is_void(type_function_get_rettype(func->type))) + if (pass == PASS_OUT && !is_void(type_function_get_rettype(func->declspec.type))) { var_t v = *func; - v.type = type_function_get_rettype(func->type); + v.declspec.type = type_function_get_rettype(func->declspec.type); total_size += get_required_buffer_size(&v, &alignment, PASS_RETURN); total_size += alignment; } @@ -3972,9 +4211,9 @@ static void print_phase_function(FILE *file, int indent, const char *type, print_file(file, indent, "&__frame->_StubMsg,\n"); print_file(file, indent, "%s%s%s%s%s,\n", (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)", - (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "", + (phase == PHASE_UNMARSHAL || decl_indirect(var->declspec.type)) ? "&" : "", local_var_prefix, - (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "", + (phase == PHASE_UNMARSHAL && decl_indirect(var->declspec.type)) ? "_p_" : "", var->name); print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n", type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");"); @@ -3987,7 +4226,7 @@ void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix, enum remoting_phase phase, enum pass pass, const var_t *var, const char *varname) { - type_t *type = var->type; + type_t *type = var->declspec.type; unsigned int alignment = 0; /* no work to do for other phases, buffer sizing is done elsewhere */ @@ -4018,8 +4257,9 @@ void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix, } else { - const type_t *ref = is_ptr(type) ? type_pointer_get_ref(type) : type; - switch (get_basic_fc(ref)) + const decl_spec_t *ref = is_ptr(type) ? type_pointer_get_ref(type) : &var->declspec; + + switch (get_basic_fc(ref->type)) { case FC_BYTE: case FC_CHAR: @@ -4056,7 +4296,7 @@ void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix, default: error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", - var->name, get_basic_fc(ref)); + var->name, get_basic_fc(ref->type)); } if (phase == PHASE_MARSHAL && alignment > 1) @@ -4067,7 +4307,7 @@ void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix, if (phase == PHASE_MARSHAL) { print_file(file, indent, "*("); - write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL); + write_type_decl(file, ref, NULL); if (is_ptr(type)) fprintf(file, " *)__frame->_StubMsg.Buffer = *"); else @@ -4078,7 +4318,7 @@ void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix, else if (phase == PHASE_UNMARSHAL) { print_file(file, indent, "if (__frame->_StubMsg.Buffer + sizeof("); - write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL); + write_type_decl(file, ref, NULL); fprintf(file, ") > __frame->_StubMsg.BufferEnd)\n"); print_file(file, indent, "{\n"); print_file(file, indent + 1, "RpcRaiseException(RPC_X_BAD_STUB_DATA);\n"); @@ -4090,12 +4330,12 @@ void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix, fprintf(file, " = ("); else fprintf(file, " = *("); - write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL); + write_type_decl(file, ref, NULL); fprintf(file, " *)__frame->_StubMsg.Buffer;\n"); } print_file(file, indent, "__frame->_StubMsg.Buffer += sizeof("); - write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL); + write_type_decl(file, ref, NULL); fprintf(file, ");\n"); } } @@ -4111,7 +4351,7 @@ expr_t *get_size_is_expr(const type_t *t, const char *name) { expr_t *x = NULL; - for ( ; is_array(t); t = type_array_get_element(t)) + for ( ; is_array(t); t = type_array_get_element_type(t)) if (type_array_has_conformance(t) && type_array_get_conformance(t)->type != EXPR_VOID) { @@ -4129,7 +4369,7 @@ expr_t *get_size_is_expr(const type_t *t, const char *name) void write_parameter_conf_or_var_exprs(FILE *file, int indent, const char *local_var_prefix, enum remoting_phase phase, const var_t *var, int valid_variance) { - const type_t *type = var->type; + const type_t *type = var->declspec.type; /* get fundamental type for the argument */ for (;;) { @@ -4181,7 +4421,7 @@ void write_parameter_conf_or_var_exprs(FILE *file, int indent, const char *local break; } case TGT_POINTER: - type = type_pointer_get_ref(type); + type = type_pointer_get_ref_type(type); continue; case TGT_INVALID: case TGT_USER_TYPE: @@ -4203,11 +4443,11 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const { int in_attr, out_attr, pointer_type; const char *type_str = NULL; - const type_t *type = var->type; + const type_t *type = var->declspec.type; unsigned int alignment, start_offset = type->typestring_offset; if (is_ptr(type) || is_array(type)) - pointer_type = get_pointer_fc(type, var->attrs, pass != PASS_RETURN); + pointer_type = get_pointer_fc(type, var->attrs, TRUE, pass != PASS_RETURN); else pointer_type = 0; @@ -4256,19 +4496,20 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const print_file(file, indent, "NdrServerContextNewMarshall(\n"); print_file(file, indent + 1, "&__frame->_StubMsg,\n"); print_file(file, indent + 1, "(NDR_SCONTEXT)%s%s,\n", local_var_prefix, var->name); - print_file(file, indent + 1, "(NDR_RUNDOWN)%s_rundown,\n", get_context_handle_type_name(var->type)); + print_file(file, indent + 1, "(NDR_RUNDOWN)%s_rundown,\n", get_context_handle_type_name(var->declspec.type)); print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset); } } else if (phase == PHASE_UNMARSHAL) { - if (pass == PASS_OUT) + if (pass == PASS_OUT || pass == PASS_RETURN) { if (!in_attr) print_file(file, indent, "*%s%s = 0;\n", local_var_prefix, var->name); print_file(file, indent, "NdrClientContextUnmarshall(\n"); print_file(file, indent + 1, "&__frame->_StubMsg,\n"); - print_file(file, indent + 1, "(NDR_CCONTEXT *)%s%s,\n", local_var_prefix, var->name); + print_file(file, indent + 1, "(NDR_CCONTEXT *)%s%s%s,\n", + pass == PASS_RETURN ? "&" : "", local_var_prefix, var->name); print_file(file, indent + 1, "__frame->_Handle);\n"); } else @@ -4296,7 +4537,7 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const { print_file(file, indent, "if (%s%s)\n", local_var_prefix, var->name); indent++; - print_file(file, indent, "__frame->_StubMsg.pfnFree(%s%s);\n", local_var_prefix, var->name); + print_file(file, indent, "__frame->_StubMsg.pfnFree((void*)%s%s);\n", local_var_prefix, var->name); } } else @@ -4321,7 +4562,7 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const break; case TGT_ARRAY: { - unsigned char tc = get_array_fc(type); + unsigned char tc = get_array_fc(type, var->attrs); const char *array_type = NULL; /* We already have the size_is expression since it's at the @@ -4362,16 +4603,16 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const ((tc == FC_SMVARRAY || tc == FC_LGVARRAY) && in_attr) || (tc == FC_CARRAY && !in_attr)) { - if (type_array_is_decl_as_ptr(type) && type->details.array.ptr_tfsoff) + if (type_array_is_decl_as_ptr(type) && type_array_get_ptr_tfsoff(type)) { print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, - type->details.array.ptr_tfsoff); + type_array_get_ptr_tfsoff(type)); break; } print_phase_function(file, indent, array_type, local_var_prefix, phase, var, start_offset); print_file(file, indent, "if (%s%s)\n", local_var_prefix, var->name); indent++; - print_file(file, indent, "__frame->_StubMsg.pfnFree(%s%s);\n", local_var_prefix, var->name); + print_file(file, indent, "__frame->_StubMsg.pfnFree((void*)%s%s);\n", local_var_prefix, var->name); break; } } @@ -4399,9 +4640,9 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const range_max = LIST_ENTRY(list_next(range_list, list_head(range_list)), const expr_t, entry); print_file(file, indent, "if ((%s%s < (", local_var_prefix, var->name); - write_type_decl(file, var->type, NULL); + write_type_decl(file, &var->declspec, NULL); fprintf(file, ")0x%x) || (%s%s > (", range_min->cval, local_var_prefix, var->name); - write_type_decl(file, var->type, NULL); + write_type_decl(file, &var->declspec, NULL); fprintf(file, ")0x%x))\n", range_max->cval); print_file(file, indent, "{\n"); print_file(file, indent+1, "RpcRaiseException(RPC_S_INVALID_BOUND);\n"); @@ -4447,8 +4688,8 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const } case TGT_POINTER: { - const type_t *ref = type_pointer_get_ref(type); - if (pointer_type == FC_RP) switch (typegen_detect_type(ref, NULL, TDT_ALL_TYPES)) + const type_t *ref = type_pointer_get_ref_type(type); + if (pointer_type == FC_RP) switch (typegen_detect_type(ref, var->attrs, TDT_ALL_TYPES)) { case TGT_BASIC: print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name); @@ -4473,7 +4714,7 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const { print_file(file, indent, "if (%s%s)\n", local_var_prefix, var->name); indent++; - print_file(file, indent, "__frame->_StubMsg.pfnFree(%s%s);\n", local_var_prefix, var->name); + print_file(file, indent, "__frame->_StubMsg.pfnFree((void*)%s%s);\n", local_var_prefix, var->name); indent--; } break; @@ -4568,14 +4809,14 @@ void write_remoting_arguments(FILE *file, int indent, const var_t *func, const c if (pass == PASS_RETURN) { write_remoting_arg( file, indent, func, local_var_prefix, pass, phase, - type_function_get_retval(func->type) ); + type_function_get_retval(func->declspec.type) ); } else { const var_t *var; - if (!type_get_function_args(func->type)) + if (!type_function_get_args(func->declspec.type)) return; - LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) + LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry ) write_remoting_arg( file, indent, func, local_var_prefix, pass, phase, var ); } } @@ -4616,57 +4857,62 @@ void declare_stub_args( FILE *file, int indent, const var_t *func ) { int in_attr, out_attr; int i = 0; - const var_t *var = type_function_get_retval(func->type); + var_t *var = type_function_get_retval(func->declspec.type); /* declare return value */ - if (!is_void(var->type)) + if (!is_void(var->declspec.type)) { - print_file(file, indent, "%s", ""); - write_type_decl(file, var->type, var->name); - fprintf(file, ";\n"); + if (is_context_handle(var->declspec.type)) + print_file(file, indent, "NDR_SCONTEXT %s;\n", var->name); + else + { + print_file(file, indent, "%s", ""); + write_type_decl(file, &var->declspec, var->name); + fprintf(file, ";\n"); + } } - if (!type_get_function_args(func->type)) + if (!type_function_get_args(func->declspec.type)) return; - LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) + LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), var_t, entry ) { in_attr = is_attr(var->attrs, ATTR_IN); out_attr = is_attr(var->attrs, ATTR_OUT); if (!out_attr && !in_attr) in_attr = 1; - if (is_context_handle(var->type)) + if (is_context_handle(var->declspec.type)) print_file(file, indent, "NDR_SCONTEXT %s;\n", var->name); else { - if (!in_attr && !is_conformant_array(var->type)) + if (!in_attr && !is_conformant_array(var->declspec.type)) { - type_t *type_to_print; + const decl_spec_t *type_to_print; char name[16]; print_file(file, indent, "%s", ""); - if (type_get_type(var->type) == TYPE_ARRAY && - !type_array_is_decl_as_ptr(var->type)) - type_to_print = var->type; + if (type_get_type(var->declspec.type) == TYPE_ARRAY && + !type_array_is_decl_as_ptr(var->declspec.type)) + type_to_print = &var->declspec; else - type_to_print = type_pointer_get_ref(var->type); - sprintf(name, "_W%u", i++); + type_to_print = type_pointer_get_ref(var->declspec.type); + snprintf(name, sizeof(name), "_W%u", i++); write_type_decl(file, type_to_print, name); fprintf(file, ";\n"); } print_file(file, indent, "%s", ""); - write_type_decl_left(file, var->type); + write_type_decl_left(file, &var->declspec); fprintf(file, " "); - if (type_get_type(var->type) == TYPE_ARRAY && - !type_array_is_decl_as_ptr(var->type)) { + if (type_get_type(var->declspec.type) == TYPE_ARRAY && + !type_array_is_decl_as_ptr(var->declspec.type)) { fprintf(file, "(*%s)", var->name); } else fprintf(file, "%s", var->name); - write_type_right(file, var->type, FALSE); + write_type_right(file, var->declspec.type, FALSE); fprintf(file, ";\n"); - if (decl_indirect(var->type)) + if (decl_indirect(var->declspec.type)) print_file(file, indent, "void *_p_%s;\n", var->name); } } @@ -4680,10 +4926,10 @@ void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char const var_t *var; type_t *ref; - if (!type_get_function_args(func->type)) + if (!type_function_get_args(func->declspec.type)) return; - LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) + LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry ) { in_attr = is_attr(var->attrs, ATTR_IN); out_attr = is_attr(var->attrs, ATTR_OUT); @@ -4694,7 +4940,7 @@ void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char { print_file(file, indent, "%s%s", local_var_prefix, var->name); - switch (typegen_detect_type(var->type, var->attrs, TDT_IGNORE_STRINGS)) + switch (typegen_detect_type(var->declspec.type, var->attrs, TDT_IGNORE_STRINGS)) { case TGT_CTXT_HANDLE_POINTER: fprintf(file, " = NdrContextHandleInitialize(\n"); @@ -4703,15 +4949,15 @@ void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char var->typestring_offset); break; case TGT_ARRAY: - if (type_array_has_conformance(var->type)) + if (type_array_has_conformance(var->declspec.type)) { unsigned int size; type_t *type; fprintf(file, " = NdrAllocate(&__frame->_StubMsg, "); - for (type = var->type; + for (type = var->declspec.type; is_array(type) && type_array_has_conformance(type); - type = type_array_get_element(type)) + type = type_array_get_element_type(type)) { write_expr(file, type_array_get_conformance(type), TRUE, TRUE, NULL, NULL, local_var_prefix); @@ -4721,9 +4967,9 @@ void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char fprintf(file, "%u);\n", size); print_file(file, indent, "memset(%s%s, 0, ", local_var_prefix, var->name); - for (type = var->type; + for (type = var->declspec.type; is_array(type) && type_array_has_conformance(type); - type = type_array_get_element(type)) + type = type_array_get_element_type(type)) { write_expr(file, type_array_get_conformance(type), TRUE, TRUE, NULL, NULL, local_var_prefix); @@ -4737,7 +4983,7 @@ void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char break; case TGT_POINTER: fprintf(file, " = &%s_W%u;\n", local_var_prefix, i); - ref = type_pointer_get_ref(var->type); + ref = type_pointer_get_ref_type(var->declspec.type); switch (typegen_detect_type(ref, var->attrs, TDT_IGNORE_STRINGS)) { case TGT_BASIC: @@ -4757,11 +5003,11 @@ void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char print_file(file, indent, "%s_W%u = 0;\n", local_var_prefix, i); break; } - ref = type_array_get_element(ref); + ref = type_array_get_element_type(ref); /* fall through */ case TGT_STRUCT: case TGT_UNION: - if (type_has_pointers(ref)) + if (type_has_pointers(ref, var->attrs)) print_file(file, indent, "memset(&%s_W%u, 0, sizeof(%s_W%u));\n", local_var_prefix, i, local_var_prefix, i); break; @@ -4790,14 +5036,14 @@ void write_func_param_struct( FILE *file, const type_t *iface, const type_t *fun const char *var_decl, int add_retval ) { var_t *retval = type_function_get_retval( func ); - const var_list_t *args = type_get_function_args( func ); + const var_list_t *args = type_function_get_args( func ); const var_t *arg; int needs_packing; unsigned int align = 0; if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) - if (!is_array( arg->type )) type_memsize_and_alignment( arg->type, &align ); + if (!is_array( arg->declspec.type )) type_memsize_and_alignment( arg->declspec.type, &align ); needs_packing = (align > pointer_size); @@ -4809,33 +5055,30 @@ void write_func_param_struct( FILE *file, const type_t *iface, const type_t *fun if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) { print_file(file, 2, "%s", ""); - write_type_left( file, (type_t *)arg->type, NAME_DEFAULT, TRUE ); - if (needs_space_after( arg->type )) fputc( ' ', file ); - if (is_array( arg->type ) && !type_array_is_decl_as_ptr( arg->type )) fputc( '*', file ); + write_type_left( file, &arg->declspec, NAME_DEFAULT, false, TRUE ); + if (needs_space_after( arg->declspec.type )) fputc( ' ', file ); + if (is_array( arg->declspec.type ) && !type_array_is_decl_as_ptr( arg->declspec.type )) fputc( '*', file ); /* FIXME: should check for large args being passed by pointer */ align = 0; - if (is_array( arg->type ) || is_ptr( arg->type )) align = pointer_size; - else type_memsize_and_alignment( arg->type, &align ); + if (is_array( arg->declspec.type ) || is_ptr( arg->declspec.type )) align = pointer_size; + else type_memsize_and_alignment( arg->declspec.type, &align ); - if (align >= pointer_size) - fprintf( file, "%s;\n", arg->name ); - else -#ifdef __REACTOS__ - fprintf( file, "DECLSPEC_ALIGN(%u) %s;\n", pointer_size, arg->name ); -#else - fprintf( file, "%s DECLSPEC_ALIGN(%u);\n", arg->name, pointer_size ); -#endif + if (align < pointer_size) + fprintf( file, "DECLSPEC_ALIGN(%u) ", pointer_size ); + fprintf( file, "%s;\n", arg->name ); } - if (add_retval && !is_void( retval->type )) + if (add_retval && !is_void( retval->declspec.type )) { print_file(file, 2, "%s", ""); - write_type_decl( file, retval->type, retval->name ); - if (is_array( retval->type ) || is_ptr( retval->type ) || - type_memsize( retval->type ) == pointer_size) - fprintf( file, ";\n" ); - else - fprintf( file, " DECLSPEC_ALIGN(%u);\n", pointer_size ); + write_type_left( file, &retval->declspec, NAME_DEFAULT, false, TRUE ); + if (needs_space_after( retval->declspec.type )) fputc( ' ', file ); + if (!is_array( retval->declspec.type ) && !is_ptr( retval->declspec.type ) && + type_memsize( retval->declspec.type ) != pointer_size) + { + fprintf( file, "DECLSPEC_ALIGN(%u) ", pointer_size ); + } + fprintf( file, "%s;\n", retval->name ); } print_file(file, 1, "} %s;\n", var_decl ); if (needs_packing) print_file( file, 0, "#include \n" ); @@ -4844,7 +5087,7 @@ void write_func_param_struct( FILE *file, const type_t *iface, const type_t *fun void write_pointer_checks( FILE *file, int indent, const var_t *func ) { - const var_list_t *args = type_get_function_args( func->type ); + const var_list_t *args = type_function_get_args( func->declspec.type ); const var_t *var; if (!args) return; @@ -4877,10 +5120,11 @@ int write_expr_eval_routines(FILE *file, const char *iface) } else { + decl_spec_t ds = {.type = (type_t *)eval->cont_type}; print_file(file, 1, "%s", ""); - write_type_left(file, (type_t *)eval->cont_type, NAME_DEFAULT, TRUE); + write_type_left(file, &ds, NAME_DEFAULT, false, TRUE); fprintf(file, " *%s = (", var_name); - write_type_left(file, (type_t *)eval->cont_type, NAME_DEFAULT, TRUE); + write_type_left(file, &ds, NAME_DEFAULT, false, TRUE); fprintf(file, " *)(pStubMsg->StackTop - %u);\n", eval->baseoff); } print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */ @@ -4974,20 +5218,20 @@ error: void write_client_call_routine( FILE *file, const type_t *iface, const var_t *func, const char *prefix, unsigned int proc_offset ) { - type_t *rettype = type_function_get_rettype( func->type ); - int has_ret = !is_void( rettype ); - const var_list_t *args = type_get_function_args( func->type ); + const decl_spec_t *rettype = type_function_get_ret( func->declspec.type ); + int has_ret = !is_void( rettype->type ); + const var_list_t *args = type_function_get_args( func->declspec.type ); const var_t *arg; int len, needs_params = 0; /* we need a param structure if we have more than one arg */ - if (pointer_size == 4 && args) needs_params = is_object( iface ) || list_count( args ) > 1; + if (target.cpu == CPU_i386 && args) needs_params = is_object( iface ) || list_count( args ) > 1; print_file( file, 0, "{\n"); if (needs_params) { if (has_ret) print_file( file, 1, "%s", "CLIENT_CALL_RETURN _RetVal;\n" ); - write_func_param_struct( file, iface, func->type, "__params", FALSE ); + write_func_param_struct( file, iface, func->declspec.type, "__params", FALSE ); if (is_object( iface )) print_file( file, 1, "__params.This = This;\n" ); if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) @@ -4997,14 +5241,14 @@ void write_client_call_routine( FILE *file, const type_t *iface, const var_t *fu len = fprintf( file, " %s%s( ", has_ret ? "_RetVal = " : "", - get_stub_mode() == MODE_Oif ? "NdrClientCall2" : "NdrClientCall" ); + interpreted_mode ? "NdrClientCall2" : "NdrClientCall" ); fprintf( file, "&%s_StubDesc,", prefix ); fprintf( file, "\n%*s&__MIDL_ProcFormatString.Format[%u]", len, "", proc_offset ); if (needs_params) { fprintf( file, ",\n%*s&__params", len, "" ); } - else if (pointer_size == 8) + else if (target.cpu != CPU_i386) { if (is_object( iface )) fprintf( file, ",\n%*sThis", len, "" ); if (args) @@ -5025,7 +5269,7 @@ void write_client_call_routine( FILE *file, const type_t *iface, const var_t *fu { print_file( file, 1, "return (" ); write_type_decl_left(file, rettype); - fprintf( file, ")%s;\n", pointer_size == 8 ? "_RetVal.Simple" : "*(LONG_PTR *)&_RetVal" ); + fprintf( file, ")%s;\n", target.cpu != CPU_i386 ? "_RetVal.Simple" : "*(LONG_PTR *)&_RetVal" ); } print_file( file, 0, "}\n\n"); } @@ -5052,7 +5296,7 @@ void write_exceptions( FILE *file ) fprintf( file, " EXCEPTION_REGISTRATION_RECORD frame; \\\n"); fprintf( file, " __filter_func filter; \\\n"); fprintf( file, " __finally_func finally; \\\n"); - fprintf( file, " sigjmp_buf jmp; \\\n"); + fprintf( file, " __wine_jmp_buf jmp; \\\n"); fprintf( file, " DWORD code; \\\n"); fprintf( file, " unsigned char abnormal_termination; \\\n"); fprintf( file, " unsigned char filter_level; \\\n"); @@ -5072,19 +5316,19 @@ void write_exceptions( FILE *file ) fprintf( file, " __wine_pop_frame( &exc_frame->frame );\n"); fprintf( file, " }\n"); fprintf( file, " exc_frame->filter_level = 0;\n"); - fprintf( file, " siglongjmp( exc_frame->jmp, 1 );\n"); + fprintf( file, " __wine_longjmp( &exc_frame->jmp, 1 );\n"); fprintf( file, "}\n"); fprintf( file, "\n"); - fprintf( file, "static DWORD __widl_exception_handler( EXCEPTION_RECORD *record,\n"); - fprintf( file, " EXCEPTION_REGISTRATION_RECORD *frame,\n"); - fprintf( file, " CONTEXT *context,\n"); - fprintf( file, " EXCEPTION_REGISTRATION_RECORD **pdispatcher )\n"); + fprintf( file, "static DWORD __cdecl __widl_exception_handler( EXCEPTION_RECORD *record,\n"); + fprintf( file, " EXCEPTION_REGISTRATION_RECORD *frame,\n"); + fprintf( file, " CONTEXT *context,\n"); + fprintf( file, " EXCEPTION_REGISTRATION_RECORD **pdispatcher )\n"); fprintf( file, "{\n"); fprintf( file, " struct __exception_frame *exc_frame = (struct __exception_frame *)frame;\n"); fprintf( file, "\n"); - fprintf( file, " if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND | EH_NESTED_CALL))\n"); + fprintf( file, " if (record->ExceptionFlags & (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND | EXCEPTION_NESTED_CALL))\n"); fprintf( file, " {\n" ); - fprintf( file, " if (exc_frame->finally_level && (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)))\n"); + fprintf( file, " if (exc_frame->finally_level && (record->ExceptionFlags & (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND)))\n"); fprintf( file, " {\n" ); fprintf( file, " exc_frame->abnormal_termination = 1;\n"); fprintf( file, " exc_frame->finally( exc_frame );\n"); @@ -5098,7 +5342,7 @@ void write_exceptions( FILE *file ) fprintf( file, "}\n"); fprintf( file, "\n"); fprintf( file, "#define RpcTryExcept \\\n"); - fprintf( file, " if (!sigsetjmp( __frame->jmp, 0 )) \\\n"); + fprintf( file, " if (!__wine_setjmpex( &__frame->jmp, &__frame->frame )) \\\n"); fprintf( file, " { \\\n"); fprintf( file, " if (!__frame->finally_level) \\\n" ); fprintf( file, " __wine_push_frame( &__frame->frame ); \\\n"); diff --git a/sdk/tools/widl/typegen.h b/sdk/tools/widl/typegen.h index 95ad601768d..cc843625023 100644 --- a/sdk/tools/widl/typegen.h +++ b/sdk/tools/widl/typegen.h @@ -97,7 +97,6 @@ int is_full_pointer_function(const var_t *func); void write_full_pointer_init(FILE *file, int indent, const var_t *func, int is_server); void write_full_pointer_free(FILE *file, int indent, const var_t *func); unsigned char get_basic_fc(const type_t *type); -unsigned char get_pointer_fc(const type_t *type, const attr_list_t *attrs, int toplevel_param); unsigned char get_struct_fc(const type_t *type); enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *attrs, unsigned int flags); unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align); diff --git a/sdk/tools/widl/typelib.c b/sdk/tools/widl/typelib.c index 9411ccc545c..ac43404db26 100644 --- a/sdk/tools/widl/typelib.c +++ b/sdk/tools/widl/typelib.c @@ -20,27 +20,23 @@ */ #include "config.h" -#include "wine/port.h" -#include "wine/wpp.h" #include #include #include -#ifdef HAVE_UNISTD_H -# include -#endif #include #include +#include "widl.h" #ifdef __REACTOS__ #include +#include #else #include "windef.h" #include "winbase.h" #endif - -#include "widl.h" #include "utils.h" +#include "wpp_private.h" #include "parser.h" #include "header.h" #include "typelib.h" @@ -71,7 +67,6 @@ static const struct oatype { {"VARIANT", VT_VARIANT}, {"VARIANT_BOOL", VT_BOOL} }; -#define NTYPES (sizeof(oatypes)/sizeof(oatypes[0])) #define KWP(p) ((const struct oatype *)(p)) static int kw_cmp_func(const void *s1, const void *s2) @@ -86,11 +81,11 @@ static unsigned short builtin_vt(const type_t *t) const struct oatype *kwp; key.kw = kw; #ifdef KW_BSEARCH - kwp = bsearch(&key, oatypes, NTYPES, sizeof(oatypes[0]), kw_cmp_func); + kwp = bsearch(&key, oatypes, ARRAY_SIZE(oatypes), sizeof(oatypes[0]), kw_cmp_func); #else { unsigned int i; - for (kwp=NULL, i=0; i < NTYPES; i++) + for (kwp = NULL, i = 0; i < ARRAY_SIZE(oatypes); i++) if (!kw_cmp_func(&key, &oatypes[i])) { kwp = &oatypes[i]; break; @@ -104,9 +99,9 @@ static unsigned short builtin_vt(const type_t *t) { const type_t *elem_type; if (is_array(t)) - elem_type = type_array_get_element(t); + elem_type = type_array_get_element_type(t); else - elem_type = type_pointer_get_ref(t); + elem_type = type_pointer_get_ref_type(t); if (type_get_type(elem_type) == TYPE_BASIC) { switch (type_basic_get_type(elem_type)) @@ -136,7 +131,8 @@ unsigned short get_type_vt(type_t *t) if (vt) return vt; } - if (type_is_alias(t) && is_attr(t->attrs, ATTR_PUBLIC)) + if (type_is_alias(t) && + (is_attr(t->attrs, ATTR_PUBLIC) || is_attr(t->attrs, ATTR_WIREMARSHAL))) return VT_USERDEFINED; switch (type_get_type(t)) { @@ -205,7 +201,7 @@ unsigned short get_type_vt(type_t *t) case TYPE_ARRAY: if (type_array_is_decl_as_ptr(t)) { - if (match(type_array_get_element(t)->name, "SAFEARRAY")) + if (match(type_array_get_element_type(t)->name, "SAFEARRAY")) return VT_SAFEARRAY; return VT_PTR; } @@ -225,13 +221,18 @@ unsigned short get_type_vt(type_t *t) case TYPE_MODULE: case TYPE_UNION: case TYPE_ENCAPSULATED_UNION: + case TYPE_RUNTIMECLASS: + case TYPE_DELEGATE: return VT_USERDEFINED; case TYPE_VOID: return VT_VOID; case TYPE_ALIAS: - /* aliases should be filtered out by the type_get_type call above */ + case TYPE_APICONTRACT: + case TYPE_PARAMETERIZED_TYPE: + case TYPE_PARAMETER: + /* not supposed to be here */ assert(0); break; @@ -261,128 +262,147 @@ void end_typelib(void) } #endif -static void tlb_read(int fd, void *buf, int count) +static void msft_read_guid(void *data, MSFT_SegDir *segdir, int offset, struct uuid *guid) { - if(read(fd, buf, count) < count) - error("error while reading importlib.\n"); + memcpy( guid, (char *)data + segdir->pGuidTab.offset + offset, sizeof(*guid) ); } -static void tlb_lseek(int fd, off_t offset) +static void read_msft_importlib(importlib_t *importlib, void *data, unsigned int size) { - if(lseek(fd, offset, SEEK_SET) == -1) - error("lseek failed\n"); -} - -static void msft_read_guid(int fd, MSFT_SegDir *segdir, int offset, GUID *guid) -{ - tlb_lseek(fd, segdir->pGuidTab.offset+offset); - tlb_read(fd, guid, sizeof(GUID)); -} - -static void read_msft_importlib(importlib_t *importlib, int fd) -{ - MSFT_Header header; - MSFT_SegDir segdir; + MSFT_Header *header = data; + MSFT_SegDir *segdir; int *typeinfo_offs; int i; importlib->allocated = 0; + importlib->version = header->version; - tlb_lseek(fd, 0); - tlb_read(fd, &header, sizeof(header)); + typeinfo_offs = (int *)(header + 1); + segdir = (MSFT_SegDir *)(typeinfo_offs + header->nrtypeinfos); - importlib->version = header.version; + msft_read_guid(data, segdir, header->posguid, &importlib->guid); - typeinfo_offs = xmalloc(header.nrtypeinfos*sizeof(INT)); - tlb_read(fd, typeinfo_offs, header.nrtypeinfos*sizeof(INT)); - tlb_read(fd, &segdir, sizeof(segdir)); - - msft_read_guid(fd, &segdir, header.posguid, &importlib->guid); - - importlib->ntypeinfos = header.nrtypeinfos; + importlib->ntypeinfos = header->nrtypeinfos; importlib->importinfos = xmalloc(importlib->ntypeinfos*sizeof(importinfo_t)); for(i=0; i < importlib->ntypeinfos; i++) { - MSFT_TypeInfoBase base; - MSFT_NameIntro nameintro; + MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)((char *)(segdir + 1) + typeinfo_offs[i]); + MSFT_NameIntro *nameintro; int len; - tlb_lseek(fd, sizeof(MSFT_Header) + header.nrtypeinfos*sizeof(INT) + sizeof(MSFT_SegDir) - + typeinfo_offs[i]); - tlb_read(fd, &base, sizeof(base)); - importlib->importinfos[i].importlib = importlib; - importlib->importinfos[i].flags = (base.typekind&0xf)<<24; + importlib->importinfos[i].flags = (base->typekind & 0xf)<<24; importlib->importinfos[i].offset = -1; importlib->importinfos[i].id = i; - if(base.posguid != -1) { + if(base->posguid != -1) { importlib->importinfos[i].flags |= MSFT_IMPINFO_OFFSET_IS_GUID; - msft_read_guid(fd, &segdir, base.posguid, &importlib->importinfos[i].guid); + msft_read_guid(data, segdir, base->posguid, &importlib->importinfos[i].guid); } else memset( &importlib->importinfos[i].guid, 0, sizeof(importlib->importinfos[i].guid)); - tlb_lseek(fd, segdir.pNametab.offset + base.NameOffset); - tlb_read(fd, &nameintro, sizeof(nameintro)); - - len = nameintro.namelen & 0xff; + nameintro = (MSFT_NameIntro *)((char *)data + segdir->pNametab.offset + base->NameOffset); + len = nameintro->namelen & 0xff; importlib->importinfos[i].name = xmalloc(len+1); - tlb_read(fd, importlib->importinfos[i].name, len); + memcpy( importlib->importinfos[i].name, nameintro + 1, len ); importlib->importinfos[i].name[len] = 0; } - - free(typeinfo_offs); } -static int open_typelib(const char *name) +static unsigned int rva_to_va( const IMAGE_NT_HEADERS32 *nt, unsigned int rva ) { - char *file_name; - int fd; + IMAGE_SECTION_HEADER *sec = IMAGE_FIRST_SECTION( nt ); + unsigned int i; - file_name = wpp_find_include(name, NULL); - if(!file_name) - return open(name, O_RDONLY | O_BINARY ); + for (i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++) + if (sec->VirtualAddress <= rva && sec->VirtualAddress + sec->Misc.VirtualSize > rva) + return sec->PointerToRawData + (rva - sec->VirtualAddress); + error( "no PE section found for addr %x\n", rva ); +#ifdef __REACTOS__ + return 0; +#endif +} - fd = open(file_name, O_RDONLY | O_BINARY ); - free(file_name); - return fd; +static void read_pe_importlib(importlib_t *importlib, void *data, unsigned int size) +{ + IMAGE_DOS_HEADER *dos = data; + IMAGE_NT_HEADERS32 *nt; + IMAGE_DATA_DIRECTORY *dir; + IMAGE_RESOURCE_DIRECTORY *root, *resdir; + IMAGE_RESOURCE_DIRECTORY_ENTRY *entry; + IMAGE_RESOURCE_DATA_ENTRY *resdata; + void *ptr; + unsigned int i, va; + + if (dos->e_lfanew < sizeof(*dos) || dos->e_lfanew >= size) error( "not a PE file\n" ); + nt = (IMAGE_NT_HEADERS32 *)((char *)data + dos->e_lfanew); + if (nt->Signature != IMAGE_NT_SIGNATURE) error( "not a PE file\n" ); + if ((char *)(IMAGE_FIRST_SECTION(nt) + nt->FileHeader.NumberOfSections) > (char *)data + size) + error( "invalid PE file\n" ); + switch (nt->OptionalHeader.Magic) + { + case IMAGE_NT_OPTIONAL_HDR32_MAGIC: + dir = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE]; + break; + case IMAGE_NT_OPTIONAL_HDR64_MAGIC: + dir = &((IMAGE_NT_HEADERS64 *)nt)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE]; + break; + default: + error( "invalid PE file\n" ); + } + if (!dir->VirtualAddress || !dir->Size) error( "resource not found in PE file\n" ); + va = rva_to_va( nt, dir->VirtualAddress ); + if (va + dir->Size > size) error( "invalid resource data in PE file\n" ); + root = resdir = (IMAGE_RESOURCE_DIRECTORY *)((char *)data + va ); + entry = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1); + for (i = 0; i < resdir->NumberOfNamedEntries; i++, entry++) + { + static const WCHAR typelibW[] = {'T','Y','P','E','L','I','B'}; + WCHAR *name = (WCHAR *)((char *)root + entry->NameOffset); + if (name[0] != ARRAY_SIZE(typelibW)) continue; + if (!memcmp( name + 1, typelibW, sizeof(typelibW) )) break; + } + if (i == resdir->NumberOfNamedEntries) error( "typelib resource not found in PE file\n" ); + while (entry->DataIsDirectory) + { + resdir = (IMAGE_RESOURCE_DIRECTORY *)((char *)root + entry->OffsetToDirectory); + entry = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1); + } + resdata = (IMAGE_RESOURCE_DATA_ENTRY *)((char *)root + entry->OffsetToData); + ptr = (char *)data + rva_to_va( nt, resdata->OffsetToData ); + if (memcmp( ptr, "MSFT", 4 )) error( "invalid typelib found in PE file\n" ); + read_msft_importlib( importlib, ptr, resdata->Size ); } static void read_importlib(importlib_t *importlib) { - int fd; - INT magic; + int fd, size; + void *data; fd = open_typelib(importlib->name); /* widl extension: if importlib name has no .tlb extension, try using .tlb */ - if(fd < 0) { - const char *p = strrchr(importlib->name, '.'); - size_t len = p ? p - importlib->name : strlen(importlib->name); - if(strcmp(importlib->name + len, ".tlb")) { - char *tlb_name = xmalloc(len + 5); - memcpy(tlb_name, importlib->name, len); - strcpy(tlb_name + len, ".tlb"); - fd = open_typelib(tlb_name); - free(tlb_name); - } - } + if (fd < 0 && !strendswith( importlib->name, ".tlb" )) + fd = open_typelib( strmake( "%s.tlb", importlib->name )); if(fd < 0) error("Could not find importlib %s.\n", importlib->name); - tlb_read(fd, &magic, sizeof(magic)); + size = lseek( fd, 0, SEEK_END ); + data = xmalloc( size ); + lseek( fd, 0, SEEK_SET ); + if (read( fd, data, size) < size) error("error while reading importlib.\n"); + close( fd ); - switch(magic) { - case MSFT_MAGIC: - read_msft_importlib(importlib, fd); - break; - default: - error("Wrong or unsupported typelib magic %x\n", magic); - }; + if (!memcmp( data, "MSFT", 4 )) + read_msft_importlib(importlib, data, size); + else if (!memcmp( data, "MZ", 2 )) + read_pe_importlib(importlib, data, size); + else + error("Wrong or unsupported typelib\n"); - close(fd); + free( data ); } #ifdef __REACTOS__ diff --git a/sdk/tools/widl/typelib_struct.h b/sdk/tools/widl/typelib_struct.h index 0d9f8ebd53c..ec1e317bf23 100644 --- a/sdk/tools/widl/typelib_struct.h +++ b/sdk/tools/widl/typelib_struct.h @@ -49,13 +49,13 @@ * */ typedef struct tagMSFT_Header { -/*0x00*/INT magic1; /* 0x5446534D "MSFT" */ - INT magic2; /* 0x00010002 version nr? */ - INT posguid; /* position of libid in guid table */ +/*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 */ + int lcid; /* locale id */ +/*0x10*/int lcid2; + int varflags; /* (largely) unknown flags */ /* the lower nibble is syskind */ /* 0x40 always seems to be set */ /* 0x10 set with a helpfile defined */ @@ -63,30 +63,30 @@ typedef struct tagMSFT_Header { case the offset to the name in the stringtable appears right after this struct, before the typeinfo offsets */ - 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 */ + 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 nimpinfos; /* number of impinfos */ + 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 nimpinfos; /* number of impinfos */ } 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 */ + 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; @@ -118,70 +118,60 @@ typedef struct tagMSFT_SegDir { /* base type info data */ typedef struct tagMSFT_TypeInfoBase { -/*000*/ INT typekind; /* it is the TKIND_xxx */ +/*000*/ int typekind; /* it is the TKIND_xxx */ /* some byte alignment stuff */ - INT memoffset; /* points past the file, if no elements */ - INT res2; /* zero if no element, N*0x40 */ - INT res3; /* -1 if no element, (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, including inherits */ - INT16 cImplTypes; /* nr of implemented interfaces */ -#else - INT16 cImplTypes; /* nr of implemented interfaces */ - INT16 cbSizeVft; /* virtual table size, including inherits */ -#endif -/*050*/ INT size; /* size in bytes, at least for structures */ + int memoffset; /* points past the file, if no elements */ + int res2; /* zero if no element, N*0x40 */ + int res3; /* -1 if no element, (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 */ + short cImplTypes; /* nr of implemented interfaces */ + short cbSizeVft; /* virtual table size, including inherits */ +/*050*/ int size; /* size in bytes, at least for structures */ /* FIXME: name of this field */ - INT datatype1; /* position in type description table */ + int datatype1; /* position in type description table */ /* or in base interfaces */ /* if coclass: offset in reftable */ /* if interface: reference to inherited if */ - INT datatype2; /* for interfaces: hiword is num of inherited funcs */ + int datatype2; /* for interfaces: hiword is num of inherited funcs */ /* loword is num of inherited interfaces */ - INT res18; /* always? 0 */ -/*060*/ INT res19; /* always? -1 */ + 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 flags; /* bits 0 - 15: count */ + int flags; /* bits 0 - 15: count */ /* bit 16: if set oGuid is an offset to Guid */ /* if clear oGuid is a typeinfo index in the specified typelib */ /* bits 24 - 31: TKIND of reference */ - INT oImpFile; /* offset in the Import File table */ - INT oGuid; /* offset in Guid table or typeinfo index (see bit 16 of flags) */ + int oImpFile; /* offset in the Import File table */ + int oGuid; /* offset in Guid table or typeinfo index (see bit 16 of flags) */ } MSFT_ImpInfo; #define MSFT_IMPINFO_OFFSET_IS_GUID 0x00010000 /* function description data */ typedef struct { -/* INT recsize; record size including some extra stuff */ - INT DataType; /* data type of the member, 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 */ +/* int recsize; record size including some extra stuff */ + int DataType; /* data type of the member, eg return of function */ + int Flags; /* something to do with attribute flags (LOWORD) */ + short VtableOffset; /* offset in vtable */ + short funcdescsize; /* size of reconstituted FUNCDESC and related structs */ + int FKCCIC; /* bit string with the following */ /* meaning (bit 0 is the lsb): */ /* bits 0 - 2: FUNCKIND */ /* bits 3 - 6: INVOKEKIND */ @@ -191,96 +181,86 @@ typedef struct { /* bit 13: oEntry is numeric */ /* bit 14: has retval param */ /* bits 16 - 31: index of next function with same id */ -#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 + short nrargs; /* number of arguments (including optional ????) */ + short nroargs; /* nr of optional arguments */ /* optional attribute fields, the number of them is variable */ - INT OptAttr[1]; + int OptAttr[1]; /* -0* INT helpcontext; -1* INT oHelpString; -2* INT oEntry; // either offset in string table or numeric as it is (see bit 13 of FKCCIC) // -3* INT res9; // unknown (-1) // -4* INT resA; // unknown (-1) // -5* INT HelpStringContext; +0* int helpcontext; +1* int oHelpString; +2* int oEntry; // either offset in string table or numeric as it is (see bit 13 of FKCCIC) // +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 // +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 oDefaultValue[nrargs]; + * int oDefaultValue[nrargs]; */ /* Parameter info one per argument*/ typedef struct { - INT DataType; - INT oName; - INT Flags; + int DataType; + int oName; + int Flags; } MSFT_ParameterInfo; /* Variable description data */ typedef struct { -/* INT recsize; // record size including some extra 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 */ +/* int recsize; // record size including some extra stuff */ + int DataType; /* data type of the variable */ + int Flags; /* VarFlags (LOWORD) */ + short VarKind; /* VarKind */ + short vardescsize; /* size of reconstituted VARDESC and related structs */ + 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; + 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 */ + 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 */ + 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 + struct uuid 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 */ + 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, + 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 */ + int next_hash; /* offset to next name in the hash bucket */ + int namelen; /* only lower 8 bits are valid */ /* 0x1000 if name is only used once as a variable name */ /* 0x2000 if name is a variable in an enumeration */ /* 0x3800 if name is typeinfo name */ @@ -288,9 +268,9 @@ typedef struct { } MSFT_NameIntro; /* the custom data table directory has entries like this */ typedef struct { - INT GuidOffset; - INT DataOffset; - INT next; /* next offset in the table, -1 if it's the last */ + int GuidOffset; + int DataOffset; + int next; /* next offset in the table, -1 if it's the last */ } MSFT_CDGuid; @@ -305,35 +285,35 @@ typedef struct { #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 */ +/*00*/ unsigned int SLTG_magic; /* 0x47544c53 == "SLTG" */ +/*04*/ unsigned short nrOfFileBlks; /* no of SLTG_BlkEntry's + 1 */ +/*06*/ unsigned short res06; /* ?? always 9 */ +/*08*/ unsigned short res08; /* some kind of len/offset ?? */ +/*0a*/ unsigned short first_blk; /* 1 based index into blk entries that + corresponds to first block in file */ +/*0c*/ unsigned int res0c; /* always 0x000204ff */ +/*10*/ unsigned int res10; /* always 0x00000000 */ +/*14*/ unsigned int res14; /* always 0x000000c0 */ +/*18*/ unsigned int res18; /* always 0x46000000 */ +/*1c*/ unsigned int res1c; /* always 0x00000044 */ +/*20*/ unsigned int 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; +/*00*/ unsigned int len; +/*04*/ unsigned short index_string; /* offs from start of SLTG_Magic to index string */ +/*06*/ unsigned short 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 */ + entry first_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" */ +/*00*/ unsigned char res00; /* always 0x01 */ +/*01*/ char CompObj_magic[8]; /* always "CompObj" */ +/*09*/ char dir_magic[4]; /* always "dir" */ } SLTG_Magic; #define SLTG_COMPOBJ_MAGIC "CompObj" @@ -346,13 +326,13 @@ uniqueness. I guess successive chars increment when we need to wrap the first one. */ typedef struct { -/*00*/ CHAR string[11]; +/*00*/ char string[11]; } SLTG_Index; /* This is followed by SLTG_pad9 */ typedef struct { -/*00*/ CHAR pad[9]; /* 9 '\0's */ +/*00*/ char pad[9]; /* 9 '\0's */ } SLTG_Pad9; @@ -362,25 +342,25 @@ 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; +typedef unsigned short 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; +/*00*/ unsigned short magic; /* 0x51cc */ +/*02*/ unsigned short res02; /* 0x0003, 0x0004 */ +/*04*/ unsigned short name; /* offset to name in name table */ +/*06*/ SLTG_Name res06; /* maybe this is just WORD == 0xffff */ + SLTG_Name helpstring; + SLTG_Name helpfile; + unsigned int helpcontext; + unsigned short syskind; /* == 1 for win32, 0 for win16 */ + unsigned short lcid; /* == 0x409, 0x809 etc */ + unsigned int res12; /* == 0 */ + unsigned short libflags; /* LIBFLAG_* */ + unsigned short maj_vers; + unsigned short min_vers; + struct uuid uuid; } SLTG_LibBlk; #define SLTG_LIBBLK_MAGIC 0x51cc @@ -388,18 +368,18 @@ typedef struct { /* 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; + unsigned short small_no; + SLTG_Name index_name; /* This refers to a name in the directory */ + SLTG_Name other_name; /* Another one of these weird names */ + unsigned short res1a; /* 0xffff */ + unsigned short name_offs; /* offset to name in name table */ + unsigned short 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 ? */ + unsigned short res20; /* 0xffff */ + unsigned int helpcontext; + unsigned short res26; /* 0xffff */ + struct uuid uuid; } SLTG_OtherTypeInfo; /* Next we get WORD 0x0003 followed by a DWORD which if we add to @@ -407,104 +387,104 @@ typedef struct { 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 */ +/*00*/ unsigned short magic; /* 0x0501 */ +/*02*/ unsigned int href_table; /* if not 0xffffffff, then byte offset from + beginning of struct to href table */ +/*06*/ unsigned int res06; /* 0xffffffff */ +/*0a*/ unsigned int elem_table; /* offset to members */ +/*0e*/ unsigned int res0e; /* 0xffffffff */ +/*12*/ unsigned short major_version; /* major version number */ +/*14*/ unsigned short minor_version; /* minor version number */ +/*16*/ unsigned int res16; /* 0xfffe0000 */ +/*1a*/ unsigned char typeflags1;/* 0x02 | top 5 bits hold l5sbs of TYPEFLAGS */ +/*1b*/ unsigned char typeflags2;/* TYPEFLAGS >> 5 */ +/*1c*/ unsigned char typeflags3;/* 0x02*/ +/*1d*/ unsigned char typekind; /* 0x03 == TKIND_INTERFACE etc. */ +/*1e*/ unsigned int 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; +/*00*/ unsigned short cFuncs; +/*02*/ unsigned short cVars; +/*04*/ unsigned short cImplTypes; +/*06*/ unsigned short res06; +/*08*/ unsigned short res08; +/*0a*/ unsigned short res0a; +/*0c*/ unsigned short res0c; +/*0e*/ unsigned short res0e; +/*10*/ unsigned short res10; +/*12*/ unsigned short res12; +/*14*/ unsigned short tdescalias_vt; /* for TKIND_ALIAS */ +/*16*/ unsigned short res16; +/*18*/ unsigned short res18; +/*1a*/ unsigned short res1a; +/*1c*/ unsigned short res1c; +/*1e*/ unsigned short res1e; +/*20*/ unsigned short cbSizeInstance; +/*22*/ unsigned short cbAlignment; +/*24*/ unsigned short res24; +/*26*/ unsigned short res26; +/*28*/ unsigned short cbSizeVft; +/*2a*/ unsigned short res2a; +/*2c*/ unsigned short res2c; +/*2e*/ unsigned short res2e; +/*30*/ unsigned short res30; +/*32*/ unsigned short res32; +/*34*/ unsigned short 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 */ +/*00*/ unsigned short res00; /* 0x0001 sometimes 0x0003 ?? */ +/*02*/ unsigned short res02; /* 0xffff */ +/*04*/ unsigned char res04; /* 0x01 */ +/*05*/ unsigned int 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 */ +/*00*/ unsigned short magic; /* 0x120a */ +/*02*/ unsigned short next; /* offset in bytes to next block from start of block + group, 0xffff if last item */ +/*04*/ unsigned short name; /* offset to name within name table */ +/*06*/ unsigned short value; /* offset to value from start of block group */ +/*08*/ unsigned short res08; /* 0x56 */ +/*0a*/ unsigned int memid; /* memid */ +/*0e*/ unsigned short helpcontext;/* 0xfffe == no context, 0x0001 == stored in EnumInfo struct, else offset + to value from start of block group */ +/*10*/ unsigned short 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 */ +/*00*/ unsigned short vt; /* vartype, 0xffff marks end. */ +/*02*/ unsigned short 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 + unsigned char magic; /* 0x4c or 0x6c */ + unsigned char inv; /* high nibble is INVOKE_KIND, low nibble = 2 */ + unsigned short next; /* byte offset from beginning of group to next fn */ + unsigned short name; /* Offset within name table to name */ + unsigned int dispid; /* dispid */ + unsigned short helpcontext; /* helpcontext (again 1 is special) */ + unsigned short helpstring;/* helpstring offset to offset */ + unsigned short arg_off; /* offset to args from start of block */ + unsigned char nacc; /* lowest 3bits are CALLCONV, rest are no of args */ + unsigned char 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 */ + unsigned short rettype; /* return type VT_?? or offset to ret type */ + unsigned short vtblpos; /* position in vtbl? */ + unsigned short 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 */ + unsigned short name; /* offset to 2nd letter of name */ + unsigned short+ type; /* VT_ of param */ #endif } SLTG_Function; @@ -512,32 +492,32 @@ typedef struct { #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 */ +/*00*/ unsigned char magic; /* 0xdf */ +/*01*/ unsigned char res01; /* 0x00 */ +/*02*/ unsigned int res02; /* 0xffffffff */ +/*06*/ unsigned int res06; /* 0xffffffff */ +/*0a*/ unsigned int res0a; /* 0xffffffff */ +/*0e*/ unsigned int res0e; /* 0xffffffff */ +/*12*/ unsigned int res12; /* 0xffffffff */ +/*16*/ unsigned int res16; /* 0xffffffff */ +/*1a*/ unsigned int res1a; /* 0xffffffff */ +/*1e*/ unsigned int res1e; /* 0xffffffff */ +/*22*/ unsigned int res22; /* 0xffffffff */ +/*26*/ unsigned int res26; /* 0xffffffff */ +/*2a*/ unsigned int res2a; /* 0xffffffff */ +/*2e*/ unsigned int res2e; /* 0xffffffff */ +/*32*/ unsigned int res32; /* 0xffffffff */ +/*36*/ unsigned int res36; /* 0xffffffff */ +/*3a*/ unsigned int res3a; /* 0xffffffff */ +/*3e*/ unsigned int res3e; /* 0xffffffff */ +/*42*/ unsigned short res42; /* 0xffff */ +/*44*/ unsigned int 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]; +/*50*/ unsigned short res50; /* 0xffff */ +/*52*/ unsigned char res52; /* 0x01 */ +/*53*/ unsigned int 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 @@ -547,47 +527,47 @@ typedef struct { * the imported typelib. */ -/*xx*/ BYTE resxx; /* 0xdf */ +/*xx*/ unsigned char 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 ?? */ + unsigned short res00; /* 0x0001 */ + unsigned char res02; /* 0x02 */ + unsigned char res03; /* 0x40 if internal ref, 0x00 if external ? */ + unsigned short res04; /* 0xffff */ + unsigned short 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, ? */ + unsigned short res00; /* 0x004a */ + unsigned short next; /* byte offs to next interface */ + unsigned short res04; /* 0xffff */ + unsigned char impltypeflags; /* IMPLTYPEFLAG_* */ + unsigned char res07; /* 0x80 */ + unsigned short res08; /* 0x0012, 0x0028 ?? */ + unsigned short ref; /* number in ref table ? */ + unsigned short res0c; /* 0x4000 */ + unsigned short res0e; /* 0xfffe */ + unsigned short res10; /* 0xffff */ + unsigned short res12; /* 0x001d */ + unsigned short 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; /* ?? */ + unsigned char magic; /* 0x0a */ + unsigned char typepos; + unsigned short next; + unsigned short name; + unsigned short byte_offs; /* pos in struct */ + unsigned short type; /* if typepos == 0x02 this is the type, else offset to type */ + unsigned int memid; + unsigned short helpcontext; /* ?? */ + unsigned short helpstring; /* ?? */ } SLTG_RecordItem; #define SLTG_RECORD_MAGIC 0x0a diff --git a/sdk/tools/widl/typetree.c b/sdk/tools/widl/typetree.c index b93806be981..fd18dac3b19 100644 --- a/sdk/tools/widl/typetree.c +++ b/sdk/tools/widl/typetree.c @@ -23,12 +23,16 @@ #include #include #include +#ifdef __REACTOS__ +#include +#endif #include "widl.h" #include "utils.h" #include "parser.h" #include "typetree.h" #include "header.h" +#include "hash.h" type_t *duptype(type_t *t, int dupname) { @@ -49,7 +53,11 @@ type_t *make_type(enum type_type type) t->type_type = type; t->attrs = NULL; t->c_name = NULL; - t->orig = NULL; + t->signature = NULL; + t->qualified_name = NULL; + t->impl_name = NULL; + t->param_name = NULL; + t->short_name = NULL; memset(&t->details, 0, sizeof(t->details)); t->typestring_offset = 0; t->ptrdesc = 0; @@ -59,9 +67,8 @@ type_t *make_type(enum type_type type) t->user_types_registered = FALSE; t->tfswrite = FALSE; t->checked = FALSE; - t->is_alias = FALSE; t->typelib_idx = -1; - init_loc_info(&t->loc_info); + init_location( &t->where, NULL, NULL ); return t; } @@ -78,54 +85,336 @@ static const var_t *find_arg(const var_list_t *args, const char *name) return NULL; } -const char *type_get_name(const type_t *type, enum name_type name_type) +const char *type_get_decl_name(const type_t *type, enum name_type name_type) { switch(name_type) { case NAME_DEFAULT: return type->name; case NAME_C: - return type->c_name; + return type->c_name ? type->c_name : type->name; } assert(0); return NULL; } -static char *append_namespace(char *ptr, struct namespace *namespace, const char *separator) +const char *type_get_name(const type_t *type, enum name_type name_type) { - if(is_global_namespace(namespace)) { - if(!use_abi_namespace) - return ptr; - strcpy(ptr, "ABI"); - strcat(ptr, separator); - return ptr + strlen(ptr); + switch(name_type) { + case NAME_DEFAULT: + return type->qualified_name ? type->qualified_name : type->name; + case NAME_C: + return type->c_name ? type->c_name : type->name; } - ptr = append_namespace(ptr, namespace->parent, separator); - strcpy(ptr, namespace->name); - strcat(ptr, separator); - return ptr + strlen(ptr); + assert(0); + return NULL; } -char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix) +static size_t append_namespace(char **buf, size_t *len, size_t pos, struct namespace *namespace, const char *separator, const char *abi_prefix) { - unsigned len = strlen(prefix) + strlen(suffix); - unsigned sep_len = strlen(separator); - struct namespace *iter; - char *ret, *ptr; + int nested = namespace && !is_global_namespace(namespace); + const char *name = nested ? namespace->name : abi_prefix; + size_t n = 0; + if (!name) return 0; + if (nested) n += append_namespace(buf, len, pos + n, namespace->parent, separator, abi_prefix); + n += strappend(buf, len, pos + n, "%s%s", name, separator); + return n; +} - if(use_abi_namespace && !is_global_namespace(namespace)) - len += 3 /* strlen("ABI") */ + sep_len; +static size_t append_namespaces(char **buf, size_t *len, size_t pos, struct namespace *namespace, const char *prefix, + const char *separator, const char *suffix, const char *abi_prefix) +{ + int nested = namespace && !is_global_namespace(namespace); + size_t n = 0; + n += strappend(buf, len, pos + n, "%s", prefix); + if (nested) n += append_namespace(buf, len, pos + n, namespace, separator, abi_prefix); + if (suffix) n += strappend(buf, len, pos + n, "%s", suffix); + else if (nested) + { + n -= strlen(separator); + (*buf)[n] = 0; + } + return n; +} - for(iter = namespace; !is_global_namespace(iter); iter = iter->parent) - len += strlen(iter->name) + sep_len; +static size_t append_pointer_stars(char **buf, size_t *len, size_t pos, type_t *type) +{ + size_t n = 0; + for (; type && type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) n += strappend(buf, len, pos + n, "*"); + return n; +} - ret = xmalloc(len+1); - strcpy(ret, prefix); - ptr = append_namespace(ret + strlen(ret), namespace, separator); - strcpy(ptr, suffix); +static size_t append_type_signature(char **buf, size_t *len, size_t pos, type_t *type); - return ret; +static size_t append_var_list_signature(char **buf, size_t *len, size_t pos, var_list_t *var_list) +{ + var_t *var; + size_t n = 0; + + if (!var_list) n += strappend(buf, len, pos + n, ";"); + else LIST_FOR_EACH_ENTRY(var, var_list, var_t, entry) + { + n += strappend(buf, len, pos + n, ";"); + n += append_type_signature(buf, len, pos + n, var->declspec.type); + } + + return n; +} + +static size_t append_type_signature(char **buf, size_t *len, size_t pos, type_t *type) +{ + const struct uuid *uuid; + size_t n = 0; + + if (!type) return 0; + switch (type->type_type) + { + case TYPE_INTERFACE: + if (!strcmp(type->name, "IInspectable")) n += strappend(buf, len, pos + n, "cinterface(IInspectable)"); + else if (type->signature) n += strappend(buf, len, pos + n, "%s", type->signature); + else + { + if (!(uuid = get_attrp( type->attrs, ATTR_UUID ))) + error_at( &type->where, "cannot compute type signature, no uuid found for type %s.\n", type->name ); + + n += strappend(buf, len, pos + n, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + uuid->Data1, uuid->Data2, uuid->Data3, + uuid->Data4[0], uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], + uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], uuid->Data4[7]); + } + return n; + case TYPE_DELEGATE: + n += strappend(buf, len, pos + n, "delegate("); + n += append_type_signature(buf, len, pos + n, type_delegate_get_iface(type)); + n += strappend(buf, len, pos + n, ")"); + return n; + case TYPE_RUNTIMECLASS: + n += strappend(buf, len, pos + n, "rc("); + n += append_namespaces(buf, len, pos + n, type->namespace, "", ".", type->name, NULL); + n += strappend(buf, len, pos + n, ";"); + n += append_type_signature(buf, len, pos + n, type_runtimeclass_get_default_iface(type, TRUE)); + n += strappend(buf, len, pos + n, ")"); + return n; + case TYPE_POINTER: + n += append_type_signature(buf, len, pos + n, type->details.pointer.ref.type); + return n; + case TYPE_ALIAS: + if (!strcmp(type->name, "boolean")) n += strappend(buf, len, pos + n, "b1"); + else if (!strcmp(type->name, "GUID")) n += strappend(buf, len, pos + n, "g16"); + else if (!strcmp(type->name, "HSTRING")) n += strappend(buf, len, pos + n, "string"); + else n += append_type_signature(buf, len, pos + n, type->details.alias.aliasee.type); + return n; + case TYPE_STRUCT: + n += strappend(buf, len, pos + n, "struct("); + n += append_namespaces(buf, len, pos + n, type->namespace, "", ".", type->name, NULL); + n += append_var_list_signature(buf, len, pos + n, type->details.structure->fields); + n += strappend(buf, len, pos + n, ")"); + return n; + case TYPE_BASIC: + switch (type_basic_get_type(type)) + { + case TYPE_BASIC_INT16: + n += strappend(buf, len, pos + n, type_basic_get_sign(type) <= 0 ? "i2" : "u2"); + return n; + case TYPE_BASIC_INT: + case TYPE_BASIC_INT32: + case TYPE_BASIC_LONG: + n += strappend(buf, len, pos + n, type_basic_get_sign(type) <= 0 ? "i4" : "u4"); + return n; + case TYPE_BASIC_INT64: + n += strappend(buf, len, pos + n, type_basic_get_sign(type) <= 0 ? "i8" : "u8"); + return n; + case TYPE_BASIC_INT8: + assert(type_basic_get_sign(type) > 0); /* signature string for signed char isn't specified */ + n += strappend(buf, len, pos + n, "u1"); + return n; + case TYPE_BASIC_FLOAT: + n += strappend(buf, len, pos + n, "f4"); + return n; + case TYPE_BASIC_DOUBLE: + n += strappend(buf, len, pos + n, "f8"); + return n; + case TYPE_BASIC_BYTE: + n += strappend(buf, len, pos + n, "u1"); + return n; + case TYPE_BASIC_INT3264: + case TYPE_BASIC_CHAR: + case TYPE_BASIC_HYPER: + case TYPE_BASIC_WCHAR: + case TYPE_BASIC_ERROR_STATUS_T: + case TYPE_BASIC_HANDLE: + error_at( &type->where, "unimplemented type signature for basic type %d.\n", + type_basic_get_type( type ) ); + break; + } + case TYPE_ENUM: + n += strappend(buf, len, pos + n, "enum("); + n += append_namespaces(buf, len, pos + n, type->namespace, "", ".", type->name, NULL); + if (is_attr(type->attrs, ATTR_FLAGS)) n += strappend(buf, len, pos + n, ";u4"); + else n += strappend(buf, len, pos + n, ";i4"); + n += strappend(buf, len, pos + n, ")"); + return n; + case TYPE_ARRAY: + case TYPE_ENCAPSULATED_UNION: + case TYPE_UNION: + case TYPE_COCLASS: + case TYPE_VOID: + case TYPE_FUNCTION: + case TYPE_BITFIELD: + case TYPE_MODULE: + case TYPE_APICONTRACT: + error_at( &type->where, "unimplemented type signature for type %s of type %d.\n", + type->name, type->type_type ); + break; + case TYPE_PARAMETERIZED_TYPE: + case TYPE_PARAMETER: + assert(0); /* should not be there */ + break; + } + + return n; +} + +char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, const char *abi_prefix) +{ + size_t len = 0; + char *buf = NULL; + append_namespaces(&buf, &len, 0, namespace, prefix, separator, suffix, abi_prefix); + return buf; +} + +char *format_parameterized_type_name(type_t *type, typeref_list_t *params) +{ + size_t len = 0, pos = 0; + char *buf = NULL; + typeref_t *ref; + + pos += strappend(&buf, &len, pos, "%s<", type->name); + if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry) + { + type = type_pointer_get_root_type(ref->type); + pos += strappend(&buf, &len, pos, "%s", type->qualified_name); + pos += append_pointer_stars(&buf, &len, pos, ref->type); + if (list_next(params, &ref->entry)) pos += strappend(&buf, &len, pos, ","); + } + pos += strappend(&buf, &len, pos, " >"); + + return buf; +} + +static char const *parameterized_type_shorthands[][2] = { + {"Windows__CFoundation__CCollections__C", "__F"}, + {"Windows_CFoundation_CCollections_C", "__F"}, + {"Windows__CFoundation__C", "__F"}, + {"Windows_CFoundation_C", "__F"}, +}; + +static char *format_parameterized_type_c_name(type_t *type, typeref_list_t *params, const char *prefix, const char *separator) +{ + const char *tmp, *ns_prefix = "__x_", *abi_prefix = NULL; + size_t len = 0, pos = 0; + char *buf = NULL; + int i, count = params ? list_count(params) : 0; + typeref_t *ref; + + if (!strcmp(separator, "__C")) ns_prefix = "_C"; + else if (use_abi_namespace) abi_prefix = "ABI"; + + pos += append_namespaces(&buf, &len, pos, type->namespace, ns_prefix, separator, "", abi_prefix); + pos += strappend(&buf, &len, pos, "%s%s_%d", prefix, type->name, count); + if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry) + { + type = type_pointer_get_root_type(ref->type); + if ((tmp = type->param_name)) pos += strappend(&buf, &len, pos, "_%s", tmp); + else pos += append_namespaces(&buf, &len, pos, type->namespace, "_", "__C", type->name, NULL); + } + + for (i = 0; i < ARRAY_SIZE(parameterized_type_shorthands); ++i) + { + if ((tmp = strstr(buf, parameterized_type_shorthands[i][0])) && + (tmp - buf) == strlen(ns_prefix) + (abi_prefix ? 5 : 0)) + { + tmp += strlen(parameterized_type_shorthands[i][0]); + strcpy(buf, parameterized_type_shorthands[i][1]); + memmove(buf + 3, tmp, len - (tmp - buf)); + } + } + + return buf; +} + +static char *format_parameterized_type_signature(type_t *type, typeref_list_t *params) +{ + size_t len = 0, pos = 0; + char *buf = NULL; + typeref_t *ref; + const struct uuid *uuid; + + if (!(uuid = get_attrp( type->attrs, ATTR_UUID ))) + error_at( &type->where, "cannot compute type signature, no uuid found for type %s.\n", type->name ); + + pos += strappend(&buf, &len, pos, "pinterface({%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + uuid->Data1, uuid->Data2, uuid->Data3, + uuid->Data4[0], uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], + uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], uuid->Data4[7]); + if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry) + { + pos += strappend(&buf, &len, pos, ";"); + pos += append_type_signature(&buf, &len, pos, ref->type); + } + pos += strappend(&buf, &len, pos, ")"); + + return buf; +} + +static char *format_parameterized_type_short_name(type_t *type, typeref_list_t *params, const char *prefix) +{ + size_t len = 0, pos = 0; + char *buf = NULL; + typeref_t *ref; + + pos += strappend(&buf, &len, pos, "%s%s", prefix, type->name); + if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry) + { + type = type_pointer_get_root_type(ref->type); + if (type->short_name) pos += strappend(&buf, &len, pos, "_%s", type->short_name); + else pos += strappend(&buf, &len, pos, "_%s", type->name); + } + + return buf; +} + +static char *format_parameterized_type_impl_name(type_t *type, typeref_list_t *params, const char *prefix) +{ + size_t len = 0, pos = 0; + char *buf = NULL; + typeref_t *ref; + type_t *iface; + + pos += strappend(&buf, &len, pos, "%s%s_impl<", prefix, type->name); + if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry) + { + type = type_pointer_get_root_type(ref->type); + if (type->type_type == TYPE_RUNTIMECLASS) + { + pos += strappend(&buf, &len, pos, "ABI::Windows::Foundation::Internal::AggregateType<%s", type->qualified_name); + pos += append_pointer_stars(&buf, &len, pos, ref->type); + iface = type_runtimeclass_get_default_iface(type, TRUE); + pos += strappend(&buf, &len, pos, ", %s", iface->qualified_name); + pos += append_pointer_stars(&buf, &len, pos, ref->type); + pos += strappend(&buf, &len, pos, " >"); + } + else + { + pos += strappend(&buf, &len, pos, "%s", type->qualified_name); + pos += append_pointer_stars(&buf, &len, pos, ref->type); + } + if (list_next(params, &ref->entry)) pos += strappend(&buf, &len, pos, ", "); + } + pos += strappend(&buf, &len, pos, " >"); + + return buf; } type_t *type_new_function(var_list_t *args) @@ -137,7 +426,7 @@ type_t *type_new_function(var_list_t *args) if (args) { arg = LIST_ENTRY(list_head(args), var_t, entry); - if (list_count(args) == 1 && !arg->name && arg->type && type_get_type(arg->type) == TYPE_VOID) + if (list_count(args) == 1 && !arg->name && arg->declspec.type && type_get_type(arg->declspec.type) == TYPE_VOID) { list_remove(&arg->entry); free(arg); @@ -147,7 +436,7 @@ type_t *type_new_function(var_list_t *args) } if (args) LIST_FOR_EACH_ENTRY(arg, args, var_t, entry) { - if (arg->type && type_get_type(arg->type) == TYPE_VOID) + if (arg->declspec.type && type_get_type(arg->declspec.type) == TYPE_VOID) error_loc("argument '%s' has void type\n", arg->name); if (!arg->name) { @@ -174,58 +463,31 @@ type_t *type_new_function(var_list_t *args) t = make_type(TYPE_FUNCTION); t->details.function = xmalloc(sizeof(*t->details.function)); t->details.function->args = args; - t->details.function->idx = -1; + t->details.function->retval = make_var(xstrdup("_RetVal")); return t; } -type_t *type_new_pointer(unsigned char pointer_default, type_t *ref, attr_list_t *attrs) +type_t *type_new_pointer(type_t *ref) { type_t *t = make_type(TYPE_POINTER); - t->details.pointer.def_fc = pointer_default; - t->details.pointer.ref = ref; - t->attrs = attrs; + t->details.pointer.ref.type = ref; return t; } -type_t *type_new_alias(type_t *t, const char *name) +type_t *type_new_alias(const decl_spec_t *t, const char *name) { - type_t *a = duptype(t, 0); + type_t *a = make_type(TYPE_ALIAS); a->name = xstrdup(name); a->attrs = NULL; - a->orig = t; - a->is_alias = TRUE; - /* for pointer types */ - a->details = t->details; - init_loc_info(&a->loc_info); + a->details.alias.aliasee = *t; + init_location( &a->where, NULL, NULL ); return a; } -type_t *type_new_module(char *name) -{ - type_t *type = get_type(TYPE_MODULE, name, NULL, 0); - if (type->type_type != TYPE_MODULE || type->defined) - error_loc("%s: redefinition error; original definition was at %s:%d\n", - type->name, type->loc_info.input_name, type->loc_info.line_number); - type->name = name; - return type; -} - -type_t *type_new_coclass(char *name) -{ - type_t *type = get_type(TYPE_COCLASS, name, NULL, 0); - if (type->type_type != TYPE_COCLASS || type->defined) - error_loc("%s: redefinition error; original definition was at %s:%d\n", - type->name, type->loc_info.input_name, type->loc_info.line_number); - type->name = name; - return type; -} - - -type_t *type_new_array(const char *name, type_t *element, int declptr, - unsigned int dim, expr_t *size_is, expr_t *length_is, - unsigned char ptr_default_fc) +type_t *type_new_array(const char *name, const decl_spec_t *element, int declptr, + unsigned int dim, expr_t *size_is, expr_t *length_is) { type_t *t = make_type(TYPE_ARRAY); if (name) t->name = xstrdup(name); @@ -235,8 +497,8 @@ type_t *type_new_array(const char *name, type_t *element, int declptr, t->details.array.size_is = size_is; else t->details.array.dim = dim; - t->details.array.elem = element; - t->details.array.ptr_def_fc = ptr_default_fc; + if (element) + t->details.array.elem = *element; return t; } @@ -271,94 +533,123 @@ type_t *type_new_void(void) return void_type; } -type_t *type_new_enum(const char *name, struct namespace *namespace, int defined, var_list_t *enums) +static void define_type(type_t *type, const struct location *where) { - type_t *tag_type = name ? find_type(name, namespace, tsENUM) : NULL; - type_t *t = make_type(TYPE_ENUM); - t->name = name; - t->namespace = namespace; + if (type->defined) + error_loc("type %s already defined at %s:%d\n", type->name, type->where.input_name, type->where.first_line ); - if (tag_type && tag_type->details.enumeration) - t->details.enumeration = tag_type->details.enumeration; - else if (defined) + type->defined = TRUE; + type->defined_in_import = parse_only; + type->where = *where; +} + +type_t *type_new_enum(const char *name, struct namespace *namespace, + int defined, var_list_t *enums, const struct location *where) +{ + type_t *t = NULL; + + if (name) + t = find_type(name, namespace,tsENUM); + + if (!t) + { + t = make_type(TYPE_ENUM); + t->name = name; + t->namespace = namespace; + if (name) + reg_type(t, name, namespace, tsENUM); + } + + if (defined) { t->details.enumeration = xmalloc(sizeof(*t->details.enumeration)); t->details.enumeration->enums = enums; - t->defined = TRUE; + define_type(t, where); } - if (name) - { - if (defined) - reg_type(t, name, namespace, tsENUM); - else - add_incomplete(t); - } return t; } -type_t *type_new_struct(char *name, struct namespace *namespace, int defined, var_list_t *fields) +type_t *type_new_struct(char *name, struct namespace *namespace, + int defined, var_list_t *fields, const struct location *where) { - type_t *tag_type = name ? find_type(name, namespace, tsSTRUCT) : NULL; - type_t *t; + type_t *t = NULL; - /* avoid creating duplicate typelib type entries */ - if (tag_type && do_typelib) return tag_type; - - t = make_type(TYPE_STRUCT); - t->name = name; - t->namespace = namespace; - - if (tag_type && tag_type->details.structure) - t->details.structure = tag_type->details.structure; - else if (defined) - { - t->details.structure = xmalloc(sizeof(*t->details.structure)); - t->details.structure->fields = fields; - t->defined = TRUE; - } if (name) + t = find_type(name, namespace, tsSTRUCT); + + if (!t) { - if (defined) + t = make_type(TYPE_STRUCT); + t->name = name; + t->namespace = namespace; + if (name) reg_type(t, name, namespace, tsSTRUCT); - else - add_incomplete(t); } - return t; -} -type_t *type_new_nonencapsulated_union(const char *name, int defined, var_list_t *fields) -{ - type_t *tag_type = name ? find_type(name, NULL, tsUNION) : NULL; - type_t *t = make_type(TYPE_UNION); - t->name = name; - if (tag_type && tag_type->details.structure) - t->details.structure = tag_type->details.structure; - else if (defined) + if (defined) { t->details.structure = xmalloc(sizeof(*t->details.structure)); t->details.structure->fields = fields; - t->defined = TRUE; - } - if (name) - { - if (defined) - reg_type(t, name, NULL, tsUNION); - else - add_incomplete(t); + define_type(t, where); } + return t; } -type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *union_field, var_list_t *cases) +type_t *type_new_nonencapsulated_union(const char *name, struct namespace *namespace, + int defined, var_list_t *fields, const struct location *where) { - type_t *t = get_type(TYPE_ENCAPSULATED_UNION, name, NULL, tsUNION); - if (!union_field) union_field = make_var( xstrdup("tagged_union") ); - union_field->type = type_new_nonencapsulated_union(NULL, TRUE, cases); + type_t *t = NULL; + + if (name) + t = find_type(name, namespace, tsUNION); + + if (!t) + { + t = make_type(TYPE_UNION); + t->name = name; + t->namespace = namespace; + if (name) + reg_type(t, name, namespace, tsUNION); + } + + if (!t->defined && defined) + { + t->details.structure = xmalloc(sizeof(*t->details.structure)); + t->details.structure->fields = fields; + define_type(t, where); + } + + return t; +} + +type_t *type_new_encapsulated_union(char *name, var_t *switch_field, + var_t *union_field, var_list_t *cases, const struct location *where) +{ + type_t *t = NULL; + + if (name) + t = find_type(name, NULL, tsUNION); + + if (!t) + { + t = make_type(TYPE_ENCAPSULATED_UNION); + t->name = name; + if (name) + reg_type(t, name, NULL, tsUNION); + } + t->type_type = TYPE_ENCAPSULATED_UNION; + + if (!union_field) + union_field = make_var(xstrdup("tagged_union")); + union_field->declspec.type = type_new_nonencapsulated_union(gen_name(), NULL, TRUE, cases, where); + t->details.structure = xmalloc(sizeof(*t->details.structure)); - t->details.structure->fields = append_var( NULL, switch_field ); - t->details.structure->fields = append_var( t->details.structure->fields, union_field ); - t->defined = TRUE; + t->details.structure->fields = append_var(NULL, switch_field); + t->details.structure->fields = append_var(t->details.structure->fields, union_field); + define_type(t, where); + return t; } @@ -413,9 +704,9 @@ type_t *type_new_bitfield(type_t *field, const expr_t *bits) return t; } -static int compute_method_indexes(type_t *iface) +static unsigned int compute_method_indexes(type_t *iface) { - int idx; + unsigned int idx; statement_t *stmt; if (!iface->details.iface) @@ -430,14 +721,28 @@ static int compute_method_indexes(type_t *iface) { var_t *func = stmt->u.var; if (!is_callas(func->attrs)) - func->type->details.function->idx = idx++; + func->func_idx = idx++; } return idx; } -void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts) +type_t *type_interface_declare(char *name, struct namespace *namespace) { + type_t *type = get_type(TYPE_INTERFACE, name, namespace, 0); + if (type_get_type_detect_alias( type ) != TYPE_INTERFACE) + error_loc( "interface %s previously not declared an interface at %s:%d\n", type->name, + type->where.input_name, type->where.first_line ); + return type; +} + +type_t *type_interface_define(type_t *iface, attr_list_t *attrs, type_t *inherit, + statement_list_t *stmts, typeref_list_t *requires, const struct location *where) +{ + if (iface == inherit) + error_loc("interface %s can't inherit from itself\n", + iface->name); + iface->attrs = check_interface_attrs(iface->name, attrs); iface->details.iface = xmalloc(sizeof(*iface->details.iface)); iface->details.iface->disp_props = NULL; iface->details.iface->disp_methods = NULL; @@ -445,12 +750,25 @@ void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stm iface->details.iface->inherit = inherit; iface->details.iface->disp_inherit = NULL; iface->details.iface->async_iface = NULL; - iface->defined = TRUE; + iface->details.iface->requires = requires; + define_type(iface, where); compute_method_indexes(iface); + return iface; } -void type_dispinterface_define(type_t *iface, var_list_t *props, var_list_t *methods) +type_t *type_dispinterface_declare(char *name) { + type_t *type = get_type(TYPE_INTERFACE, name, NULL, 0); + if (type_get_type_detect_alias( type ) != TYPE_INTERFACE) + error_loc( "dispinterface %s previously not declared a dispinterface at %s:%d\n", + type->name, type->where.input_name, type->where.first_line ); + return type; +} + +type_t *type_dispinterface_define(type_t *iface, attr_list_t *attrs, + var_list_t *props, var_list_t *methods, const struct location *where) +{ + iface->attrs = check_dispiface_attrs(iface->name, attrs); iface->details.iface = xmalloc(sizeof(*iface->details.iface)); iface->details.iface->disp_props = props; iface->details.iface->disp_methods = methods; @@ -459,12 +777,16 @@ void type_dispinterface_define(type_t *iface, var_list_t *props, var_list_t *met if (!iface->details.iface->inherit) error_loc("IDispatch is undefined\n"); iface->details.iface->disp_inherit = NULL; iface->details.iface->async_iface = NULL; - iface->defined = TRUE; + iface->details.iface->requires = NULL; + define_type(iface, where); compute_method_indexes(iface); + return iface; } -void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface) +type_t *type_dispinterface_define_from_iface(type_t *dispiface, + attr_list_t *attrs, type_t *iface, const struct location *where) { + dispiface->attrs = check_dispiface_attrs(dispiface->name, attrs); dispiface->details.iface = xmalloc(sizeof(*dispiface->details.iface)); dispiface->details.iface->disp_props = NULL; dispiface->details.iface->disp_methods = NULL; @@ -473,29 +795,535 @@ void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface) if (!dispiface->details.iface->inherit) error_loc("IDispatch is undefined\n"); dispiface->details.iface->disp_inherit = iface; dispiface->details.iface->async_iface = NULL; - dispiface->defined = TRUE; + dispiface->details.iface->requires = NULL; + define_type(dispiface, where); compute_method_indexes(dispiface); + return dispiface; } -void type_module_define(type_t *module, statement_list_t *stmts) +type_t *type_module_declare(char *name) { - if (module->details.module) error_loc("multiple definition error\n"); + type_t *type = get_type(TYPE_MODULE, name, NULL, 0); + if (type_get_type_detect_alias( type ) != TYPE_MODULE) + error_loc( "module %s previously not declared a module at %s:%d\n", type->name, + type->where.input_name, type->where.first_line ); + return type; +} + +type_t *type_module_define(type_t* module, attr_list_t *attrs, + statement_list_t *stmts, const struct location *where) +{ + module->attrs = check_module_attrs(module->name, attrs); module->details.module = xmalloc(sizeof(*module->details.module)); module->details.module->stmts = stmts; - module->defined = TRUE; + define_type(module, where); + return module; } -type_t *type_coclass_define(type_t *coclass, ifref_list_t *ifaces) +type_t *type_coclass_declare(char *name) { + type_t *type = get_type(TYPE_COCLASS, name, NULL, 0); + if (type_get_type_detect_alias( type ) != TYPE_COCLASS) + error_loc( "coclass %s previously not declared a coclass at %s:%d\n", type->name, + type->where.input_name, type->where.first_line ); + return type; +} + +type_t *type_coclass_define(type_t *coclass, attr_list_t *attrs, + typeref_list_t *ifaces, const struct location *where) +{ + coclass->attrs = check_coclass_attrs(coclass->name, attrs); coclass->details.coclass.ifaces = ifaces; - coclass->defined = TRUE; + define_type(coclass, where); return coclass; } +type_t *type_runtimeclass_declare(char *name, struct namespace *namespace) +{ + type_t *type = get_type(TYPE_RUNTIMECLASS, name, namespace, 0); + if (type_get_type_detect_alias( type ) != TYPE_RUNTIMECLASS) + error_loc( "runtimeclass %s previously not declared a runtimeclass at %s:%d\n", type->name, + type->where.input_name, type->where.first_line ); + return type; +} + +type_t *type_runtimeclass_define(type_t *runtimeclass, attr_list_t *attrs, + typeref_list_t *ifaces, const struct location *where) +{ + typeref_t *ref, *required, *tmp; + typeref_list_t *requires; + + runtimeclass->attrs = check_runtimeclass_attrs(runtimeclass->name, attrs); + runtimeclass->details.runtimeclass.ifaces = ifaces; + define_type(runtimeclass, where); + if (!type_runtimeclass_get_default_iface(runtimeclass, FALSE) && + !get_attrp(runtimeclass->attrs, ATTR_STATIC)) + error_loc("runtimeclass %s must have a default interface or static factory\n", runtimeclass->name); + + if (ifaces) LIST_FOR_EACH_ENTRY(ref, ifaces, typeref_t, entry) + { + /* FIXME: this should probably not be allowed, here or in coclass, */ + /* but for now there's too many places in Wine IDL where it is to */ + /* even print a warning. */ + if (!(ref->type->defined)) continue; + if (!(requires = type_iface_get_requires(ref->type))) continue; + LIST_FOR_EACH_ENTRY(required, requires, typeref_t, entry) + { + int found = 0; + + LIST_FOR_EACH_ENTRY(tmp, ifaces, typeref_t, entry) + if ((found = type_is_equal(tmp->type, required->type))) break; + + if (!found) + error_loc("interface '%s' also requires interface '%s', " + "but runtimeclass '%s' does not implement it.\n", + ref->type->name, required->type->name, runtimeclass->name); + } + } + + return runtimeclass; +} + +type_t *type_apicontract_declare(char *name, struct namespace *namespace) +{ + type_t *type = get_type(TYPE_APICONTRACT, name, namespace, 0); + if (type_get_type_detect_alias( type ) != TYPE_APICONTRACT) + error_loc( "apicontract %s previously not declared a apicontract at %s:%d\n", type->name, + type->where.input_name, type->where.first_line ); + return type; +} + +type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs, const struct location *where) +{ + apicontract->attrs = check_apicontract_attrs(apicontract->name, attrs); + define_type(apicontract, where); + return apicontract; +} + +static void compute_delegate_iface_names(type_t *delegate, type_t *type, typeref_list_t *params) +{ + type_t *iface = delegate->details.delegate.iface; + iface->namespace = delegate->namespace; + iface->name = strmake("I%s", delegate->name); + if (type) iface->c_name = format_parameterized_type_c_name(type, params, "I", "_C"); + else iface->c_name = format_namespace(delegate->namespace, "__x_", "_C", iface->name, use_abi_namespace ? "ABI" : NULL); + if (type) iface->param_name = format_parameterized_type_c_name(type, params, "I", "__C"); + else iface->param_name = format_namespace(delegate->namespace, "_", "__C", iface->name, NULL); + iface->qualified_name = format_namespace(delegate->namespace, "", "::", iface->name, use_abi_namespace ? "ABI" : NULL); +} + +type_t *type_delegate_declare(char *name, struct namespace *namespace) +{ + type_t *type = get_type(TYPE_DELEGATE, name, namespace, 0); + if (type_get_type_detect_alias( type ) != TYPE_DELEGATE) + error_loc( "delegate %s previously not declared a delegate at %s:%d\n", type->name, + type->where.input_name, type->where.first_line ); + return type; +} + +type_t *type_delegate_define(type_t *delegate, attr_list_t *attrs, + statement_list_t *stmts, const struct location *where) +{ + type_t *iface; + + delegate->attrs = check_interface_attrs(delegate->name, attrs); + + iface = make_type(TYPE_INTERFACE); + iface->attrs = delegate->attrs; + iface->details.iface = xmalloc(sizeof(*iface->details.iface)); + iface->details.iface->disp_props = NULL; + iface->details.iface->disp_methods = NULL; + iface->details.iface->stmts = stmts; + iface->details.iface->inherit = find_type("IUnknown", NULL, 0); + if (!iface->details.iface->inherit) error_loc("IUnknown is undefined\n"); + iface->details.iface->disp_inherit = NULL; + iface->details.iface->async_iface = NULL; + iface->details.iface->requires = NULL; + define_type(iface, where); + iface->defined = TRUE; + compute_method_indexes(iface); + + delegate->details.delegate.iface = iface; + define_type(delegate, where); + compute_delegate_iface_names(delegate, NULL, NULL); + + return delegate; +} + +type_t *type_parameterized_interface_declare(char *name, struct namespace *namespace, typeref_list_t *params) +{ + type_t *type = get_type(TYPE_PARAMETERIZED_TYPE, name, namespace, 0); + if (type_get_type_detect_alias( type ) != TYPE_PARAMETERIZED_TYPE) + error_loc( "pinterface %s previously not declared a pinterface at %s:%d\n", type->name, + type->where.input_name, type->where.first_line ); + type->details.parameterized.type = make_type(TYPE_INTERFACE); + type->details.parameterized.params = params; + return type; +} + +type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, type_t *inherit, + statement_list_t *stmts, typeref_list_t *requires, const struct location *where) +{ + type_t *iface; + + /* The parameterized type UUID is actually a PIID that is then used as a seed to generate + * a new type GUID with the rules described in: + * https://docs.microsoft.com/en-us/uwp/winrt-cref/winrt-type-system#parameterized-types + * TODO: store type signatures for generated interfaces, and generate their GUIDs + */ + type->attrs = check_interface_attrs(type->name, attrs); + + iface = type->details.parameterized.type; + iface->details.iface = xmalloc(sizeof(*iface->details.iface)); + iface->details.iface->disp_props = NULL; + iface->details.iface->disp_methods = NULL; + iface->details.iface->stmts = stmts; + iface->details.iface->inherit = inherit; + iface->details.iface->disp_inherit = NULL; + iface->details.iface->async_iface = NULL; + iface->details.iface->requires = requires; + + iface->name = type->name; + + define_type(type, where); + return type; +} + +type_t *type_parameterized_delegate_declare(char *name, struct namespace *namespace, typeref_list_t *params) +{ + type_t *type = get_type(TYPE_PARAMETERIZED_TYPE, name, namespace, 0); + if (type_get_type_detect_alias( type ) != TYPE_PARAMETERIZED_TYPE) + error_loc( "pdelegate %s previously not declared a pdelegate at %s:%d\n", type->name, + type->where.input_name, type->where.first_line ); + type->details.parameterized.type = make_type(TYPE_DELEGATE); + type->details.parameterized.params = params; + return type; +} + +type_t *type_parameterized_delegate_define(type_t *type, attr_list_t *attrs, + statement_list_t *stmts, const struct location *where) +{ + type_t *iface, *delegate; + + type->attrs = check_interface_attrs(type->name, attrs); + + delegate = type->details.parameterized.type; + delegate->attrs = type->attrs; + delegate->details.delegate.iface = make_type(TYPE_INTERFACE); + + iface = delegate->details.delegate.iface; + iface->details.iface = xmalloc(sizeof(*iface->details.iface)); + iface->details.iface->disp_props = NULL; + iface->details.iface->disp_methods = NULL; + iface->details.iface->stmts = stmts; + iface->details.iface->inherit = find_type("IUnknown", NULL, 0); + if (!iface->details.iface->inherit) error_loc("IUnknown is undefined\n"); + iface->details.iface->disp_inherit = NULL; + iface->details.iface->async_iface = NULL; + iface->details.iface->requires = NULL; + + delegate->name = type->name; + compute_delegate_iface_names(delegate, type, type->details.parameterized.params); + + define_type(type, where); + return type; +} + +type_t *type_parameterized_type_specialize_partial(type_t *type, typeref_list_t *params) +{ + type_t *new_type = duptype(type, 0); + new_type->details.parameterized.type = type; + new_type->details.parameterized.params = params; + return new_type; +} + +static type_t *replace_type_parameters_in_type(type_t *type, typeref_list_t *orig, typeref_list_t *repl); + +static typeref_list_t *replace_type_parameters_in_type_list(typeref_list_t *list, typeref_list_t *orig, typeref_list_t *repl) +{ + typeref_list_t *new_list = NULL; + typeref_t *ref; + + if (!list) return list; + + LIST_FOR_EACH_ENTRY(ref, list, typeref_t, entry) + { + type_t *new_type = replace_type_parameters_in_type(ref->type, orig, repl); + new_list = append_typeref(new_list, make_typeref(new_type)); + } + + return new_list; +} + +static var_t *replace_type_parameters_in_var(var_t *var, typeref_list_t *orig, typeref_list_t *repl) +{ + var_t *new_var = xmalloc(sizeof(*new_var)); + *new_var = *var; + list_init(&new_var->entry); + new_var->declspec.type = replace_type_parameters_in_type(var->declspec.type, orig, repl); + return new_var; +} + +static var_list_t *replace_type_parameters_in_var_list(var_list_t *var_list, typeref_list_t *orig, typeref_list_t *repl) +{ + var_list_t *new_var_list; + var_t *var, *new_var; + + if (!var_list) return var_list; + + new_var_list = xmalloc(sizeof(*new_var_list)); + list_init(new_var_list); + + LIST_FOR_EACH_ENTRY(var, var_list, var_t, entry) + { + new_var = replace_type_parameters_in_var(var, orig, repl); + list_add_tail(new_var_list, &new_var->entry); + } + + return new_var_list; +} + +static statement_t *replace_type_parameters_in_statement( statement_t *stmt, typeref_list_t *orig, + typeref_list_t *repl, struct location *where ) +{ + statement_t *new_stmt = xmalloc(sizeof(*new_stmt)); + *new_stmt = *stmt; + list_init(&new_stmt->entry); + + switch (stmt->type) + { + case STMT_DECLARATION: + new_stmt->u.var = replace_type_parameters_in_var(stmt->u.var, orig, repl); + break; + case STMT_TYPE: + case STMT_TYPEREF: + new_stmt->u.type = replace_type_parameters_in_type(stmt->u.type, orig, repl); + break; + case STMT_TYPEDEF: + new_stmt->u.type_list = replace_type_parameters_in_type_list(stmt->u.type_list, orig, repl); + break; + case STMT_MODULE: + case STMT_LIBRARY: + case STMT_IMPORT: + case STMT_IMPORTLIB: + case STMT_PRAGMA: + case STMT_CPPQUOTE: + error_at( where, "unimplemented parameterized type replacement for statement type %d.\n", stmt->type ); + break; + } + + return new_stmt; +} + +static statement_list_t *replace_type_parameters_in_statement_list( statement_list_t *stmt_list, typeref_list_t *orig, + typeref_list_t *repl, struct location *where ) +{ + statement_list_t *new_stmt_list; + statement_t *stmt, *new_stmt; + + if (!stmt_list) return stmt_list; + + new_stmt_list = xmalloc(sizeof(*new_stmt_list)); + list_init(new_stmt_list); + + LIST_FOR_EACH_ENTRY(stmt, stmt_list, statement_t, entry) + { + new_stmt = replace_type_parameters_in_statement( stmt, orig, repl, where ); + list_add_tail(new_stmt_list, &new_stmt->entry); + } + + return new_stmt_list; +} + +static type_t *replace_type_parameters_in_type(type_t *type, typeref_list_t *orig, typeref_list_t *repl) +{ + struct list *o, *r; + type_t *t; + + if (!type) return type; + switch (type->type_type) + { + case TYPE_VOID: + case TYPE_BASIC: + case TYPE_ENUM: + case TYPE_BITFIELD: + case TYPE_INTERFACE: + case TYPE_RUNTIMECLASS: + case TYPE_DELEGATE: + case TYPE_STRUCT: + case TYPE_ENCAPSULATED_UNION: + case TYPE_UNION: + return type; + case TYPE_PARAMETER: + if (!orig || !repl) return NULL; + for (o = list_head(orig), r = list_head(repl); o && r; + o = list_next(orig, o), r = list_next(repl, r)) + if (type == LIST_ENTRY(o, typeref_t, entry)->type) + return LIST_ENTRY(r, typeref_t, entry)->type; + return type; + case TYPE_POINTER: + t = replace_type_parameters_in_type(type->details.pointer.ref.type, orig, repl); + if (t == type->details.pointer.ref.type) return type; + type = duptype(type, 0); + type->details.pointer.ref.type = t; + return type; + case TYPE_ALIAS: + t = replace_type_parameters_in_type(type->details.alias.aliasee.type, orig, repl); + if (t == type->details.alias.aliasee.type) return type; + type = duptype(type, 0); + type->details.alias.aliasee.type = t; + return type; + case TYPE_ARRAY: + t = replace_type_parameters_in_type(type->details.array.elem.type, orig, repl); + if (t == t->details.array.elem.type) return type; + type = duptype(type, 0); + t->details.array.elem.type = t; + return type; + case TYPE_FUNCTION: + t = duptype(type, 0); + t->details.function = xmalloc(sizeof(*t->details.function)); + t->details.function->args = replace_type_parameters_in_var_list(type->details.function->args, orig, repl); + t->details.function->retval = replace_type_parameters_in_var(type->details.function->retval, orig, repl); + return t; + case TYPE_PARAMETERIZED_TYPE: + t = type->details.parameterized.type; + if (t->type_type != TYPE_PARAMETERIZED_TYPE) return find_parameterized_type(type, repl); + repl = replace_type_parameters_in_type_list(type->details.parameterized.params, orig, repl); + return replace_type_parameters_in_type(t, t->details.parameterized.params, repl); + case TYPE_MODULE: + case TYPE_COCLASS: + case TYPE_APICONTRACT: + error_at( &type->where, "unimplemented parameterized type replacement for type %s of type %d.\n", + type->name, type->type_type ); + break; + } + + return type; +} + +static void type_parameterized_interface_specialize(type_t *tmpl, type_t *iface, typeref_list_t *orig, typeref_list_t *repl) +{ + iface->details.iface = xmalloc(sizeof(*iface->details.iface)); + iface->details.iface->disp_methods = NULL; + iface->details.iface->disp_props = NULL; + iface->details.iface->stmts = replace_type_parameters_in_statement_list( tmpl->details.iface->stmts, + orig, repl, &tmpl->where ); + iface->details.iface->inherit = replace_type_parameters_in_type(tmpl->details.iface->inherit, orig, repl); + iface->details.iface->disp_inherit = NULL; + iface->details.iface->async_iface = NULL; + iface->details.iface->requires = NULL; +} + +static void type_parameterized_delegate_specialize(type_t *tmpl, type_t *delegate, typeref_list_t *orig, typeref_list_t *repl) +{ + type_parameterized_interface_specialize(tmpl->details.delegate.iface, delegate->details.delegate.iface, orig, repl); +} + +type_t *type_parameterized_type_specialize_declare(type_t *type, typeref_list_t *params) +{ + type_t *tmpl = type->details.parameterized.type; + type_t *new_type = duptype(tmpl, 0); + + new_type->namespace = type->namespace; + new_type->name = format_parameterized_type_name(type, params); + reg_type(new_type, new_type->name, new_type->namespace, 0); + new_type->c_name = format_parameterized_type_c_name(type, params, "", "_C"); + new_type->short_name = format_parameterized_type_short_name(type, params, ""); + new_type->param_name = format_parameterized_type_c_name(type, params, "", "__C"); + + if (new_type->type_type == TYPE_DELEGATE) + { + new_type->details.delegate.iface = duptype(tmpl->details.delegate.iface, 0); + compute_delegate_iface_names(new_type, type, params); + new_type->details.delegate.iface->short_name = format_parameterized_type_short_name(type, params, "I"); + } + + return new_type; +} + +static void compute_interface_signature_uuid(type_t *iface) +{ + static const char winrt_pinterface_namespace[] = {0x11,0xf4,0x7a,0xd5,0x7b,0x73,0x42,0xc0,0xab,0xae,0x87,0x8b,0x1e,0x16,0xad,0xee}; + static const int version = 5; + struct sha1_context ctx; + unsigned char hash[20]; + struct uuid *uuid; + + if (!(uuid = get_attrp(iface->attrs, ATTR_UUID))) + { + uuid = xmalloc(sizeof(*uuid)); + iface->attrs = append_attr( iface->attrs, attr_ptr( iface->where, ATTR_UUID, uuid ) ); + } + + sha1_init(&ctx); + sha1_update(&ctx, winrt_pinterface_namespace, sizeof(winrt_pinterface_namespace)); + sha1_update(&ctx, iface->signature, strlen(iface->signature)); + sha1_finalize(&ctx, (unsigned int *)hash); + + /* https://tools.ietf.org/html/rfc4122: + + * Set the four most significant bits (bits 12 through 15) of the + time_hi_and_version field to the appropriate 4-bit version number + from Section 4.1.3. + + * Set the two most significant bits (bits 6 and 7) of the + clock_seq_hi_and_reserved to zero and one, respectively. + */ + + hash[6] = ((hash[6] & 0x0f) | (version << 4)); + hash[8] = ((hash[8] & 0x3f) | 0x80); + + uuid->Data1 = ((unsigned int)hash[0] << 24) | ((unsigned int)hash[1] << 16) | ((unsigned int)hash[2] << 8) | hash[3]; + uuid->Data2 = ((unsigned short)hash[4] << 8) | hash[5]; + uuid->Data3 = ((unsigned short)hash[6] << 8) | hash[7]; + memcpy(&uuid->Data4, hash + 8, sizeof(*uuid) - offsetof(struct uuid, Data4)); +} + +type_t *type_parameterized_type_specialize_define(type_t *type) +{ + type_t *tmpl = type->details.parameterized.type; + typeref_list_t *orig = tmpl->details.parameterized.params; + typeref_list_t *repl = type->details.parameterized.params; + type_t *iface = find_parameterized_type(tmpl, repl); + + if (type_get_type_detect_alias(type) != TYPE_PARAMETERIZED_TYPE || + type_get_type_detect_alias(tmpl) != TYPE_PARAMETERIZED_TYPE) + error_loc( "cannot define non-parameterized type %s, declared at %s:%d\n", type->name, + type->where.input_name, type->where.first_line ); + + if (type_get_type_detect_alias(tmpl->details.parameterized.type) == TYPE_INTERFACE && + type_get_type_detect_alias(iface) == TYPE_INTERFACE) + type_parameterized_interface_specialize(tmpl->details.parameterized.type, iface, orig, repl); + else if (type_get_type_detect_alias(tmpl->details.parameterized.type) == TYPE_DELEGATE && + type_get_type_detect_alias(iface) == TYPE_DELEGATE) + type_parameterized_delegate_specialize(tmpl->details.parameterized.type, iface, orig, repl); + else + error_loc("pinterface/pdelegate %s previously not declared a pinterface/pdelegate at %s:%d\n", + iface->name, iface->where.input_name, iface->where.first_line); + + iface->impl_name = format_parameterized_type_impl_name(type, repl, ""); + iface->signature = format_parameterized_type_signature(type, repl); + iface->defined = TRUE; + if (iface->type_type == TYPE_DELEGATE) + { + iface = iface->details.delegate.iface; + iface->impl_name = format_parameterized_type_impl_name(type, repl, "I"); + iface->signature = format_parameterized_type_signature(type, repl); + iface->defined = TRUE; + } + compute_interface_signature_uuid(iface); + compute_method_indexes(iface); + return iface; +} + int type_is_equal(const type_t *type1, const type_t *type2) { + if (type1 == type2) + return TRUE; if (type_get_type_detect_alias(type1) != type_get_type_detect_alias(type2)) return FALSE; + if (type1->namespace != type2->namespace) + return FALSE; if (type1->name && type2->name) return !strcmp(type1->name, type2->name); diff --git a/sdk/tools/widl/typetree.h b/sdk/tools/widl/typetree.h index fc134cd575d..e9536a26ad5 100644 --- a/sdk/tools/widl/typetree.h +++ b/sdk/tools/widl/typetree.h @@ -20,6 +20,9 @@ #include "widltypes.h" #include +#include + +#include "utils.h" #ifndef WIDL_TYPE_TREE_H #define WIDL_TYPE_TREE_H @@ -29,29 +32,63 @@ enum name_type { NAME_C }; +type_t *find_parameterized_type(type_t *type, typeref_list_t *params); + type_t *type_new_function(var_list_t *args); -type_t *type_new_pointer(unsigned char pointer_default, type_t *ref, attr_list_t *attrs); -type_t *type_new_alias(type_t *t, const char *name); -type_t *type_new_module(char *name); -type_t *type_new_array(const char *name, type_t *element, int declptr, - unsigned int dim, expr_t *size_is, expr_t *length_is, - unsigned char ptr_default_fc); +type_t *type_new_pointer(type_t *ref); +type_t *type_new_alias(const decl_spec_t *t, const char *name); +type_t *type_module_declare(char *name); +type_t *type_new_array(const char *name, const decl_spec_t *element, int declptr, + unsigned int dim, expr_t *size_is, expr_t *length_is); type_t *type_new_basic(enum type_basic_type basic_type); type_t *type_new_int(enum type_basic_type basic_type, int sign); type_t *type_new_void(void); -type_t *type_new_coclass(char *name); -type_t *type_new_enum(const char *name, struct namespace *namespace, int defined, var_list_t *enums); -type_t *type_new_struct(char *name, struct namespace *namespace, int defined, var_list_t *fields); -type_t *type_new_nonencapsulated_union(const char *name, int defined, var_list_t *fields); -type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *union_field, var_list_t *cases); +type_t *type_coclass_declare(char *name); +type_t *type_new_enum(const char *name, struct namespace *namespace, + int defined, var_list_t *enums, const struct location *where); +type_t *type_new_struct(char *name, struct namespace *namespace, + int defined, var_list_t *fields, const struct location *where); +type_t *type_new_nonencapsulated_union(const char *name, struct namespace *namespace, + int defined, var_list_t *fields, const struct location *where); +type_t *type_new_encapsulated_union(char *name, var_t *switch_field, + var_t *union_field, var_list_t *cases, const struct location *where); type_t *type_new_bitfield(type_t *field_type, const expr_t *bits); -void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts); -void type_dispinterface_define(type_t *iface, var_list_t *props, var_list_t *methods); -void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface); -void type_module_define(type_t *module, statement_list_t *stmts); -type_t *type_coclass_define(type_t *coclass, ifref_list_t *ifaces); +type_t *type_runtimeclass_declare(char *name, struct namespace *namespace); +type_t *type_interface_declare(char *name, struct namespace *namespace); +type_t *type_interface_define(type_t *iface, attr_list_t *attrs, type_t *inherit, + statement_list_t *stmts, typeref_list_t *requires, const struct location *where); +type_t *type_dispinterface_declare(char *name); +type_t *type_dispinterface_define(type_t *iface, attr_list_t *attrs, + var_list_t *props, var_list_t *methods, const struct location *where); +type_t *type_dispinterface_define_from_iface(type_t *dispiface, + attr_list_t *attrs, type_t *iface, const struct location *where); +type_t *type_module_define(type_t* module, attr_list_t *attrs, + statement_list_t *stmts, const struct location *where); +type_t *type_coclass_define(type_t *coclass, attr_list_t *attrs, + typeref_list_t *ifaces, const struct location *where); +type_t *type_runtimeclass_define(type_t *runtimeclass, attr_list_t *attrs, + typeref_list_t *ifaces, const struct location *where); +type_t *type_apicontract_declare(char *name, struct namespace *namespace); +type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs, const struct location *where); +type_t *type_delegate_declare(char *name, struct namespace *namespace); +type_t *type_delegate_define(type_t *delegate, attr_list_t *attrs, + statement_list_t *stmts, const struct location *where); +type_t *type_parameterized_interface_declare(char *name, struct namespace *namespace, typeref_list_t *params); +type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, type_t *inherit, + statement_list_t *stmts, typeref_list_t *requires, const struct location *where); +type_t *type_parameterized_delegate_declare(char *name, struct namespace *namespace, typeref_list_t *params); +type_t *type_parameterized_delegate_define(type_t *type, attr_list_t *attrs, + statement_list_t *stmts, const struct location *where); +type_t *type_parameterized_type_specialize_partial(type_t *type, typeref_list_t *params); +type_t *type_parameterized_type_specialize_declare(type_t *type, typeref_list_t *params); +type_t *type_parameterized_type_specialize_define(type_t *type); int type_is_equal(const type_t *type1, const type_t *type2); +const char *type_get_decl_name(const type_t *type, enum name_type name_type); const char *type_get_name(const type_t *type, enum name_type name_type); +char *gen_name(void); + +typeref_t *make_typeref(type_t *type); +typeref_list_t *append_typeref(typeref_list_t *list, typeref_t *ref); /* FIXME: shouldn't need to export this */ type_t *duptype(type_t *t, int dupname); @@ -59,8 +96,16 @@ type_t *duptype(type_t *t, int dupname); /* un-alias the type until finding the non-alias type */ static inline type_t *type_get_real_type(const type_t *type) { - if (type->is_alias) - return type_get_real_type(type->orig); + if (type->type_type == TYPE_ALIAS) + return type_get_real_type(type->details.alias.aliasee.type); + else + return (type_t *)type; +} + +static inline type_t *type_parameterized_type_get_real_type(const type_t *type) +{ + if (type->type_type == TYPE_PARAMETERIZED_TYPE) + return type_parameterized_type_get_real_type(type->details.parameterized.type); else return (type_t *)type; } @@ -105,9 +150,14 @@ static inline var_t *type_function_get_retval(const type_t *type) return type->details.function->retval; } +static inline const decl_spec_t *type_function_get_ret(const type_t *type) +{ + return &type_function_get_retval(type)->declspec; +} + static inline type_t *type_function_get_rettype(const type_t *type) { - return type_function_get_retval(type)->type; + return type_function_get_retval(type)->declspec.type; } static inline var_list_t *type_enum_get_values(const type_t *type) @@ -142,7 +192,7 @@ static inline var_list_t *type_union_get_cases(const type_t *type) if (type_type == TYPE_ENCAPSULATED_UNION) { const var_t *uv = LIST_ENTRY(list_tail(type->details.structure->fields), const var_t, entry); - return uv->type->details.structure->fields; + return uv->declspec.type->details.structure->fields; } else return type->details.structure->fields; @@ -162,6 +212,20 @@ static inline type_t *type_iface_get_inherit(const type_t *type) return type->details.iface->inherit; } +static inline typeref_list_t *type_iface_get_requires(const type_t *type) +{ + type = type_get_real_type(type); + assert(type_get_type(type) == TYPE_INTERFACE); + return type->details.iface->requires; +} + +static inline type_t *type_iface_get_async_iface(const type_t *type) +{ + type = type_get_real_type(type); + assert(type_get_type(type) == TYPE_INTERFACE); + return type->details.iface->async_iface; +} + static inline var_list_t *type_dispiface_get_props(const type_t *type) { type = type_get_real_type(type); @@ -210,7 +274,14 @@ static inline int type_is_complete(const type_t *type) case TYPE_POINTER: case TYPE_ARRAY: case TYPE_BITFIELD: + case TYPE_RUNTIMECLASS: + case TYPE_DELEGATE: return TRUE; + case TYPE_APICONTRACT: + case TYPE_PARAMETERIZED_TYPE: + case TYPE_PARAMETER: + assert(0); + break; } return FALSE; } @@ -250,11 +321,30 @@ static inline expr_t *type_array_get_variance(const type_t *type) return type->details.array.length_is; } -static inline type_t *type_array_get_element(const type_t *type) +static inline unsigned short type_array_get_ptr_tfsoff(const type_t *type) { type = type_get_real_type(type); assert(type_get_type(type) == TYPE_ARRAY); - return type->details.array.elem; + return type->details.array.ptr_tfsoff; +} + +static inline void type_array_set_ptr_tfsoff(type_t *type, unsigned short ptr_tfsoff) +{ + type = type_get_real_type(type); + assert(type_get_type(type) == TYPE_ARRAY); + type->details.array.ptr_tfsoff = ptr_tfsoff; +} + +static inline const decl_spec_t *type_array_get_element(const type_t *type) +{ + type = type_get_real_type(type); + assert(type_get_type(type) == TYPE_ARRAY); + return &type->details.array.elem; +} + +static inline type_t *type_array_get_element_type(const type_t *type) +{ + return type_array_get_element(type)->type; } static inline int type_array_is_decl_as_ptr(const type_t *type) @@ -264,43 +354,82 @@ static inline int type_array_is_decl_as_ptr(const type_t *type) return type->details.array.declptr; } -static inline unsigned char type_array_get_ptr_default_fc(const type_t *type) -{ - type = type_get_real_type(type); - assert(type_get_type(type) == TYPE_ARRAY); - return type->details.array.ptr_def_fc; -} - static inline int type_is_alias(const type_t *type) { - return type->is_alias; + return type->type_type == TYPE_ALIAS; } -static inline type_t *type_alias_get_aliasee(const type_t *type) +static inline int type_is_ptr( const type_t *type ) +{ + return type->type_type == TYPE_POINTER; +} + +static inline const decl_spec_t *type_alias_get_aliasee(const type_t *type) { assert(type_is_alias(type)); - return type->orig; + return &type->details.alias.aliasee; } -static inline ifref_list_t *type_coclass_get_ifaces(const type_t *type) +static inline type_t *type_alias_get_aliasee_type(const type_t *type) +{ + assert(type_is_alias(type)); + return type->details.alias.aliasee.type; +} + +static inline typeref_list_t *type_coclass_get_ifaces(const type_t *type) { type = type_get_real_type(type); assert(type_get_type(type) == TYPE_COCLASS); return type->details.coclass.ifaces; } -static inline type_t *type_pointer_get_ref(const type_t *type) +static inline typeref_list_t *type_runtimeclass_get_ifaces(const type_t *type) { type = type_get_real_type(type); - assert(type_get_type(type) == TYPE_POINTER); - return type->details.pointer.ref; + assert(type_get_type(type) == TYPE_RUNTIMECLASS); + return type->details.runtimeclass.ifaces; } -static inline unsigned char type_pointer_get_default_fc(const type_t *type) +static inline type_t *type_runtimeclass_get_default_iface(const type_t *type, int check) +{ + typeref_list_t *ifaces = type_runtimeclass_get_ifaces(type); + typeref_t *ref; + + if (ifaces) LIST_FOR_EACH_ENTRY(ref, ifaces, typeref_t, entry) + if (is_attr(ref->attrs, ATTR_DEFAULT)) + return ref->type; + + if (!check) return NULL; + error_at( &type->where, "runtimeclass %s needs a default interface\n", type->name ); + +#ifdef __REACTOS__ + return NULL; +#endif +} + +static inline type_t *type_delegate_get_iface(const type_t *type) +{ + type = type_get_real_type(type); + assert(type_get_type(type) == TYPE_DELEGATE); + return type->details.delegate.iface; +} + +static inline const decl_spec_t *type_pointer_get_ref(const type_t *type) { type = type_get_real_type(type); assert(type_get_type(type) == TYPE_POINTER); - return type->details.pointer.def_fc; + return &type->details.pointer.ref; +} + +static inline type_t *type_pointer_get_ref_type(const type_t *type) +{ + return type_pointer_get_ref(type)->type; +} + +static inline type_t *type_pointer_get_root_type(type_t *type) +{ + for (; type && type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) {} + return type; } static inline type_t *type_bitfield_get_field(const type_t *type) diff --git a/sdk/tools/widl/utils.c b/sdk/tools/widl/utils.c index 90668873aac..4f2e9d3d602 100644 --- a/sdk/tools/widl/utils.c +++ b/sdk/tools/widl/utils.c @@ -20,7 +20,6 @@ */ #include "config.h" -#include "wine/port.h" #include #include @@ -33,72 +32,17 @@ #include "utils.h" #include "parser.h" -#define CURRENT_LOCATION { input_name ? input_name : "stdin", line_number, parser_text } - -static const int want_near_indication = 0; - -static void make_print(char *str) +void error_at( const struct location *where, const char *s, ... ) { - while(*str) - { - if(!isprint(*str)) - *str = ' '; - str++; - } -} + char buffer[1024]; -static void generic_msg(const loc_info_t *loc_info, const char *s, const char *t, va_list ap) -{ - fprintf(stderr, "%s:%d: %s: ", loc_info->input_name, loc_info->line_number, t); - vfprintf(stderr, s, ap); + va_list ap; + va_start( ap, s ); + vsnprintf( buffer, sizeof(buffer), s, ap ); + va_end( ap ); - if (want_near_indication) - { - char *cpy; - if(loc_info->near_text) - { - cpy = xstrdup(loc_info->near_text); - make_print(cpy); - fprintf(stderr, " near '%s'", cpy); - free(cpy); - } - } -} - - -void error_loc(const char *s, ...) -{ - loc_info_t cur_loc = CURRENT_LOCATION; - va_list ap; - va_start(ap, s); - generic_msg(&cur_loc, s, "error", ap); - va_end(ap); - exit(1); -} - -/* yyerror: yacc assumes this is not newline terminated. */ -void parser_error(const char *s) -{ - error_loc("%s\n", s); -} - -void error_loc_info(const loc_info_t *loc_info, const char *s, ...) -{ - va_list ap; - va_start(ap, s); - generic_msg(loc_info, s, "error", ap); - va_end(ap); - exit(1); -} - -int parser_warning(const char *s, ...) -{ - loc_info_t cur_loc = CURRENT_LOCATION; - va_list ap; - va_start(ap, s); - generic_msg(&cur_loc, s, "warning", ap); - va_end(ap); - return 0; + parser_error( where, buffer ); + exit( 1 ); } void error(const char *s, ...) @@ -120,12 +64,16 @@ void warning(const char *s, ...) va_end(ap); } -void warning_loc_info(const loc_info_t *loc_info, const char *s, ...) +void warning_at( const struct location *where, const char *s, ... ) { - va_list ap; - va_start(ap, s); - generic_msg(loc_info, s, "warning", ap); - va_end(ap); + char buffer[1024]; + + va_list ap; + va_start( ap, s ); + vsnprintf( buffer, sizeof(buffer), s, ap ); + va_end( ap ); + + parser_warning( where, buffer ); } void chat(const char *s, ...) @@ -140,35 +88,6 @@ void chat(const char *s, ...) } } -char *dup_basename(const char *name, const char *ext) -{ - int namelen; - int extlen = strlen(ext); - char *base; - char *slash; - - if(!name) - name = "widl.tab"; - - slash = strrchr(name, '/'); - if (!slash) - slash = strrchr(name, '\\'); - - if (slash) - name = slash + 1; - - namelen = strlen(name); - - /* +6 for later extension (strlen("_r.rgs")) and +1 for '\0' */ - base = xmalloc(namelen +6 +1); - strcpy(base, name); - if(!strcasecmp(name + namelen-extlen, ext)) - { - base[namelen - extlen] = '\0'; - } - return base; -} - size_t widl_getline(char **linep, size_t *lenp, FILE *fp) { char *line = *linep; @@ -198,48 +117,41 @@ size_t widl_getline(char **linep, size_t *lenp, FILE *fp) return n; } -void *xmalloc(size_t size) +size_t strappend(char **buf, size_t *len, size_t pos, const char* fmt, ...) { - void *res; + size_t size; + va_list ap; + char *ptr; + int n; - assert(size > 0); - res = malloc(size); - if(res == NULL) + assert( buf && len ); + assert( (*len == 0 && *buf == NULL) || (*len != 0 && *buf != NULL) ); + + if (*buf) { - error("Virtual memory exhausted.\n"); + size = *len; + ptr = *buf; } - memset(res, 0x55, size); - return res; -} - - -void *xrealloc(void *p, size_t size) -{ - void *res; - - assert(size > 0); - res = realloc(p, size); - if(res == NULL) + else { - error("Virtual memory exhausted.\n"); + size = 100; + ptr = xmalloc( size ); } - return res; -} -char *xstrdup(const char *str) -{ - char *s; + for (;;) + { + va_start( ap, fmt ); + n = vsnprintf( ptr + pos, size - pos, fmt, ap ); + va_end( ap ); + if (n == -1) size *= 2; + else if (pos + (size_t)n >= size) size = pos + n + 1; + else break; + ptr = xrealloc( ptr, size ); + } - assert(str != NULL); - s = xmalloc(strlen(str)+1); - return strcpy(s, str); -} - -int strendswith(const char* str, const char* end) -{ - int l = strlen(str); - int m = strlen(end); - return l >= m && strcmp(str + l - m, end) == 0; + *len = size; + *buf = ptr; + return n; } /******************************************************************* @@ -248,7 +160,6 @@ int strendswith(const char* str, const char* end) * Function for writing to a memory buffer. */ -int byte_swapped = 0; unsigned char *output_buffer; size_t output_buffer_pos; size_t output_buffer_size; @@ -260,32 +171,6 @@ static struct resource } resources[16]; static unsigned int nb_resources; -static void check_output_buffer_space( size_t size ) -{ - if (output_buffer_pos + size >= output_buffer_size) - { - output_buffer_size = max( output_buffer_size * 2, output_buffer_pos + size ); - output_buffer = xrealloc( output_buffer, output_buffer_size ); - } -} - -void init_output_buffer(void) -{ - output_buffer_size = 1024; - output_buffer_pos = 0; - output_buffer = xmalloc( output_buffer_size ); -} - -void flush_output_buffer( const char *name ) -{ - int fd = open( name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666 ); - if (fd == -1) error( "Error creating %s\n", name ); - if (write( fd, output_buffer, output_buffer_pos ) != output_buffer_pos) - error( "Error writing to %s\n", name ); - close( fd ); - free( output_buffer ); -} - static inline void put_resource_id( const char *str ) { if (str[0] != '#') @@ -309,7 +194,7 @@ void add_output_to_resources( const char *type, const char *name ) size_t data_size = output_buffer_pos; size_t header_size = 5 * sizeof(unsigned int) + 2 * sizeof(unsigned short); - assert( nb_resources < sizeof(resources)/sizeof(resources[0]) ); + assert( nb_resources < ARRAY_SIZE( resources )); if (type[0] != '#') header_size += (strlen( type ) + 1) * sizeof(unsigned short); else header_size += 2 * sizeof(unsigned short); @@ -340,7 +225,6 @@ void add_output_to_resources( const char *type, const char *name ) void flush_output_resources( const char *name ) { - int fd; unsigned int i; /* all output must have been saved with add_output_to_resources() first */ @@ -358,59 +242,13 @@ void flush_output_resources( const char *name ) put_dword( 0 ); /* Version */ put_dword( 0 ); /* Characteristics */ - fd = open( name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666 ); - if (fd == -1) error( "Error creating %s\n", name ); - if (write( fd, output_buffer, output_buffer_pos ) != output_buffer_pos) - error( "Error writing to %s\n", name ); for (i = 0; i < nb_resources; i++) { - if (write( fd, resources[i].data, resources[i].size ) != resources[i].size) - error( "Error writing to %s\n", name ); + put_data( resources[i].data, resources[i].size ); free( resources[i].data ); } - close( fd ); + flush_output_buffer( name ); nb_resources = 0; - free( output_buffer ); -} - -void put_data( const void *data, size_t size ) -{ - check_output_buffer_space( size ); - memcpy( output_buffer + output_buffer_pos, data, size ); - output_buffer_pos += size; -} - -void put_byte( unsigned char val ) -{ - check_output_buffer_space( 1 ); - output_buffer[output_buffer_pos++] = val; -} - -void put_word( unsigned short val ) -{ - if (byte_swapped) val = (val << 8) | (val >> 8); - put_data( &val, sizeof(val) ); -} - -void put_dword( unsigned int val ) -{ - if (byte_swapped) - val = ((val << 24) | ((val << 8) & 0x00ff0000) | ((val >> 8) & 0x0000ff00) | (val >> 24)); - put_data( &val, sizeof(val) ); -} - -void put_qword( unsigned int val ) -{ - if (byte_swapped) - { - put_dword( 0 ); - put_dword( val ); - } - else - { - put_dword( val ); - put_dword( 0 ); - } } /* pointer-sized word */ @@ -445,13 +283,3 @@ void put_str( int indent, const char *format, ... ) check_output_buffer_space( size ); } } - -void align_output( unsigned int align ) -{ - size_t size = align - (output_buffer_pos % align); - - if (size == align) return; - check_output_buffer_space( size ); - memset( output_buffer + output_buffer_pos, 0, size ); - output_buffer_pos += size; -} diff --git a/sdk/tools/widl/utils.h b/sdk/tools/widl/utils.h index ec02fc7c372..2a6bc7d7930 100644 --- a/sdk/tools/widl/utils.h +++ b/sdk/tools/widl/utils.h @@ -22,52 +22,25 @@ #define __WIDL_UTILS_H #include "widltypes.h" +#include "parser.h" -#include /* size_t */ - -void *xmalloc(size_t); -void *xrealloc(void *, size_t); -char *xstrdup(const char *str); -int strendswith(const char* str, const char* end); - -#ifndef __GNUC__ -#define __attribute__(X) -#endif - -void parser_error(const char *s) __attribute__((noreturn)); -int parser_warning(const char *s, ...) __attribute__((format (printf, 1, 2))); -void error_loc(const char *s, ...) __attribute__((format (printf, 1, 2))) __attribute__((noreturn)); void error(const char *s, ...) __attribute__((format (printf, 1, 2))) __attribute__((noreturn)); -void error_loc_info(const loc_info_t *, const char *s, ...) __attribute__((format (printf, 2, 3))) __attribute__((noreturn)); +void error_at( const struct location *, const char *s, ... ) __attribute__((format( printf, 2, 3 ))) __attribute__((noreturn)); +#define error_loc( ... ) error_at( NULL, ## __VA_ARGS__ ) void warning(const char *s, ...) __attribute__((format (printf, 1, 2))); -void warning_loc_info(const loc_info_t *, const char *s, ...) __attribute__((format (printf, 2, 3))); +void warning_at( const struct location *, const char *s, ... ) __attribute__((format( printf, 2, 3 ))); +#define warning_loc( ... ) warning_at( NULL, ## __VA_ARGS__ ) void chat(const char *s, ...) __attribute__((format (printf, 1, 2))); +size_t strappend(char **buf, size_t *len, size_t pos, const char* fmt, ...) __attribute__((__format__ (__printf__, 4, 5 ))); -char *dup_basename(const char *name, const char *ext); size_t widl_getline(char **linep, size_t *lenp, FILE *fp); -UUID *parse_uuid(const char *u); -int is_valid_uuid(const char *s); - /* buffer management */ -extern int byte_swapped; -extern unsigned char *output_buffer; -extern size_t output_buffer_pos; -extern size_t output_buffer_size; - -extern void init_output_buffer(void); -extern void flush_output_buffer( const char *name ); extern void add_output_to_resources( const char *type, const char *name ); extern void flush_output_resources( const char *name ); -extern void put_data( const void *data, size_t size ); -extern void put_byte( unsigned char val ); -extern void put_word( unsigned short val ); -extern void put_dword( unsigned int val ); -extern void put_qword( unsigned int val ); extern void put_pword( unsigned int val ); extern void put_str( int indent, const char *format, ... ) __attribute__((format (printf, 2, 3))); -extern void align_output( unsigned int align ); /* typelibs expect the minor version to be stored in the higher bits and * major to be stored in the lower bits */ @@ -75,11 +48,4 @@ extern void align_output( unsigned int align ); #define MAJORVERSION(version) ((version) & 0xffff) #define MINORVERSION(version) (((version) >> 16) & 0xffff) -#ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif -#ifndef min -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - #endif diff --git a/sdk/tools/widl/widl.c b/sdk/tools/widl/widl.c index 77d4b7750a9..19348c70dc3 100644 --- a/sdk/tools/widl/widl.c +++ b/sdk/tools/widl/widl.c @@ -20,33 +20,28 @@ */ #include "config.h" -#include "wine/port.h" #include #include #include #include -#ifdef HAVE_UNISTD_H -# include -#endif #include #include #include -#include -#ifdef HAVE_GETOPT_H -# include -#endif +#include +#include #include "widl.h" #include "utils.h" #include "parser.h" -#include "wine/wpp.h" +#include "wpp_private.h" #include "header.h" static const char usage[] = "Usage: widl [options...] infile.idl\n" " or: widl [options...] --dlldata-only name1 [name2...]\n" " --acf=file Use ACF file\n" +" --align=n Set structure packing to 'n'\n" " -app_config Ignored, present for midl compatibility\n" " -b arch Set the target architecture\n" " -c Generate client stub\n" @@ -56,30 +51,32 @@ static const char usage[] = " --help Display this help and exit\n" " -h Generate headers\n" " -H file Name of header file (default is infile.h)\n" -" -I path Set include search dir to path (multiple -I allowed)\n" +" -I directory Add directory to the include search path (multiple -I allowed)\n" +" -L directory Add directory to the library search path (multiple -L allowed)\n" " --local-stubs=file Write empty stubs for call_as/local methods to file\n" " -m32, -m64 Set the target architecture (Win32 or Win64)\n" " -N Do not preprocess input\n" +" --nostdinc Do not search the standard include path\n" +" --ns_prefix Prefix namespaces with ABI namespace\n" " --oldnames Use old naming conventions\n" -" --oldtlb Use old typelib (SLTG) format\n" +" --oldtlb Generate typelib in the old format (SLTG)\n" " -o, --output=NAME Set the output file name\n" " -Otype Type of stubs to generate (-Os, -Oi, -Oif)\n" " -p Generate proxy\n" +" --packing=n Set structure packing to 'n'\n" " --prefix-all=p Prefix names of client stubs / server functions with 'p'\n" " --prefix-client=p Prefix names of client stubs with 'p'\n" " --prefix-server=p Prefix names of server functions with 'p'\n" " -r Generate registration script\n" " -robust Ignored, present for midl compatibility\n" -" --winrt Enable Windows Runtime mode\n" -" --ns_prefix Prefix namespaces with ABI namespace\n" +" --sysroot=DIR Prefix include paths with DIR\n" " -s Generate server stub\n" " -t Generate typelib\n" " -u Generate interface identifiers file\n" " -V Print version and exit\n" " -W Enable pedantic warnings\n" " --win32, --win64 Set the target architecture (Win32 or Win64)\n" -" --win32-align n Set win32 structure alignment to 'n'\n" -" --win64-align n Set win64 structure alignment to 'n'\n" +" --winrt Enable Windows Runtime mode\n" "Debug level 'n' is a bitmask with following meaning:\n" " * 0x01 Tell which resource is parsed (verbose mode)\n" " * 0x02 Dump internal structures\n" @@ -92,19 +89,7 @@ static const char usage[] = static const char version_string[] = "Wine IDL Compiler version " PACKAGE_VERSION "\n" "Copyright 2002 Ove Kaaven\n"; -#ifdef __i386__ -enum target_cpu target_cpu = CPU_x86; -#elif defined(__x86_64__) -enum target_cpu target_cpu = CPU_x86_64; -#elif defined(__powerpc__) -enum target_cpu target_cpu = CPU_POWERPC; -#elif defined(__arm__) -enum target_cpu target_cpu = CPU_ARM; -#elif defined(__aarch64__) -enum target_cpu target_cpu = CPU_ARM64; -#else -#error Unsupported CPU -#endif +struct target target = { 0 }; int debuglevel = DEBUGLEVEL_NONE; int parser_debug, yy_flex_debug; @@ -114,7 +99,6 @@ int do_everything = 1; static int preprocess_only = 0; int do_header = 0; int do_typelib = 0; -int do_old_typelib = 0; int do_proxies = 0; int do_client = 0; int do_server = 0; @@ -123,14 +107,14 @@ int do_idfile = 0; int do_dlldata = 0; static int no_preprocess = 0; int old_names = 0; -int win32_packing = 8; -int win64_packing = 8; +int old_typelib = 0; int winrt_mode = 0; +int interpreted_mode = 1; int use_abi_namespace = 0; -static enum stub_mode stub_mode = MODE_Os; +static int stdinc = 1; char *input_name; -char *input_idl_name; +char *idl_name; char *acf_name; char *header_name; char *local_stubs_name; @@ -146,14 +130,20 @@ char *server_token; char *regscript_name; char *regscript_token; static char *idfile_name; -char *temp_name; +struct strarray temp_files = { 0 }; +const char *temp_dir = NULL; const char *prefix_client = ""; const char *prefix_server = ""; - -int line_number = 1; +static const char *bindir; +static const char *libdir; +static const char *includedir; +static struct strarray dlldirs; +static char *output_name; +static const char *sysroot = ""; static FILE *idfile; +unsigned int packing = 8; unsigned int pointer_size = 0; time_t now; @@ -165,7 +155,9 @@ enum { DLLDATA_OPTION, DLLDATA_ONLY_OPTION, LOCAL_STUBS_OPTION, + NOSTDINC_OPTION, OLD_TYPELIB_OPTION, + PACKING_OPTION, PREFIX_ALL_OPTION, PREFIX_CLIENT_OPTION, PREFIX_SERVER_OPTION, @@ -173,60 +165,47 @@ enum { RT_NS_PREFIX, RT_OPTION, ROBUST_OPTION, + SYSROOT_OPTION, WIN32_OPTION, WIN64_OPTION, - WIN32_ALIGN_OPTION, - WIN64_ALIGN_OPTION }; static const char short_options[] = - "b:cC:d:D:EhH:I:m:No:O:pP:rsS:tT:uU:VW"; -static const struct option long_options[] = { - { "acf", 1, NULL, ACF_OPTION }, - { "app_config", 0, NULL, APP_CONFIG_OPTION }, - { "dlldata", 1, NULL, DLLDATA_OPTION }, - { "dlldata-only", 0, NULL, DLLDATA_ONLY_OPTION }, - { "help", 0, NULL, PRINT_HELP }, - { "local-stubs", 1, NULL, LOCAL_STUBS_OPTION }, - { "ns_prefix", 0, NULL, RT_NS_PREFIX }, - { "oldnames", 0, NULL, OLDNAMES_OPTION }, - { "oldtlb", 0, NULL, OLD_TYPELIB_OPTION }, - { "output", 0, NULL, 'o' }, - { "prefix-all", 1, NULL, PREFIX_ALL_OPTION }, - { "prefix-client", 1, NULL, PREFIX_CLIENT_OPTION }, - { "prefix-server", 1, NULL, PREFIX_SERVER_OPTION }, - { "robust", 0, NULL, ROBUST_OPTION }, - { "target", 0, NULL, 'b' }, - { "winrt", 0, NULL, RT_OPTION }, - { "win32", 0, NULL, WIN32_OPTION }, - { "win64", 0, NULL, WIN64_OPTION }, - { "win32-align", 1, NULL, WIN32_ALIGN_OPTION }, - { "win64-align", 1, NULL, WIN64_ALIGN_OPTION }, - { NULL, 0, NULL, 0 } + "b:cC:d:D:EhH:I:L:m:No:O:pP:rsS:tT:uU:VW"; +static const struct long_option long_options[] = { + { "acf", 1, ACF_OPTION }, + { "align", 1, PACKING_OPTION }, + { "app_config", 0, APP_CONFIG_OPTION }, + { "dlldata", 1, DLLDATA_OPTION }, + { "dlldata-only", 0, DLLDATA_ONLY_OPTION }, + { "help", 0, PRINT_HELP }, + { "local-stubs", 1, LOCAL_STUBS_OPTION }, + { "nostdinc", 0, NOSTDINC_OPTION }, + { "ns_prefix", 0, RT_NS_PREFIX }, + { "oldnames", 0, OLDNAMES_OPTION }, + { "oldtlb", 0, OLD_TYPELIB_OPTION }, + { "output", 0, 'o' }, + { "packing", 1, PACKING_OPTION }, + { "prefix-all", 1, PREFIX_ALL_OPTION }, + { "prefix-client", 1, PREFIX_CLIENT_OPTION }, + { "prefix-server", 1, PREFIX_SERVER_OPTION }, + { "robust", 0, ROBUST_OPTION }, + { "sysroot", 1, SYSROOT_OPTION }, + { "target", 0, 'b' }, + { "winrt", 0, RT_OPTION }, + { "win32", 0, WIN32_OPTION }, + { "win64", 0, WIN64_OPTION }, + { NULL } }; static void rm_tempfile(void); -enum stub_mode get_stub_mode(void) -{ - /* old-style interpreted stubs are not supported on 64-bit */ - if (stub_mode == MODE_Oi && pointer_size == 8) return MODE_Oif; - return stub_mode; -} - static char *make_token(const char *name) { char *token; - char *slash; int i; - slash = strrchr(name, '/'); - if(!slash) - slash = strrchr(name, '\\'); - - if (slash) name = slash + 1; - - token = xstrdup(name); + token = get_basename( name ); for (i=0; token[i]; i++) { if (!isalnum(token[i])) token[i] = '_'; else token[i] = tolower(token[i]); @@ -237,7 +216,7 @@ static char *make_token(const char *name) /* duplicate a basename into a valid C token */ static char *dup_basename_token(const char *name, const char *ext) { - char *p, *ret = dup_basename( name, ext ); + char *p, *ret = replace_extension( get_basename(name), ext, "" ); /* map invalid characters to '_' */ for (p = ret; *p; p++) if (!isalnum(*p)) *p = '_'; return ret; @@ -245,6 +224,7 @@ static char *dup_basename_token(const char *name, const char *ext) static void add_widl_version_define(void) { + char version_str[32]; unsigned int version; const char *p = PACKAGE_VERSION; @@ -263,58 +243,8 @@ static void add_widl_version_define(void) if (p) version += atoi(p + 1); - if (version != 0) - { - char version_str[11]; - snprintf(version_str, sizeof(version_str), "0x%x", version); - wpp_add_define("__WIDL__", version_str); - } - else - wpp_add_define("__WIDL__", NULL); -} - -/* set the target platform */ -static void set_target( const char *target ) -{ - static const struct - { - const char *name; - enum target_cpu cpu; - } cpu_names[] = - { - { "i386", CPU_x86 }, - { "i486", CPU_x86 }, - { "i586", CPU_x86 }, - { "i686", CPU_x86 }, - { "i786", CPU_x86 }, - { "amd64", CPU_x86_64 }, - { "x86_64", CPU_x86_64 }, - { "powerpc", CPU_POWERPC }, - { "arm", CPU_ARM }, - { "armv5", CPU_ARM }, - { "armv6", CPU_ARM }, - { "armv7", CPU_ARM }, - { "arm64", CPU_ARM64 }, - { "aarch64", CPU_ARM64 }, - }; - - unsigned int i; - char *p, *spec = xstrdup( target ); - - /* target specification is in the form CPU-MANUFACTURER-OS or CPU-MANUFACTURER-KERNEL-OS */ - - if (!(p = strchr( spec, '-' ))) error( "Invalid target specification '%s'\n", target ); - *p++ = 0; - for (i = 0; i < sizeof(cpu_names)/sizeof(cpu_names[0]); i++) - { - if (!strcmp( cpu_names[i].name, spec )) - { - target_cpu = cpu_names[i].cpu; - free( spec ); - return; - } - } - error( "Unrecognized CPU '%s'\n", spec ); + snprintf(version_str, sizeof(version_str), "__WIDL__=0x%x", version); + wpp_add_cmdline_define(version_str); } /* clean things up when aborting on a signal */ @@ -327,7 +257,6 @@ static void set_everything(int x) { do_header = x; do_typelib = x; - do_old_typelib = x; do_proxies = x; do_client = x; do_server = x; @@ -350,33 +279,10 @@ void end_cplusplus_guard(FILE *fp) fprintf(fp, "#endif\n\n"); } -typedef struct -{ - char *filename; - struct list link; -} filename_node_t; - -static void add_filename_node(struct list *list, const char *name) -{ - filename_node_t *node = xmalloc(sizeof *node); - node->filename = dup_basename( name, ".idl" ); - list_add_tail(list, &node->link); -} - -static void free_filename_nodes(struct list *list) -{ - filename_node_t *node, *next; - LIST_FOR_EACH_ENTRY_SAFE(node, next, list, filename_node_t, link) { - list_remove(&node->link); - free(node->filename); - free(node); - } -} - -static void write_dlldata_list(struct list *filenames, int define_proxy_delegation) +static void write_dlldata_list( struct strarray filenames, int define_proxy_delegation) { FILE *dlldata; - filename_node_t *node; + unsigned int i; dlldata = fopen(dlldata_name, "w"); if (!dlldata) @@ -387,22 +293,24 @@ static void write_dlldata_list(struct list *filenames, int define_proxy_delegati if (define_proxy_delegation) fprintf(dlldata, "#define PROXY_DELEGATION\n"); +#ifdef __REACTOS__ fprintf(dlldata, "#ifdef __REACTOS__\n"); fprintf(dlldata, "#define WIN32_NO_STATUS\n"); fprintf(dlldata, "#define WIN32_LEAN_AND_MEAN\n"); fprintf(dlldata, "#endif\n\n"); +#endif fprintf(dlldata, "#include \n"); fprintf(dlldata, "#include \n\n"); start_cplusplus_guard(dlldata); - LIST_FOR_EACH_ENTRY(node, filenames, filename_node_t, link) - fprintf(dlldata, "EXTERN_PROXY_FILE(%s)\n", node->filename); + for (i = 0; i < filenames.count; i++) + fprintf(dlldata, "EXTERN_PROXY_FILE(%s)\n", filenames.str[i]); fprintf(dlldata, "\nPROXYFILE_LIST_START\n"); fprintf(dlldata, "/* Start of list */\n"); - LIST_FOR_EACH_ENTRY(node, filenames, filename_node_t, link) - fprintf(dlldata, " REFERENCE_PROXY_FILE(%s),\n", node->filename); + for (i = 0; i < filenames.count; i++) + fprintf(dlldata, " REFERENCE_PROXY_FILE(%s),\n", filenames.str[i]); fprintf(dlldata, "/* End of list */\n"); fprintf(dlldata, "PROXYFILE_LIST_END\n\n"); @@ -420,9 +328,8 @@ static char *eat_space(char *s) void write_dlldata(const statement_list_t *stmts) { - struct list filenames = LIST_INIT(filenames); + struct strarray filenames = empty_strarray; int define_proxy_delegation = 0; - filename_node_t *node; FILE *dlldata; if (!do_dlldata || !need_proxy_file(stmts)) @@ -453,7 +360,7 @@ void write_dlldata(const statement_list_t *stmts) --end; *end = '\0'; if (start < end) - add_filename_node(&filenames, start); + strarray_add(&filenames, replace_extension( get_basename( start ), ".idl", "" )); }else if (!define_proxy_delegation && strncmp(start, delegation_define, sizeof(delegation_define)-1)) { define_proxy_delegation = 1; } @@ -466,19 +373,15 @@ void write_dlldata(const statement_list_t *stmts) fclose(dlldata); } - LIST_FOR_EACH_ENTRY(node, &filenames, filename_node_t, link) - if (strcmp(proxy_token, node->filename) == 0) { + if (strarray_exists( &filenames, proxy_token )) /* We're already in the list, no need to regenerate this file. */ - free_filename_nodes(&filenames); return; - } - add_filename_node(&filenames, proxy_token); - write_dlldata_list(&filenames, define_proxy_delegation); - free_filename_nodes(&filenames); + strarray_add(&filenames, proxy_token); + write_dlldata_list(filenames, define_proxy_delegation); } -static void write_id_guid(FILE *f, const char *type, const char *guid_prefix, const char *name, const UUID *uuid) +static void write_id_guid(FILE *f, const char *type, const char *guid_prefix, const char *name, const struct uuid *uuid) { if (!uuid) return; fprintf(f, "MIDL_DEFINE_GUID(%s, %s_%s, 0x%08x, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x," @@ -498,27 +401,27 @@ static void write_id_data_stmts(const statement_list_t *stmts) const type_t *type = stmt->u.type; if (type_get_type(type) == TYPE_INTERFACE) { - const UUID *uuid; + const struct uuid *uuid; if (!is_object(type) && !is_attr(type->attrs, ATTR_DISPINTERFACE)) continue; uuid = get_attrp(type->attrs, ATTR_UUID); write_id_guid(idfile, "IID", is_attr(type->attrs, ATTR_DISPINTERFACE) ? "DIID" : "IID", type->name, uuid); - if (type->details.iface->async_iface) + if (type_iface_get_async_iface(type)) { - uuid = get_attrp(type->details.iface->async_iface->attrs, ATTR_UUID); - write_id_guid(idfile, "IID", "IID", type->details.iface->async_iface->name, uuid); + uuid = get_attrp(type_iface_get_async_iface(type)->attrs, ATTR_UUID); + write_id_guid(idfile, "IID", "IID", type_iface_get_async_iface(type)->name, uuid); } } else if (type_get_type(type) == TYPE_COCLASS) { - const UUID *uuid = get_attrp(type->attrs, ATTR_UUID); + const struct uuid *uuid = get_attrp(type->attrs, ATTR_UUID); write_id_guid(idfile, "CLSID", "CLSID", type->name, uuid); } } else if (stmt->type == STMT_LIBRARY) { - const UUID *uuid = get_attrp(stmt->u.lib->attrs, ATTR_UUID); + const struct uuid *uuid = get_attrp(stmt->u.lib->attrs, ATTR_UUID); write_id_guid(idfile, "IID", "LIBID", stmt->u.lib->name, uuid); write_id_data_stmts(stmt->u.lib->stmts); } @@ -536,13 +439,13 @@ void write_id_data(const statement_list_t *stmts) } fprintf(idfile, "/*** Autogenerated by WIDL %s ", PACKAGE_VERSION); - fprintf(idfile, "from %s - Do not edit ***/\n\n", input_idl_name); - + fprintf(idfile, "from %s - Do not edit ***/\n\n", idl_name); +#ifdef __REACTOS__ fprintf(idfile, "#ifdef __REACTOS__\n"); fprintf(idfile, "#define WIN32_NO_STATUS\n"); fprintf(idfile, "#define WIN32_LEAN_AND_MEAN\n"); fprintf(idfile, "#endif\n\n"); - +#endif fprintf(idfile, "#include \n"); fprintf(idfile, "#include \n\n"); @@ -581,23 +484,10 @@ void write_id_data(const statement_list_t *stmts) fclose(idfile); } -int main(int argc,char *argv[]) +static void option_callback( int optc, char *optarg ) { - int optc; - int ret = 0; - int opti = 0; - char *output_name = NULL; - - signal( SIGTERM, exit_on_signal ); - signal( SIGINT, exit_on_signal ); -#ifdef SIGHUP - signal( SIGHUP, exit_on_signal ); -#endif - - now = time(NULL); - - while((optc = getopt_long_only(argc, argv, short_options, long_options, &opti)) != EOF) { - switch(optc) { + switch (optc) + { case DLLDATA_OPTION: dlldata_name = xstrdup(optarg); break; @@ -609,6 +499,9 @@ int main(int argc,char *argv[]) do_everything = 0; local_stubs_name = xstrdup(optarg); break; + case NOSTDINC_OPTION: + stdinc = 0; + break; case OLDNAMES_OPTION: old_names = 1; break; @@ -624,28 +517,26 @@ int main(int argc,char *argv[]) break; case PRINT_HELP: fprintf(stderr, "%s", usage); - return 0; + exit(0); case RT_OPTION: winrt_mode = 1; break; case RT_NS_PREFIX: use_abi_namespace = 1; break; + case SYSROOT_OPTION: + sysroot = xstrdup(optarg); + break; case WIN32_OPTION: pointer_size = 4; break; case WIN64_OPTION: pointer_size = 8; break; - case WIN32_ALIGN_OPTION: - win32_packing = strtol(optarg, NULL, 0); - if(win32_packing != 2 && win32_packing != 4 && win32_packing != 8) - error("Packing must be one of 2, 4 or 8\n"); - break; - case WIN64_ALIGN_OPTION: - win64_packing = strtol(optarg, NULL, 0); - if(win64_packing != 2 && win64_packing != 4 && win64_packing != 8) - error("Packing must be one of 2, 4 or 8\n"); + case PACKING_OPTION: + packing = strtol(optarg, NULL, 0); + if(packing != 2 && packing != 4 && packing != 8) + error("Structure packing must be one of 2, 4 or 8\n"); break; case ACF_OPTION: acf_name = xstrdup(optarg); @@ -658,7 +549,8 @@ int main(int argc,char *argv[]) /* FIXME: Support robust option */ break; case 'b': - set_target( optarg ); + if (!parse_target( optarg, &target )) + error( "Invalid target specification '%s'\n", optarg ); break; case 'c': do_everything = 0; @@ -687,6 +579,9 @@ int main(int argc,char *argv[]) case 'I': wpp_add_include_path(optarg); break; + case 'L': + strarray_add( &dlldirs, optarg ); + break; case 'm': if (!strcmp( optarg, "32" )) pointer_size = 4; else if (!strcmp( optarg, "64" )) pointer_size = 8; @@ -698,11 +593,11 @@ int main(int argc,char *argv[]) output_name = xstrdup(optarg); break; case 'O': - if (!strcmp( optarg, "s" )) stub_mode = MODE_Os; - else if (!strcmp( optarg, "i" )) stub_mode = MODE_Oi; - else if (!strcmp( optarg, "ic" )) stub_mode = MODE_Oif; - else if (!strcmp( optarg, "if" )) stub_mode = MODE_Oif; - else if (!strcmp( optarg, "icf" )) stub_mode = MODE_Oif; + if (!strcmp( optarg, "s" )) interpreted_mode = 0; + else if (!strcmp( optarg, "i" )) interpreted_mode = 1; + else if (!strcmp( optarg, "ic" )) interpreted_mode = 1; + else if (!strcmp( optarg, "if" )) interpreted_mode = 1; + else if (!strcmp( optarg, "icf" )) interpreted_mode = 1; else error( "Invalid argument '-O%s'\n", optarg ); break; case 'p': @@ -728,7 +623,7 @@ int main(int argc,char *argv[]) do_typelib = 1; break; case OLD_TYPELIB_OPTION: - do_old_typelib = 1; + old_typelib = 1; break; case 'T': typelib_name = xstrdup(optarg); @@ -742,39 +637,112 @@ int main(int argc,char *argv[]) break; case 'V': printf("%s", version_string); - return 0; + exit(0); case 'W': pedantic = 1; break; - default: - fprintf(stderr, "%s", usage); - return 1; + case '?': + fprintf(stderr, "widl: %s\n\n%s", optarg, usage); + exit(1); } - } +} -#ifdef DEFAULT_INCLUDE_DIR - wpp_add_include_path(DEFAULT_INCLUDE_DIR); +int open_typelib( const char *name ) +{ +#ifndef __REACTOS__ + static const char *default_dirs[] = { LIBDIR "/wine", "/usr/lib/wine", "/usr/local/lib/wine" }; +#endif + struct target win_target = { target.cpu, PLATFORM_WINDOWS }; + const char *pe_dir = get_arch_dir( win_target ); + int fd; + unsigned int i; + +#define TRYOPEN(str) do { \ + char *file = str; \ + if ((fd = open( file, O_RDONLY | O_BINARY )) != -1) return fd; \ + free( file ); } while(0) + + for (i = 0; i < dlldirs.count; i++) + { + if (strendswith( dlldirs.str[i], "/*" )) /* special case for wine build tree */ + { + int namelen = strlen( name ); + if (strendswith( name, ".dll" )) namelen -= 4; + TRYOPEN( strmake( "%.*s/%.*s%s/%s", (int)strlen(dlldirs.str[i]) - 2, dlldirs.str[i], + namelen, name, pe_dir, name )); + } + else + { + TRYOPEN( strmake( "%s%s/%s", dlldirs.str[i], pe_dir, name )); + TRYOPEN( strmake( "%s/%s", dlldirs.str[i], name )); + } + } + +#ifndef __REACTOS__ + if (stdinc) + { + if (libdir) + { + TRYOPEN( strmake( "%s/wine%s/%s", libdir, pe_dir, name )); + TRYOPEN( strmake( "%s/wine/%s", libdir, name )); + } +#ifndef __REACTOS__ + for (i = 0; i < ARRAY_SIZE(default_dirs); i++) + { + if (i && !strcmp( default_dirs[i], default_dirs[0] )) continue; + TRYOPEN( strmake( "%s%s/%s", default_dirs[i], pe_dir, name )); + } +#endif + } #endif - switch (target_cpu) + error( "cannot find %s\n", name ); +#undef TRYOPEN + +#ifdef __REACTOS__ + return 1; +#endif +} + +int main(int argc,char *argv[]) +{ + int i; + int ret = 0; + struct strarray files; + + init_signals( exit_on_signal ); + bindir = get_bindir( argv[0] ); + libdir = get_libdir( bindir ); + includedir = get_includedir( bindir ); + target = init_argv0_target( argv[0] ); + + now = time(NULL); + + files = parse_options( argc, argv, short_options, long_options, 1, option_callback ); + +#ifndef __REACTOS__ + if (stdinc) { - case CPU_x86: - if (pointer_size == 8) target_cpu = CPU_x86_64; - else pointer_size = 4; - break; - case CPU_x86_64: - if (pointer_size == 4) target_cpu = CPU_x86; - else pointer_size = 8; - break; - case CPU_ARM64: - if (pointer_size == 4) error( "Cannot build 32-bit code for this CPU\n" ); - pointer_size = 8; - break; - default: - if (pointer_size == 8) error( "Cannot build 64-bit code for this CPU\n" ); - pointer_size = 4; - break; + static const char *incl_dirs[] = { INCLUDEDIR, "/usr/include", "/usr/local/include" }; + + if (includedir) + { + wpp_add_include_path( strmake( "%s/wine/msvcrt", includedir )); + wpp_add_include_path( strmake( "%s/wine/windows", includedir )); + } + for (i = 0; i < ARRAY_SIZE(incl_dirs); i++) + { + if (i && !strcmp( incl_dirs[i], incl_dirs[0] )) continue; + wpp_add_include_path( strmake( "%s%s/wine/msvcrt", sysroot, incl_dirs[i] )); + wpp_add_include_path( strmake( "%s%s/wine/windows", sysroot, incl_dirs[i] )); + } } +#endif + + if (pointer_size) + set_target_ptr_size( &target, pointer_size ); + else + pointer_size = get_target_ptr_size( target ); /* if nothing specified, try to guess output type from the output file name */ if (output_name && do_everything && !do_header && !do_typelib && !do_proxies && @@ -789,6 +757,7 @@ int main(int argc,char *argv[]) else if (strendswith( output_name, "_i.c" )) do_idfile = 1; else if (strendswith( output_name, "_r.res" )) do_regscript = 1; else if (strendswith( output_name, "_t.res" )) do_typelib = 1; + else if (strendswith( output_name, "_l.res" )) do_typelib = 1; else if (strendswith( output_name, "dlldata.c" )) do_dlldata = 1; else do_everything = 1; } @@ -797,40 +766,40 @@ int main(int argc,char *argv[]) set_everything(TRUE); } - if (!output_name) output_name = dup_basename(input_name, ".idl"); - if (do_header + do_typelib + do_proxies + do_client + - do_server + do_regscript + do_idfile + do_dlldata == 1) + do_server + do_regscript + do_idfile + do_dlldata == 1 && output_name) { - if (do_header) header_name = output_name; - else if (do_typelib) typelib_name = output_name; - else if (do_proxies) proxy_name = output_name; - else if (do_client) client_name = output_name; - else if (do_server) server_name = output_name; - else if (do_regscript) regscript_name = output_name; - else if (do_idfile) idfile_name = output_name; - else if (do_dlldata) dlldata_name = output_name; + if (do_header && !header_name) header_name = output_name; + else if (do_typelib && !typelib_name) typelib_name = output_name; + else if (do_proxies && !proxy_name) proxy_name = output_name; + else if (do_client && !client_name) client_name = output_name; + else if (do_server && !server_name) server_name = output_name; + else if (do_regscript && !regscript_name) regscript_name = output_name; + else if (do_idfile && !idfile_name) idfile_name = output_name; + else if (do_dlldata && !dlldata_name) dlldata_name = output_name; } if (!dlldata_name && do_dlldata) dlldata_name = xstrdup("dlldata.c"); - if(optind < argc) { + if (files.count) { if (do_dlldata && !do_everything) { - struct list filenames = LIST_INIT(filenames); - for ( ; optind < argc; ++optind) - add_filename_node(&filenames, argv[optind]); + struct strarray filenames = empty_strarray; + for (i = 0; i < files.count; i++) + strarray_add(&filenames, replace_extension( get_basename( files.str[i] ), ".idl", "" )); - write_dlldata_list(&filenames, 0 /* FIXME */ ); - free_filename_nodes(&filenames); + write_dlldata_list(filenames, 0 /* FIXME */ ); return 0; } - else if (optind != argc - 1) { + else if (files.count > 1) { fprintf(stderr, "%s", usage); return 1; } else - input_idl_name = input_name = xstrdup(argv[optind]); + { + input_name = xstrdup( files.str[0] ); + idl_name = get_basename( input_name ); + } } else { fprintf(stderr, "%s", usage); @@ -850,40 +819,26 @@ int main(int argc,char *argv[]) (debuglevel & DEBUGLEVEL_PPTRACE) != 0, (debuglevel & DEBUGLEVEL_PPMSG) != 0 ); - if (!header_name) { - header_name = dup_basename(input_name, ".idl"); - strcat(header_name, ".h"); - } + if (!header_name) + header_name = replace_extension( get_basename(input_name), ".idl", ".h" ); - if (!typelib_name && do_typelib) { - typelib_name = dup_basename(input_name, ".idl"); - strcat(typelib_name, ".tlb"); - } + if (!typelib_name && do_typelib) + typelib_name = replace_extension( get_basename(input_name), ".idl", ".tlb" ); - if (!proxy_name && do_proxies) { - proxy_name = dup_basename(input_name, ".idl"); - strcat(proxy_name, "_p.c"); - } + if (!proxy_name && do_proxies) + proxy_name = replace_extension( get_basename(input_name), ".idl", "_p.c" ); - if (!client_name && do_client) { - client_name = dup_basename(input_name, ".idl"); - strcat(client_name, "_c.c"); - } + if (!client_name && do_client) + client_name = replace_extension( get_basename(input_name), ".idl", "_c.c" ); - if (!server_name && do_server) { - server_name = dup_basename(input_name, ".idl"); - strcat(server_name, "_s.c"); - } + if (!server_name && do_server) + server_name = replace_extension( get_basename(input_name), ".idl", "_s.c" ); - if (!regscript_name && do_regscript) { - regscript_name = dup_basename(input_name, ".idl"); - strcat(regscript_name, "_r.rgs"); - } + if (!regscript_name && do_regscript) + regscript_name = replace_extension( get_basename(input_name), ".idl", "_r.rgs" ); - if (!idfile_name && do_idfile) { - idfile_name = dup_basename(input_name, ".idl"); - strcat(idfile_name, "_i.c"); - } + if (!idfile_name && do_idfile) + idfile_name = replace_extension( get_basename(input_name), ".idl", "_i.c" ); if (do_proxies) proxy_token = dup_basename_token(proxy_name,"_p.c"); if (do_client) client_token = dup_basename_token(client_name,"_c.c"); @@ -891,61 +846,18 @@ int main(int argc,char *argv[]) if (do_regscript) regscript_token = dup_basename_token(regscript_name,"_r.rgs"); add_widl_version_define(); - wpp_add_define("_WIN32", NULL); + wpp_add_cmdline_define("_WIN32=1"); atexit(rm_tempfile); - if (!no_preprocess) - { - chat("Starting preprocess\n"); - - if (!preprocess_only) - { - FILE *output; - int fd; - char *name = xmalloc( strlen(header_name) + 8 ); - - strcpy( name, header_name ); - strcat( name, ".XXXXXX" ); - - if ((fd = mkstemps( name, 0 )) == -1) - error("Could not generate a temp name from %s\n", name); - - temp_name = name; - if (!(output = fdopen(fd, "wt"))) - error("Could not open fd %s for writing\n", name); - - ret = wpp_parse( input_name, output ); - fclose( output ); - } - else - { - ret = wpp_parse( input_name, stdout ); - } - - if(ret) exit(1); - if(preprocess_only) exit(0); - if(!(parser_in = fopen(temp_name, "r"))) { - fprintf(stderr, "Could not open %s for input\n", temp_name); - return 1; - } - } - else { - if(!(parser_in = fopen(input_name, "r"))) { - fprintf(stderr, "Could not open %s for input\n", input_name); - return 1; - } - } + if (preprocess_only) exit( wpp_parse( input_name, stdout ) ); + parser_in = open_input_file( input_name ); header_token = make_token(header_name); init_types(); ret = parser_parse(); - - fclose(parser_in); - - if(ret) { - exit(1); - } + close_all_inputs(); + if (ret) exit(1); /* Everything has been done successfully, don't delete any files. */ set_everything(FALSE); @@ -956,9 +868,6 @@ int main(int argc,char *argv[]) static void rm_tempfile(void) { - abort_import(); - if(temp_name) - unlink(temp_name); if (do_header) unlink(header_name); if (local_stubs_name) @@ -975,4 +884,38 @@ static void rm_tempfile(void) unlink(proxy_name); if (do_typelib) unlink(typelib_name); + remove_temp_files(); +} + +char *find_input_file( const char *name, const char *parent ) +{ + char *path; + + /* don't search for a file name with a path in the include directories, for compatibility with MIDL */ + if (strchr( name, '/' ) || strchr( name, '\\' )) path = xstrdup( name ); + else if (!(path = wpp_find_include( name, parent ))) error_loc( "Unable to open include file %s\n", name ); + + return path; +} + +FILE *open_input_file( const char *path ) +{ + FILE *file; + char *name; + int ret; + + if (no_preprocess) + { + if (!(file = fopen( path, "r" ))) error_loc( "Unable to open %s\n", path ); + return file; + } + + name = make_temp_file( "widl", NULL ); + if (!(file = fopen( name, "wt" ))) error_loc( "Could not open %s for writing\n", name ); + ret = wpp_parse( path, file ); + fclose( file ); + if (ret) exit( 1 ); + + if (!(file = fopen( name, "r" ))) error_loc( "Unable to open %s\n", name ); + return file; } diff --git a/sdk/tools/widl/widl.h b/sdk/tools/widl/widl.h index 3e015ca7e13..31bb2c83694 100644 --- a/sdk/tools/widl/widl.h +++ b/sdk/tools/widl/widl.h @@ -21,6 +21,7 @@ #ifndef __WIDL_WIDL_H #define __WIDL_WIDL_H +#include "../tools.h" #include "widltypes.h" #include @@ -38,7 +39,6 @@ extern int pedantic; extern int do_everything; extern int do_header; extern int do_typelib; -extern int do_old_typelib; extern int do_proxies; extern int do_client; extern int do_server; @@ -46,13 +46,13 @@ extern int do_regscript; extern int do_idfile; extern int do_dlldata; extern int old_names; -extern int win32_packing; -extern int win64_packing; +extern int old_typelib; extern int winrt_mode; +extern int interpreted_mode; extern int use_abi_namespace; extern char *input_name; -extern char *input_idl_name; +extern char *idl_name; extern char *acf_name; extern char *header_name; extern char *header_token; @@ -69,26 +69,12 @@ extern char *regscript_name; extern char *regscript_token; extern const char *prefix_client; extern const char *prefix_server; +extern unsigned int packing; extern unsigned int pointer_size; +extern struct target target; extern time_t now; -extern int line_number; -extern int char_number; - -enum target_cpu -{ - CPU_x86, CPU_x86_64, CPU_POWERPC, CPU_ARM, CPU_ARM64, CPU_LAST = CPU_ARM64 -}; - -extern enum target_cpu target_cpu; - -enum stub_mode -{ - MODE_Os, /* inline stubs */ - MODE_Oi, /* old-style interpreted stubs */ - MODE_Oif /* new-style fully interpreted stubs */ -}; -extern enum stub_mode get_stub_mode(void); +extern int open_typelib( const char *name ); extern void write_header(const statement_list_t *stmts); extern void write_id_data(const statement_list_t *stmts); @@ -104,4 +90,40 @@ extern void write_dlldata(const statement_list_t *stmts); extern void start_cplusplus_guard(FILE *fp); extern void end_cplusplus_guard(FILE *fp); +/* attribute.c */ + +extern attr_t *attr_int( struct location where, enum attr_type attr_type, unsigned int val ); +extern attr_t *attr_ptr( struct location where, enum attr_type attr_type, void *val ); + +extern int is_attr( const attr_list_t *list, enum attr_type attr_type ); +extern int is_ptrchain_attr( const var_t *var, enum attr_type attr_type ); +extern int is_aliaschain_attr( const type_t *type, enum attr_type attr_type ); + +extern unsigned int get_attrv( const attr_list_t *list, enum attr_type attr_type ); +extern void *get_attrp( const attr_list_t *list, enum attr_type attr_type ); +extern void *get_aliaschain_attrp( const type_t *type, enum attr_type attr_type ); + +typedef int (*map_attrs_filter_t)( attr_list_t *, const attr_t * ); +extern attr_list_t *append_attr( attr_list_t *list, attr_t *attr ); +extern attr_list_t *append_attr_list( attr_list_t *new_list, attr_list_t *old_list ); +extern attr_list_t *append_attribs( attr_list_t *, attr_list_t * ); +extern attr_list_t *map_attrs( const attr_list_t *list, map_attrs_filter_t filter ); +extern attr_list_t *move_attr( attr_list_t *dst, attr_list_t *src, enum attr_type type ); + +extern attr_list_t *check_apicontract_attrs( const char *name, attr_list_t *attrs ); +extern attr_list_t *check_coclass_attrs( const char *name, attr_list_t *attrs ); +extern attr_list_t *check_dispiface_attrs( const char *name, attr_list_t *attrs ); +extern attr_list_t *check_enum_attrs( attr_list_t *attrs ); +extern attr_list_t *check_enum_member_attrs( attr_list_t *attrs ); +extern attr_list_t *check_field_attrs( const char *name, attr_list_t *attrs ); +extern attr_list_t *check_function_attrs( const char *name, attr_list_t *attrs ); +extern attr_list_t *check_interface_attrs( const char *name, attr_list_t *attrs ); +extern attr_list_t *check_library_attrs( const char *name, attr_list_t *attrs ); +extern attr_list_t *check_module_attrs( const char *name, attr_list_t *attrs ); +extern attr_list_t *check_runtimeclass_attrs( const char *name, attr_list_t *attrs ); +extern attr_list_t *check_struct_attrs( attr_list_t *attrs ); +extern attr_list_t *check_typedef_attrs( attr_list_t *attrs ); +extern attr_list_t *check_union_attrs( attr_list_t *attrs ); +extern void check_arg_attrs( const var_t *arg ); + #endif diff --git a/sdk/tools/widl/widltypes.h b/sdk/tools/widl/widltypes.h index 53a24e45f77..5ee1323793d 100644 --- a/sdk/tools/widl/widltypes.h +++ b/sdk/tools/widl/widltypes.h @@ -22,26 +22,30 @@ #define __WIDL_WIDLTYPES_H #include +#include #include -#include "guiddef.h" #include "ndrtypes.h" #include "wine/list.h" -#ifndef UUID_DEFINED -#define UUID_DEFINED -typedef GUID UUID; -#endif +struct uuid +{ + unsigned int Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +}; #define TRUE 1 #define FALSE 0 -typedef struct _loc_info_t loc_info_t; typedef struct _attr_t attr_t; +typedef struct _attr_custdata_t attr_custdata_t; typedef struct _expr_t expr_t; typedef struct _type_t type_t; typedef struct _var_t var_t; +typedef struct _decl_spec_t decl_spec_t; typedef struct _declarator_t declarator_t; -typedef struct _ifref_t ifref_t; +typedef struct _typeref_t typeref_t; typedef struct _typelib_entry_t typelib_entry_t; typedef struct _importlib_t importlib_t; typedef struct _importinfo_t importinfo_t; @@ -49,7 +53,6 @@ typedef struct _typelib_t typelib_t; typedef struct _user_type_t user_type_t; typedef struct _user_type_t context_handle_t; typedef struct _user_type_t generic_handle_t; -typedef struct _type_list_t type_list_t; typedef struct _statement_t statement_t; typedef struct _warning_t warning_t; @@ -58,7 +61,7 @@ typedef struct list str_list_t; typedef struct list expr_list_t; typedef struct list var_list_t; typedef struct list declarator_list_t; -typedef struct list ifref_list_t; +typedef struct list typeref_list_t; typedef struct list user_type_list_t; typedef struct list context_handle_list_t; typedef struct list generic_handle_list_t; @@ -67,6 +70,7 @@ typedef struct list warning_list_t; enum attr_type { + ATTR_ACTIVATABLE, ATTR_AGGREGATABLE, ATTR_ALLOCATE, ATTR_ANNOTATION, @@ -81,15 +85,20 @@ enum attr_type ATTR_CASE, ATTR_CODE, ATTR_COMMSTATUS, - ATTR_CONST, /* const pseudo-attribute */ + ATTR_COMPOSABLE, ATTR_CONTEXTHANDLE, + ATTR_CONTRACT, + ATTR_CONTRACTVERSION, ATTR_CONTROL, + ATTR_CUSTOM, ATTR_DECODE, ATTR_DEFAULT, + ATTR_DEFAULT_OVERLOAD, ATTR_DEFAULTBIND, ATTR_DEFAULTCOLLELEM, ATTR_DEFAULTVALUE, ATTR_DEFAULTVTABLE, + ATTR_DEPRECATED, ATTR_DISABLECONSISTENCYCHECK, ATTR_DISPINTERFACE, ATTR_DISPLAYBIND, @@ -99,8 +108,12 @@ enum attr_type ATTR_ENCODE, ATTR_ENDPOINT, ATTR_ENTRY, + ATTR_EVENTADD, + ATTR_EVENTREMOVE, + ATTR_EXCLUSIVETO, ATTR_EXPLICIT_HANDLE, ATTR_FAULTSTATUS, + ATTR_FLAGS, ATTR_FORCEALLOCATE, ATTR_HANDLE, ATTR_HELPCONTEXT, @@ -116,12 +129,12 @@ enum attr_type ATTR_IMMEDIATEBIND, ATTR_IMPLICIT_HANDLE, ATTR_IN, - ATTR_INLINE, ATTR_INPUTSYNC, ATTR_LENGTHIS, ATTR_LIBLCID, ATTR_LICENSED, ATTR_LOCAL, + ATTR_MARSHALING_BEHAVIOR, ATTR_MAYBE, ATTR_MESSAGE, ATTR_NOCODE, @@ -136,6 +149,7 @@ enum attr_type ATTR_OPTIMIZE, ATTR_OPTIONAL, ATTR_OUT, + ATTR_OVERLOAD, ATTR_PARAMLCID, ATTR_PARTIALIGNORE, ATTR_POINTERDEFAULT, @@ -144,6 +158,7 @@ enum attr_type ATTR_PROPGET, ATTR_PROPPUT, ATTR_PROPPUTREF, + ATTR_PROTECTED, ATTR_PROXY, ATTR_PUBLIC, ATTR_RANGE, @@ -154,6 +169,7 @@ enum attr_type ATTR_RETVAL, ATTR_SIZEIS, ATTR_SOURCE, + ATTR_STATIC, ATTR_STRICTCONTEXTHANDLE, ATTR_STRING, ATTR_SWITCHIS, @@ -175,7 +191,6 @@ enum expr_type { EXPR_VOID, EXPR_NUM, - EXPR_HEXNUM, EXPR_DOUBLE, EXPR_IDENTIFIER, EXPR_NEG, @@ -235,6 +250,16 @@ enum storage_class STG_REGISTER, }; +enum type_qualifier +{ + TYPE_QUALIFIER_CONST = 1, +}; + +enum function_specifier +{ + FUNCTION_SPECIFIER_INLINE = 1, +}; + enum statement_type { STMT_LIBRARY, @@ -258,6 +283,14 @@ enum threading_type THREADING_BOTH }; +enum marshaling_type +{ + MARSHALING_INVALID = 0, + MARSHALING_NONE, + MARSHALING_AGILE, + MARSHALING_STANDARD, +}; + enum type_basic_type { TYPE_BASIC_INT8 = 1, @@ -281,11 +314,13 @@ enum type_basic_type #define TYPE_BASIC_INT_MIN TYPE_BASIC_INT8 #define TYPE_BASIC_INT_MAX TYPE_BASIC_HYPER -struct _loc_info_t +struct location { const char *input_name; - int line_number; - const char *near_text; + int first_line; + int last_line; + int first_column; + int last_column; }; struct str_list_entry_t @@ -294,6 +329,14 @@ struct str_list_entry_t struct list entry; }; +struct _decl_spec_t +{ + type_t *type; + enum storage_class stgclass; + enum type_qualifier qualifier; + enum function_specifier func_specifier; +}; + struct _attr_t { enum attr_type type; union { @@ -302,17 +345,26 @@ struct _attr_t { } u; /* parser-internal */ struct list entry; + struct location where; +}; + +struct integer +{ + int value; + int is_unsigned; + int is_long; + int is_hex; }; struct _expr_t { enum expr_type type; const expr_t *ref; union { - int lval; + struct integer integer; double dval; const char *sval; const expr_t *ext; - type_t *tref; + decl_spec_t tref; } u; const expr_t *ext2; int is_const; @@ -321,6 +373,11 @@ struct _expr_t { struct list entry; }; +struct _attr_custdata_t { + struct uuid id; + expr_t *pval; +}; + struct struct_details { var_list_t *fields; @@ -335,7 +392,6 @@ struct func_details { var_list_t *args; struct _var_t *retval; - int idx; }; struct iface_details @@ -346,6 +402,7 @@ struct iface_details struct _type_t *inherit; struct _type_t *disp_inherit; struct _type_t *async_iface; + typeref_list_t *requires; }; struct module_details @@ -357,16 +414,15 @@ struct array_details { expr_t *size_is; expr_t *length_is; - struct _type_t *elem; + struct _decl_spec_t elem; unsigned int dim; - unsigned char ptr_def_fc; unsigned char declptr; /* if declared as a pointer */ unsigned short ptr_tfsoff; /* offset of pointer definition for declptr */ }; struct coclass_details { - ifref_list_t *ifaces; + typeref_list_t *ifaces; }; struct basic_details @@ -377,8 +433,7 @@ struct basic_details struct pointer_details { - struct _type_t *ref; - unsigned char def_fc; + struct _decl_spec_t ref; }; struct bitfield_details @@ -387,6 +442,27 @@ struct bitfield_details const expr_t *bits; }; +struct alias_details +{ + struct _decl_spec_t aliasee; +}; + +struct runtimeclass_details +{ + typeref_list_t *ifaces; +}; + +struct parameterized_details +{ + type_t *type; + typeref_list_t *params; +}; + +struct delegate_details +{ + type_t *iface; +}; + #define HASHMAX 64 struct namespace { @@ -413,10 +489,15 @@ enum type_type TYPE_POINTER, TYPE_ARRAY, TYPE_BITFIELD, + TYPE_APICONTRACT, + TYPE_RUNTIMECLASS, + TYPE_PARAMETERIZED_TYPE, + TYPE_PARAMETER, + TYPE_DELEGATE, }; struct _type_t { - const char *name; + const char *name; /* C++ name with parameters in brackets */ struct namespace *namespace; enum type_type type_type; attr_list_t *attrs; @@ -432,32 +513,45 @@ struct _type_t { struct basic_details basic; struct pointer_details pointer; struct bitfield_details bitfield; + struct alias_details alias; + struct runtimeclass_details runtimeclass; + struct parameterized_details parameterized; + struct delegate_details delegate; } details; - const char *c_name; - type_t *orig; /* dup'd types */ + const char *c_name; /* mangled C name, with namespaces and parameters */ + const char *signature; + const char *qualified_name; /* C++ fully qualified name */ + const char *impl_name; /* C++ parameterized types impl base class name */ + const char *param_name; /* used to build c_name of a parameterized type, when used as a parameter */ + const char *short_name; /* widl specific short name */ unsigned int typestring_offset; unsigned int ptrdesc; /* used for complex structs */ int typelib_idx; - loc_info_t loc_info; + struct location where; unsigned int ignore : 1; unsigned int defined : 1; + unsigned int defined_in_import : 1; unsigned int written : 1; unsigned int user_types_registered : 1; unsigned int tfswrite : 1; /* if the type needs to be written to the TFS */ unsigned int checked : 1; - unsigned int is_alias : 1; /* is the type an alias? */ }; struct _var_t { char *name; - type_t *type; + decl_spec_t declspec; attr_list_t *attrs; expr_t *eval; - enum storage_class stgclass; - unsigned int procstring_offset; + unsigned int typestring_offset; - struct _loc_info_t loc_info; + /* fields specific to functions */ + unsigned int procstring_offset, func_idx; + + struct location where; + + /* Should we define the UDT in this var, when writing a header? */ + unsigned int is_defined : 1; /* parser-internal */ struct list entry; @@ -466,15 +560,15 @@ struct _var_t { struct _declarator_t { var_t *var; type_t *type; - type_t *func_type; + enum type_qualifier qualifier; expr_t *bits; /* parser-internal */ struct list entry; }; -struct _ifref_t { - type_t *iface; +struct _typeref_t { + type_t *type; attr_list_t *attrs; /* parser-internal */ @@ -488,7 +582,7 @@ struct _typelib_entry_t { struct _importinfo_t { int offset; - GUID guid; + struct uuid guid; int flags; int id; @@ -498,10 +592,11 @@ struct _importinfo_t { }; struct _importlib_t { + int offset; char *name; int version; - GUID guid; + struct uuid guid; importinfo_t *importinfos; int ntypeinfos; @@ -516,6 +611,9 @@ struct _typelib_t { const attr_list_t *attrs; struct list importlibs; statement_list_t *stmts; + + type_t **reg_ifaces; + unsigned int reg_iface_count; }; struct _user_type_t { @@ -523,23 +621,20 @@ struct _user_type_t { const char *name; }; -struct _type_list_t { - type_t *type; - struct _type_list_t *next; -}; - struct _statement_t { struct list entry; enum statement_type type; union { - ifref_t iface; type_t *type; const char *str; var_t *var; typelib_t *lib; - type_list_t *type_list; + typeref_list_t *type_list; } u; + /* For STMT_TYPE and STMT_TYPEDEF, should we define the UDT in this + * statement, when writing a header? */ + unsigned int is_defined : 1; }; struct _warning_t { @@ -557,7 +652,7 @@ typedef enum { extern user_type_list_t user_type_list; extern context_handle_list_t context_handle_list; extern generic_handle_list_t generic_handle_list; -void check_for_additional_prototype_types(const var_list_t *list); +void check_for_additional_prototype_types(type_t *type); void init_types(void); type_t *alloc_type(void); @@ -573,31 +668,23 @@ type_t *find_type(const char *name, struct namespace *namespace, int t); type_t *make_type(enum type_type type); type_t *get_type(enum type_type type, char *name, struct namespace *namespace, int t); type_t *reg_type(type_t *type, const char *name, struct namespace *namespace, int t); -void add_incomplete(type_t *t); var_t *make_var(char *name); var_list_t *append_var(var_list_t *list, var_t *var); -void init_loc_info(loc_info_t *); - -char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix); - -static inline var_list_t *type_get_function_args(const type_t *func_type) -{ - return func_type->details.function->args; -} +char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, + const char *abi_prefix); +char *format_parameterized_type_name(type_t *type, typeref_list_t *params); static inline enum type_type type_get_type_detect_alias(const type_t *type) { - if (type->is_alias) - return TYPE_ALIAS; return type->type_type; } #define STATEMENTS_FOR_EACH_FUNC(stmt, stmts) \ if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, statement_t, entry ) \ - if (stmt->type == STMT_DECLARATION && stmt->u.var->stgclass == STG_NONE && \ - type_get_type_detect_alias(stmt->u.var->type) == TYPE_FUNCTION) + if (stmt->type == STMT_DECLARATION && stmt->u.var->declspec.stgclass == STG_NONE && \ + type_get_type_detect_alias(stmt->u.var->declspec.type) == TYPE_FUNCTION) static inline int statements_has_func(const statement_list_t *stmts) { @@ -616,4 +703,14 @@ static inline int is_global_namespace(const struct namespace *namespace) return !namespace->name; } +static inline decl_spec_t *init_declspec(decl_spec_t *declspec, type_t *type) +{ + declspec->type = type; + declspec->stgclass = STG_NONE; + declspec->qualifier = 0; + declspec->func_specifier = 0; + + return declspec; +} + #endif diff --git a/sdk/tools/widl/write_msft.c b/sdk/tools/widl/write_msft.c index 2fa7e193619..99dc076eb84 100644 --- a/sdk/tools/widl/write_msft.c +++ b/sdk/tools/widl/write_msft.c @@ -28,7 +28,6 @@ */ #include "config.h" -#include "wine/port.h" #include #include @@ -37,18 +36,6 @@ #include #include -#define NONAMELESSUNION - -#ifdef __REACTOS__ -#include -#include -#else -#include "winerror.h" -#include "windef.h" -#include "winbase.h" -#include "winnls.h" -#endif - #include "widl.h" #include "typelib.h" #include "typelib_struct.h" @@ -59,12 +46,6 @@ #include "parser.h" #include "typegen.h" -#ifdef __REACTOS__ -#define S_OK 0 -#define S_FALSE 1 -#define E_OUTOFMEMORY ((HRESULT)0x8007000EL) -#endif - enum MSFT_segment_index { MSFT_SEG_TYPEINFO = 0, /* type information */ MSFT_SEG_IMPORTINFO, /* import information */ @@ -86,7 +67,7 @@ enum MSFT_segment_index { typedef struct tagMSFT_ImpFile { int guid; - LCID lcid; + int lcid; int version; char filename[0]; /* preceded by two bytes of encoded (length << 2) + flags in the low two bits. */ } MSFT_ImpFile; @@ -99,12 +80,12 @@ typedef struct _msft_typelib_t unsigned 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_typeinfo_offsets[0x200]; /* Hope that's enough. */ - INT *typelib_namehash_segment; - INT *typelib_guidhash_segment; + int *typelib_namehash_segment; + int *typelib_guidhash_segment; - INT help_string_dll_offset; + int help_string_dll_offset; struct _msft_typeinfo_t *typeinfos; struct _msft_typeinfo_t *last_typeinfo; @@ -203,8 +184,7 @@ static void ctl2_init_segdir( * * The hash key for the GUID. */ -static int ctl2_hash_guid( - REFGUID guid) /* [I] The guid to hash. */ +static int ctl2_hash_guid(const struct uuid *guid) { int hash; int i; @@ -229,7 +209,7 @@ static int ctl2_hash_guid( 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. */ + const struct uuid *guid) /* [I] The guid to find. */ { int offset; MSFT_GuidEntry *guidentry; @@ -238,7 +218,7 @@ static int ctl2_find_guid( while (offset != -1) { guidentry = (MSFT_GuidEntry *)&typelib->typelib_segment_data[MSFT_SEG_GUID][offset]; - if (!memcmp(guidentry, guid, sizeof(GUID))) return offset; + if (!memcmp(guidentry, guid, sizeof(*guid))) return offset; offset = guidentry->next_hash; } @@ -302,36 +282,29 @@ static int ctl2_encode_name( 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]; + char *converted_name; + size_t length, size; int offset; int value; length = strlen(name); + size = (length + 7) & ~3; + converted_name = xmalloc(size + 1); memcpy(converted_name + 4, name, length); - converted_name[length + 4] = 0; - value = lhash_val_of_name_sys(typelib->typelib_header.varflags & 0x0f, typelib->typelib_header.lcid, converted_name + 4); -#ifdef WORDS_BIGENDIAN - converted_name[3] = length & 0xff; - converted_name[2] = 0x00; - converted_name[1] = value; - converted_name[0] = value >> 8; -#else converted_name[0] = length & 0xff; - converted_name[1] = 0x00; + converted_name[1] = length >> 8; converted_name[2] = value; converted_name[3] = value >> 8; -#endif for (offset = (4 - length) & 3; offset; offset--) converted_name[length + offset + 3] = 0x57; *result = converted_name; - return (length + 7) & ~3; + return size; } /**************************************************************************** @@ -353,20 +326,17 @@ static int ctl2_encode_string( 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]; + char *converted_string; + size_t length, size; int offset; length = strlen(string); + size = (length + 5) & ~3; + if (length < 3) size += 4; + converted_string = xmalloc(size); memcpy(converted_string + 2, string, length); - -#ifdef WORDS_BIGENDIAN - converted_string[1] = length & 0xff; - converted_string[0] = (length >> 8) & 0xff; -#else converted_string[0] = length & 0xff; converted_string[1] = (length >> 8) & 0xff; -#endif if(length < 3) { /* strings of this length are padded with up to 8 bytes incl the 2 byte length */ for(offset = 0; offset < 4; offset++) @@ -376,8 +346,7 @@ static int ctl2_encode_string( for (offset = (4 - (length + 2)) & 3; offset; offset--) converted_string[length + offset + 1] = 0x57; *result = converted_string; - - return (length + 5) & ~3; + return size; } /**************************************************************************** @@ -559,7 +528,11 @@ static int ctl2_alloc_name( length = ctl2_encode_name(typelib, name, &encoded_name); offset = ctl2_find_name(typelib, encoded_name); - if (offset != -1) return offset; + if (offset != -1) + { + free(encoded_name); + return offset; + } offset = ctl2_alloc_segment(typelib, MSFT_SEG_NAME, length + 8, 0); @@ -576,6 +549,7 @@ static int ctl2_alloc_name( typelib->typelib_header.nametablecount += 1; typelib->typelib_header.nametablechars += *encoded_name; + free(encoded_name); return offset; } @@ -610,6 +584,7 @@ static int ctl2_alloc_string( string_space = typelib->typelib_segment_data[MSFT_SEG_STRING] + offset; memcpy(string_space, encoded_string, length); + free(encoded_string); return offset; } @@ -690,6 +665,7 @@ static int alloc_importfile( importfile->lcid = typelib->typelib_header.lcid2; importfile->version = major_version | (minor_version << 16); memcpy(&importfile->filename, encoded_string, length); + free(encoded_string); return offset; } @@ -708,32 +684,32 @@ static void alloc_importinfo(msft_typelib_t *typelib, importinfo_t *importinfo) importlib->allocated = -1; - memcpy(&guid.guid, &importlib->guid, sizeof(GUID)); + memcpy(&guid.guid, &importlib->guid, sizeof(guid.guid)); guid.hreftype = 2; guid_idx = ctl2_alloc_guid(typelib, &guid); - alloc_importfile(typelib, guid_idx, importlib->version&0xffff, - importlib->version>>16, importlib->name); + importlib->offset = alloc_importfile(typelib, guid_idx, importlib->version & 0xffff, + importlib->version >> 16, importlib->name); } if(importinfo->offset == -1 || !(importinfo->flags & MSFT_IMPINFO_OFFSET_IS_GUID)) { MSFT_ImpInfo impinfo; impinfo.flags = importinfo->flags; - impinfo.oImpFile = 0; + impinfo.oImpFile = importlib->offset; if(importinfo->flags & MSFT_IMPINFO_OFFSET_IS_GUID) { MSFT_GuidEntry guid; guid.hreftype = 0; - memcpy(&guid.guid, &importinfo->guid, sizeof(GUID)); + memcpy(&guid.guid, &importinfo->guid, sizeof(guid.guid)); impinfo.oGuid = ctl2_alloc_guid(typelib, &guid); importinfo->offset = alloc_msft_importinfo(typelib, &impinfo); - typelib->typelib_segment_data[MSFT_SEG_GUID][impinfo.oGuid+sizeof(GUID)] + typelib->typelib_segment_data[MSFT_SEG_GUID][impinfo.oGuid+sizeof(guid.guid)] = importinfo->offset+1; if(!strcmp(importinfo->name, "IDispatch")) @@ -774,6 +750,7 @@ static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration); static void add_union_typeinfo(msft_typelib_t *typelib, type_t *tunion); static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls); static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinterface); +static void add_typedef_typeinfo(msft_typelib_t *typelib, type_t *dispinterface); /**************************************************************************** @@ -873,8 +850,8 @@ static int encode_type( case VT_PTR: { int next_vt; - for(next_vt = 0; is_ptr(type); type = type_pointer_get_ref(type)) { - next_vt = get_type_vt(type_pointer_get_ref(type)); + for(next_vt = 0; is_ptr(type); type = type_pointer_get_ref_type(type)) { + next_vt = get_type_vt(type_pointer_get_ref_type(type)); if (next_vt != 0) break; } @@ -882,7 +859,7 @@ static int encode_type( if (next_vt == 0) next_vt = VT_VOID; - encode_type(typelib, next_vt, type_pointer_get_ref(type), + encode_type(typelib, next_vt, type_pointer_get_ref_type(type), &target_type, &child_size); /* these types already have an implicit pointer, so we don't need to * add another */ @@ -923,10 +900,10 @@ static int encode_type( case VT_SAFEARRAY: { - type_t *element_type = type_alias_get_aliasee(type_array_get_element(type)); + type_t *element_type = type_alias_get_aliasee_type(type_array_get_element_type(type)); int next_vt = get_type_vt(element_type); - encode_type(typelib, next_vt, type_alias_get_aliasee(type_array_get_element(type)), + encode_type(typelib, next_vt, type_alias_get_aliasee_type(type_array_get_element_type(type)), &target_type, &child_size); for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) { @@ -977,16 +954,30 @@ static int encode_type( } else { - /* typedef'd types without public attribute aren't included in the typelib */ - while (type_is_alias(type) && !is_attr(type->attrs, ATTR_PUBLIC)) - type = type_alias_get_aliasee(type); + /* Typedefs without the [public] attribute aren't included in the + * typelib, unless the aliasee is an anonymous UDT or the typedef + * is wire-marshalled. In the latter case the wire-marshal type, + * which may be a non-public alias, is used instead. */ + while (type_is_alias(type)) + { + if (is_attr(type->attrs, ATTR_WIREMARSHAL)) + { + type = get_attrp(type->attrs, ATTR_WIREMARSHAL); + break; + } + else if (!is_attr(type->attrs, ATTR_PUBLIC)) + type = type_alias_get_aliasee_type(type); + else + break; + } chat("encode_type: VT_USERDEFINED - adding new type %s, real type %d\n", type->name, type_get_type(type)); - switch (type_get_type(type)) + switch (type_get_type_detect_alias(type)) { case TYPE_STRUCT: + case TYPE_ENCAPSULATED_UNION: add_structure_typeinfo(typelib, type); break; case TYPE_INTERFACE: @@ -1001,6 +992,9 @@ static int encode_type( case TYPE_COCLASS: add_coclass_typeinfo(typelib, type); break; + case TYPE_ALIAS: + add_typedef_typeinfo(typelib, type); + break; default: error("encode_type: VT_USERDEFINED - unhandled type %d\n", type_get_type(type)); @@ -1060,14 +1054,14 @@ static int encode_var( var, type, type->name ? type->name : "NULL"); if (is_array(type) && !type_array_is_decl_as_ptr(type)) { - int num_dims, elements = 1, arrayoffset; + int num_dims, arrayoffset; type_t *atype; int *arraydata; num_dims = 0; for (atype = type; is_array(atype) && !type_array_is_decl_as_ptr(atype); - atype = type_array_get_element(atype)) + atype = type_array_get_element_type(atype)) ++num_dims; chat("array with %d dimensions\n", num_dims); @@ -1082,12 +1076,11 @@ static int encode_var( arraydata += 2; for (atype = type; is_array(atype) && !type_array_is_decl_as_ptr(atype); - atype = type_array_get_element(atype)) + atype = type_array_get_element_type(atype)) { arraydata[0] = type_array_get_dim(atype); arraydata[1] = 0; arraydata += 2; - elements *= type_array_get_dim(atype); } typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0); @@ -1104,7 +1097,7 @@ static int encode_var( vt = get_type_vt(type); if (vt == VT_PTR) { type_t *ref = is_ptr(type) ? - type_pointer_get_ref(type) : type_array_get_element(type); + type_pointer_get_ref_type(type) : type_array_get_element_type(type); int skip_ptr = encode_var(typelib, ref, var, &target_type, &child_size); if(skip_ptr == 2) { @@ -1125,7 +1118,7 @@ static int encode_var( if (target_type & 0x80000000) { mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF; } else if (get_type_vt(ref) == VT_SAFEARRAY) { - type_t *element_type = type_alias_get_aliasee(type_array_get_element(ref)); + type_t *element_type = type_alias_get_aliasee_type(type_array_get_element_type(ref)); mix_field = get_type_vt(element_type) | VT_ARRAY | VT_BYREF; } else { typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type]; @@ -1205,7 +1198,8 @@ static void write_default_value(msft_typelib_t *typelib, type_t *type, expr_t *e int vt; if (expr->type == EXPR_STRLIT || expr->type == EXPR_WSTRLIT) { - if (get_type_vt(type) != VT_BSTR) + vt = get_type_vt(type); + if (vt != VT_BSTR && vt != VT_VARIANT) error("string default value applied to non-string type\n"); chat("default value '%s'\n", expr->u.sval); write_string_value(typelib, out, expr->u.sval); @@ -1215,7 +1209,7 @@ static void write_default_value(msft_typelib_t *typelib, type_t *type, expr_t *e if (type_get_type(type) == TYPE_ENUM) { vt = VT_I4; } else if (is_ptr(type)) { - vt = get_type_vt(type_pointer_get_ref(type)); + vt = get_type_vt(type_pointer_get_ref_type(type)); if (vt == VT_USERDEFINED) vt = VT_I4; if (expr->cval) @@ -1235,6 +1229,23 @@ static void write_default_value(msft_typelib_t *typelib, type_t *type, expr_t *e case VT_UINT: case VT_HRESULT: break; + case VT_USERDEFINED: + vt = VT_I4; + break; + case VT_VARIANT: { + switch (expr->type) { + case EXPR_DOUBLE: + vt = VT_R4; + break; + case EXPR_NUM: + vt = VT_I4; + break; + default: + warning("can't write default VT_VARIANT value for expression type %d.\n", expr->type); + return; + } + break; + } default: warning("can't write value of type %d yet\n", vt); return; @@ -1244,22 +1255,30 @@ static void write_default_value(msft_typelib_t *typelib, type_t *type, expr_t *e write_int_value(typelib, out, vt, expr->cval); } -static HRESULT set_custdata(msft_typelib_t *typelib, REFGUID guid, - int vt, const void *value, int *offset) +static void set_custdata(msft_typelib_t *typelib, const struct uuid *guid, + int vt, const void *value, int *offset) { - MSFT_GuidEntry guidentry; int guidoffset; int custoffset; int *custdata; int data_out; + int hash_key; - guidentry.guid = *guid; + hash_key = ctl2_hash_guid(guid); + guidoffset = ctl2_find_guid(typelib, hash_key, guid); + if(guidoffset == -1) { + /* add GUID that was not already present */ + MSFT_GuidEntry guidentry; + guidentry.guid = *guid; - guidentry.hreftype = -1; - guidentry.next_hash = -1; + guidentry.hreftype = -1; + guidentry.next_hash = -1; + + guidoffset = ctl2_alloc_guid(typelib, &guidentry); + } - guidoffset = ctl2_alloc_guid(typelib, &guidentry); if(vt == VT_BSTR) + /* TODO midl appears to share a single reference if the same string is used as custdata in multiple places */ write_string_value(typelib, &data_out, value); else write_int_value(typelib, &data_out, vt, *(int*)value); @@ -1271,23 +1290,39 @@ static HRESULT set_custdata(msft_typelib_t *typelib, REFGUID guid, custdata[1] = data_out; custdata[2] = *offset; *offset = custoffset; - - return S_OK; } -static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) +static void set_custdata_attr(msft_typelib_t *typelib, attr_custdata_t *custdata, int *offset) +{ + switch(custdata->pval->type) { + case EXPR_STRLIT: + case EXPR_WSTRLIT: + set_custdata(typelib, &custdata->id, VT_BSTR, custdata->pval->u.sval, offset); + break; + case EXPR_NUM: + set_custdata(typelib, &custdata->id, VT_I4, &custdata->pval->u.integer.value, offset); + break; + default: + error("custom() attribute with unknown type\n"); + break; + } +} + +static int add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) { int offset, name_offset; int *typedata, typedata_size; int i, id, next_idx; int decoded_size, extra_attr = 0; int num_params = 0, num_optional = 0, num_defaults = 0; + int has_arg_custdata = 0; var_t *arg; unsigned char *namedata; const attr_t *attr; unsigned int funcflags = 0, callconv = 4 /* CC_STDCALL */; unsigned int funckind, invokekind = 1 /* INVOKE_FUNC */; int help_context = 0, help_string_context = 0, help_string_offset = -1; + int func_custdata_offset = -1; int entry = -1, entry_is_ord = 0; int lcid_retval_count = 0; @@ -1309,11 +1344,11 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) if (is_local( func->attrs )) { chat("add_func_desc: skipping local function\n"); - return S_FALSE; + return FALSE; } - if (type_get_function_args(func->type)) - LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), var_t, entry ) + if (type_function_get_args(func->declspec.type)) + LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), var_t, entry ) { num_params++; if (arg->attrs) LIST_FOR_EACH_ENTRY( attr, arg->attrs, const attr_t, entry ) { @@ -1321,6 +1356,8 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) num_defaults++; else if(attr->type == ATTR_OPTIONAL) num_optional++; + else if(attr->type == ATTR_CUSTOM) + has_arg_custdata = 1; } } @@ -1334,6 +1371,9 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) case ATTR_BINDABLE: funcflags |= 0x4; /* FUNCFLAG_FBINDABLE */ break; + case ATTR_CUSTOM: + set_custdata_attr(typeinfo->typelib, attr->u.pval, &func_custdata_offset); + break; case ATTR_DEFAULTBIND: funcflags |= 0x20; /* FUNCFLAG_FDEFAULTBIND */ break; @@ -1354,7 +1394,7 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) break; case ATTR_HELPCONTEXT: extra_attr = max(extra_attr, 1); - help_context = expr->u.lval; + help_context = expr->u.integer.value; break; case ATTR_HELPSTRING: extra_attr = max(extra_attr, 2); @@ -1362,7 +1402,7 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) break; case ATTR_HELPSTRINGCONTEXT: extra_attr = max(extra_attr, 6); - help_string_context = expr->u.lval; + help_string_context = expr->u.integer.value; break; case ATTR_HIDDEN: funcflags |= 0x40; /* FUNCFLAG_FHIDDEN */ @@ -1378,6 +1418,9 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) break; case ATTR_OUT: break; + case ATTR_DEFAULT_OVERLOAD: + case ATTR_OVERLOAD: + break; case ATTR_PROPGET: invokekind = 0x2; /* INVOKE_PROPERTYGET */ break; @@ -1414,6 +1457,10 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) } } + if(has_arg_custdata || func_custdata_offset != -1) { + extra_attr = max(extra_attr, 7 + num_params); + } + /* allocate type data space for us */ typedata_size = 0x18 + extra_attr * sizeof(int) + (num_params * (num_defaults ? 16 : 12)); @@ -1455,11 +1502,12 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) /* fill out the basic type information */ typedata[0] = typedata_size | (index << 16); - encode_var(typeinfo->typelib, type_function_get_rettype(func->type), func, + encode_var(typeinfo->typelib, type_function_get_rettype(func->declspec.type), func, &typedata[1], &decoded_size); typedata[2] = funcflags; typedata[3] = ((52 /*sizeof(FUNCDESC)*/ + decoded_size) << 16) | typeinfo->typeinfo->cbSizeVft; typedata[4] = (next_idx << 16) | (callconv << 8) | (invokekind << 3) | funckind; + if(has_arg_custdata || func_custdata_offset != -1) typedata[4] |= 0x0080; if(num_defaults) typedata[4] |= 0x1000; if(entry_is_ord) typedata[4] |= 0x2000; typedata[5] = (num_optional << 16) | num_params; @@ -1470,6 +1518,10 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) typedata[3] += (24 /*sizeof(PARAMDESCEX)*/ * num_defaults) << 16; switch(extra_attr) { + default: + if(extra_attr > 7 + num_params) warning("unknown number of optional attrs\n"); + /* typedata[13..+num_params] = arg_custdata_offset handled in below loop */ + case 7: typedata[12] = func_custdata_offset; case 6: typedata[11] = help_string_context; case 5: typedata[10] = -1; case 4: typedata[9] = -1; @@ -1478,28 +1530,30 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) case 1: typedata[6] = help_context; case 0: break; - default: - warning("unknown number of optional attrs\n"); } - if (type_get_function_args(func->type)) + if (type_function_get_args(func->declspec.type)) { i = 0; - LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), var_t, entry ) + LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), var_t, entry ) { int paramflags = 0; int *paramdata = typedata + 6 + extra_attr + (num_defaults ? num_params : 0) + i * 3; int *defaultdata = num_defaults ? typedata + 6 + extra_attr + i : NULL; + int arg_custdata_offset = -1; if(defaultdata) *defaultdata = -1; - encode_var(typeinfo->typelib, arg->type, arg, paramdata, &decoded_size); + encode_var(typeinfo->typelib, arg->declspec.type, arg, paramdata, &decoded_size); if (arg->attrs) LIST_FOR_EACH_ENTRY( attr, arg->attrs, const attr_t, entry ) { switch(attr->type) { + case ATTR_CUSTOM: + set_custdata_attr(typeinfo->typelib, attr->u.pval, &arg_custdata_offset); + break; case ATTR_DEFAULTVALUE: { paramflags |= 0x30; /* PARAMFLAG_FHASDEFAULT | PARAMFLAG_FOPT */ - write_default_value(typeinfo->typelib, arg->type, (expr_t *)attr->u.pval, defaultdata); + write_default_value(typeinfo->typelib, arg->declspec.type, (expr_t *)attr->u.pval, defaultdata); break; } case ATTR_IN: @@ -1523,6 +1577,9 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) chat("unhandled param attr %d\n", attr->type); break; } + if(extra_attr > 7 + i) { + typedata[13+i] = arg_custdata_offset; + } } paramdata[1] = -1; paramdata[2] = paramflags; @@ -1573,8 +1630,8 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) typeinfo->typeinfo->cElement += 1; namedata = typeinfo->typelib->typelib_segment_data[MSFT_SEG_NAME] + name_offset; - if (*((INT *)namedata) == -1) { - *((INT *)namedata) = typeinfo->typelib->typelib_typeinfo_offsets[typeinfo->typeinfo->typekind >> 16]; + if (*((int *)namedata) == -1) { + *((int *)namedata) = typeinfo->typelib->typelib_typeinfo_offsets[typeinfo->typeinfo->typekind >> 16]; if(typeinfo->typekind == TKIND_MODULE) namedata[9] |= 0x10; } else @@ -1583,10 +1640,10 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) if(typeinfo->typekind == TKIND_MODULE) namedata[9] |= 0x20; - if (type_get_function_args(func->type)) + if (type_function_get_args(func->declspec.type)) { i = 0; - LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), var_t, entry ) + LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), var_t, entry ) { /* don't give the last arg of a [propput*] func a name */ if(i != num_params - 1 || (invokekind != 0x4 /* INVOKE_PROPERTYPUT */ && invokekind != 0x8 /* INVOKE_PROPERTYPUTREF */)) @@ -1598,21 +1655,26 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index) i++; } } - return S_OK; + return TRUE; } -static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var) +static void add_var_desc(msft_typeinfo_t *typeinfo, unsigned int index, var_t* var) { int offset, id; unsigned int typedata_size; - INT *typedata; + int extra_attr = 0; + int *typedata; unsigned int var_datawidth, var_alignment = 0; - int var_type_size, var_kind = 0 /* VAR_PERINSTANCE */; + int var_type_size, var_kind = 0 /* VAR_PERINSTANCE */; int alignment; int varflags = 0; const attr_t *attr; unsigned char *namedata; int var_num = (typeinfo->typeinfo->cElement >> 16) & 0xffff; + int var_custdata_offset = -1; + + if (!var->name) + var->name = gen_name(); chat("add_var_desc(%d, %s)\n", index, var->name); @@ -1624,6 +1686,10 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var) case ATTR_BINDABLE: varflags |= 0x04; /* VARFLAG_FBINDABLE */ break; + case ATTR_CUSTOM: + extra_attr = max(extra_attr,4); + set_custdata_attr(typeinfo->typelib, attr->u.pval, &var_custdata_offset); + break; case ATTR_DEFAULTBIND: varflags |= 0x20; /* VARFLAG_FDEFAULTBIND */ break; @@ -1667,7 +1733,7 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var) } /* allocate type data space for us */ - typedata_size = 0x14; + typedata_size = 0x14 + extra_attr * sizeof(int); if (!typeinfo->var_data) { typeinfo->var_data = xmalloc(0x100); @@ -1708,8 +1774,8 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var) typeinfo->var_offsets[var_num] = offset; /* figure out type widths and whatnot */ - var_datawidth = type_memsize_and_alignment(var->type, &var_alignment); - encode_var(typeinfo->typelib, var->type, var, &typedata[1], &var_type_size); + var_datawidth = type_memsize_and_alignment(var->declspec.type, &var_alignment); + encode_var(typeinfo->typelib, var->declspec.type, var, &typedata[1], &var_type_size); /* pad out starting position to data width */ typeinfo->datawidth += var_alignment - 1; @@ -1727,11 +1793,12 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var) typeinfo->datawidth += var_datawidth; break; case TKIND_UNION: - typedata[4] = typeinfo->datawidth; + typedata[4] = 0; typeinfo->datawidth = max(typeinfo->datawidth, var_datawidth); break; case TKIND_DISPATCH: var_kind = 3; /* VAR_DISPATCH */ + typedata[4] = 0; typeinfo->datawidth = pointer_size; break; default: @@ -1742,6 +1809,18 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var) /* add type description size to total required allocation */ typedata[3] += var_type_size << 16 | var_kind; + switch(extra_attr) { + case 5: typedata[9] = -1 /*help_string_context*/; + case 4: typedata[8] = var_custdata_offset; + case 3: typedata[7] = -1; + case 2: typedata[6] = -1 /*help_string_offset*/; + case 1: typedata[5] = -1 /*help_context*/; + case 0: + break; + default: + warning("unknown number of optional attrs\n"); + } + /* fix type alignment */ alignment = (typeinfo->typeinfo->typekind >> 11) & 0x1f; if (alignment < var_alignment) { @@ -1767,11 +1846,10 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var) 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]; + if (*((int *)namedata) == -1) { + *((int *)namedata) = typeinfo->typelib->typelib_typeinfo_offsets[typeinfo->typeinfo->typekind >> 16]; if(typeinfo->typekind != TKIND_DISPATCH) namedata[9] |= 0x10; } else @@ -1781,11 +1859,9 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var) namedata[9] |= 0x20; } typeinfo->var_names[var_num] = offset; - - return S_OK; } -static HRESULT add_impl_type(msft_typeinfo_t *typeinfo, type_t *ref, importinfo_t *importinfo) +static void add_impl_type(msft_typeinfo_t *typeinfo, type_t *ref, importinfo_t *importinfo) { if(importinfo) { alloc_importinfo(typeinfo->typelib, importinfo); @@ -1800,7 +1876,6 @@ static HRESULT add_impl_type(msft_typeinfo_t *typeinfo, type_t *ref, importinfo_ } typeinfo->typeinfo->cImplTypes++; - return S_OK; } static msft_typeinfo_t *create_msft_typeinfo(msft_typelib_t *typelib, enum type_kind kind, @@ -1851,7 +1926,9 @@ static msft_typeinfo_t *create_msft_typeinfo(msft_typelib_t *typelib, enum type_ if (kind == TKIND_COCLASS) typeinfo->flags |= 0x20; /* TYPEFLAG_FCONTROL */ break; - + case ATTR_CUSTOM: + set_custdata_attr(typelib, attr->u.pval, &typeinfo->oCustData); + break; case ATTR_DLLNAME: { int offset = ctl2_alloc_string(typelib, attr->u.pval); @@ -1917,7 +1994,7 @@ static msft_typeinfo_t *create_msft_typeinfo(msft_typelib_t *typelib, enum type_ break; case ATTR_UUID: - guidentry.guid = *(GUID*)attr->u.pval; + guidentry.guid = *(struct uuid *)attr->u.pval; guidentry.hreftype = typelib->typelib_typeinfo_offsets[typeinfo->typekind >> 16]; guidentry.next_hash = -1; typeinfo->posguid = ctl2_alloc_guid(typelib, &guidentry); @@ -1950,8 +2027,8 @@ static void add_dispatch(msft_typelib_t *typelib) int guid_offset, impfile_offset, hash_key; MSFT_GuidEntry guidentry; MSFT_ImpInfo impinfo; - GUID stdole = {0x00020430,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; - GUID iid_idispatch = {0x00020400,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; + static const struct uuid stdole = {0x00020430,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; + static const struct uuid iid_idispatch = {0x00020400,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; if(typelib->typelib_header.dispatchpos != -1) return; @@ -2049,9 +2126,13 @@ static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinte { idx = 0; LIST_FOR_EACH_ENTRY( func, type_dispiface_get_methods(dispinterface), var_t, entry ) - if(add_func_desc(msft_typeinfo, func, idx) == S_OK) + if(add_func_desc(msft_typeinfo, func, idx)) idx++; } + + typelib->typelib->reg_ifaces = xrealloc(typelib->typelib->reg_ifaces, + (typelib->typelib->reg_iface_count + 1) * sizeof(dispinterface)); + typelib->typelib->reg_ifaces[typelib->typelib->reg_iface_count++] = dispinterface; } static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface) @@ -2123,13 +2204,21 @@ static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface) STATEMENTS_FOR_EACH_FUNC( stmt_func, type_iface_get_stmts(interface) ) { var_t *func = stmt_func->u.var; - if(add_func_desc(msft_typeinfo, func, idx) == S_OK) + if(add_func_desc(msft_typeinfo, func, idx)) idx++; } + + if (is_attr(interface->attrs, ATTR_OLEAUTOMATION) || is_attr(interface->attrs, ATTR_DUAL)) + { + typelib->typelib->reg_ifaces = xrealloc(typelib->typelib->reg_ifaces, + (typelib->typelib->reg_iface_count + 1) * sizeof(interface)); + typelib->typelib->reg_ifaces[typelib->typelib->reg_iface_count++] = interface; + } } static void add_structure_typeinfo(msft_typelib_t *typelib, type_t *structure) { + var_list_t *fields; int idx = 0; var_t *cur; msft_typeinfo_t *msft_typeinfo; @@ -2137,13 +2226,23 @@ static void add_structure_typeinfo(msft_typelib_t *typelib, type_t *structure) if (-1 < structure->typelib_idx) return; + if (!structure->name) + structure->name = gen_name(); + structure->typelib_idx = typelib->typelib_header.nrtypeinfos; msft_typeinfo = create_msft_typeinfo(typelib, TKIND_RECORD, structure->name, structure->attrs); msft_typeinfo->typeinfo->size = 0; - if (type_struct_get_fields(structure)) - LIST_FOR_EACH_ENTRY( cur, type_struct_get_fields(structure), var_t, entry ) + if (type_get_type(structure) == TYPE_STRUCT) + fields = type_struct_get_fields(structure); + else + fields = type_encapsulated_union_get_fields(structure); + + if (fields) + { + LIST_FOR_EACH_ENTRY( cur, fields, var_t, entry ) add_var_desc(msft_typeinfo, idx++, cur); + } } static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration) @@ -2173,6 +2272,9 @@ static void add_union_typeinfo(msft_typelib_t *typelib, type_t *tunion) if (-1 < tunion->typelib_idx) return; + if (!tunion->name) + tunion->name = gen_name(); + tunion->typelib_idx = typelib->typelib_header.nrtypeinfos; msft_typeinfo = create_msft_typeinfo(typelib, TKIND_UNION, tunion->name, tunion->attrs); msft_typeinfo->typeinfo->size = 0; @@ -2192,7 +2294,7 @@ static void add_typedef_typeinfo(msft_typelib_t *typelib, type_t *tdef) if (-1 < tdef->typelib_idx) return; - type = type_alias_get_aliasee(tdef); + type = type_alias_get_aliasee_type(tdef); if (!type->name || strcmp(tdef->name, type->name) != 0) { @@ -2221,12 +2323,12 @@ static void add_typedef_typeinfo(msft_typelib_t *typelib, type_t *tdef) static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls) { msft_typeinfo_t *msft_typeinfo; - ifref_t *iref; + typeref_t *iref; int num_ifaces = 0, offset, i; MSFT_RefRecord *ref, *first = NULL, *first_source = NULL; int have_default = 0, have_default_source = 0; const attr_t *attr; - ifref_list_t *ifaces; + typeref_list_t *ifaces; if (-1 < cls->typelib_idx) return; @@ -2235,17 +2337,17 @@ static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls) msft_typeinfo = create_msft_typeinfo(typelib, TKIND_COCLASS, cls->name, cls->attrs); ifaces = type_coclass_get_ifaces(cls); - if (ifaces) LIST_FOR_EACH_ENTRY( iref, ifaces, ifref_t, entry ) num_ifaces++; + if (ifaces) LIST_FOR_EACH_ENTRY( iref, ifaces, typeref_t, entry ) num_ifaces++; offset = msft_typeinfo->typeinfo->datatype1 = ctl2_alloc_segment(typelib, MSFT_SEG_REFERENCES, num_ifaces * sizeof(*ref), 0); i = 0; - if (ifaces) LIST_FOR_EACH_ENTRY( iref, ifaces, ifref_t, entry ) { - if(iref->iface->typelib_idx == -1) - add_interface_typeinfo(typelib, iref->iface); + if (ifaces) LIST_FOR_EACH_ENTRY( iref, ifaces, typeref_t, entry ) { + if(iref->type->typelib_idx == -1) + add_interface_typeinfo(typelib, iref->type); ref = (MSFT_RefRecord*) (typelib->typelib_segment_data[MSFT_SEG_REFERENCES] + offset + i * sizeof(*ref)); - ref->reftype = typelib->typelib_typeinfo_offsets[iref->iface->typelib_idx]; + ref->reftype = typelib->typelib_typeinfo_offsets[iref->type->typelib_idx]; ref->flags = 0; ref->oCustData = -1; ref->onext = -1; @@ -2317,7 +2419,7 @@ static void add_module_typeinfo(msft_typelib_t *typelib, type_t *module) STATEMENTS_FOR_EACH_FUNC( stmt, module->details.module->stmts ) { var_t *func = stmt->u.var; - if(add_func_desc(msft_typeinfo, func, idx) == S_OK) + if(add_func_desc(msft_typeinfo, func, idx)) idx++; } @@ -2331,6 +2433,7 @@ static void add_type_typeinfo(msft_typelib_t *typelib, type_t *type) add_interface_typeinfo(typelib, type); break; case TYPE_STRUCT: + case TYPE_ENCAPSULATED_UNION: add_structure_typeinfo(typelib, type); break; case TYPE_ENUM: @@ -2368,14 +2471,14 @@ static void add_entry(msft_typelib_t *typelib, const statement_t *stmt) break; case STMT_TYPEDEF: { - const type_list_t *type_entry = stmt->u.type_list; - for (; type_entry; type_entry = type_entry->next) { + typeref_t *ref; + if (stmt->u.type_list) LIST_FOR_EACH_ENTRY(ref, stmt->u.type_list, typeref_t, entry) { /* if the type is public then add the typedef, otherwise attempt * to add the aliased type */ - if (is_attr(type_entry->type->attrs, ATTR_PUBLIC)) - add_typedef_typeinfo(typelib, type_entry->type); + if (is_attr(ref->type->attrs, ATTR_PUBLIC)) + add_typedef_typeinfo(typelib, ref->type); else - add_type_typeinfo(typelib, type_alias_get_aliasee(type_entry->type)); + add_type_typeinfo(typelib, type_alias_get_aliasee_type(ref->type)); } break; } @@ -2409,17 +2512,11 @@ static void set_version(msft_typelib_t *typelib) static void set_guid(msft_typelib_t *typelib) { - MSFT_GuidEntry guidentry; + MSFT_GuidEntry guidentry = { {0}, -2, -1 }; int offset; - void *ptr; - GUID guid = {0,0,0,{0,0,0,0,0,0}}; + struct uuid *ptr = get_attrp( typelib->typelib->attrs, ATTR_UUID ); - guidentry.guid = guid; - guidentry.hreftype = -2; - guidentry.next_hash = -1; - - ptr = get_attrp( typelib->typelib->attrs, ATTR_UUID ); - if (ptr) guidentry.guid = *(GUID *)ptr; + if (ptr) guidentry.guid = *ptr; offset = ctl2_alloc_guid(typelib, &guidentry); typelib->typelib_header.posguid = offset; @@ -2517,7 +2614,8 @@ static void set_lib_flags(msft_typelib_t *typelib) static void ctl2_write_segment(msft_typelib_t *typelib, int segment) { - put_data(typelib->typelib_segment_data[segment], typelib->typelib_segdir[segment].length); + if (typelib->typelib_segment_data[segment]) + put_data(typelib->typelib_segment_data[segment], typelib->typelib_segdir[segment].length); } static void ctl2_finalize_typeinfos(msft_typelib_t *typelib, int filesize) @@ -2613,7 +2711,6 @@ static void save_all_changes(msft_typelib_t *typelib) ctl2_finalize_typeinfos(typelib, filepos); - byte_swapped = 0; init_output_buffer(); put_data(&typelib->typelib_header, sizeof(typelib->typelib_header)); @@ -2644,9 +2741,10 @@ static void save_all_changes(msft_typelib_t *typelib) expr_t *expr = get_attrp( typelib->typelib->attrs, ATTR_ID ); if (expr) - sprintf( typelib_id, "#%d", expr->cval ); + snprintf( typelib_id, sizeof(typelib_id), "#%d", expr->cval ); add_output_to_resources( "TYPELIB", typelib_id ); - output_typelib_regscript( typelib->typelib ); + if (strendswith( typelib_name, "_t.res" )) /* add typelib registration */ + output_typelib_regscript( typelib->typelib ); #ifdef __REACTOS__ flush_output_resources( typelib_name ); #endif @@ -2659,12 +2757,12 @@ int create_msft_typelib(typelib_t *typelib) msft_typelib_t *msft; int failed = 0; const statement_t *stmt; + const attr_t *attr; time_t cur_time; - char *time_override; unsigned int version = 7 << 24 | 555; /* 7.00.0555 */ - GUID midl_time_guid = {0xde77ba63,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}}; - GUID midl_version_guid = {0xde77ba64,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}}; - GUID midl_info_guid = {0xde77ba65,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}}; + static const struct uuid midl_time_guid = {0xde77ba63,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}}; + static const struct uuid midl_version_guid = {0xde77ba64,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}}; + static const struct uuid midl_info_guid = {0xde77ba65,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}}; char info_string[128]; msft = xmalloc(sizeof(*msft)); @@ -2706,11 +2804,23 @@ int create_msft_typelib(typelib_t *typelib) set_help_string_dll(msft); set_help_string_context(msft); - /* midl adds two sets of custom data to the library: the current unix time - and midl's version number */ - time_override = getenv( "WIDL_TIME_OVERRIDE"); - cur_time = time_override ? atol( time_override) : time(NULL); - sprintf(info_string, "Created by WIDL version %s at %s\n", PACKAGE_VERSION, ctime(&cur_time)); + if (typelib->attrs) LIST_FOR_EACH_ENTRY( attr, typelib->attrs, const attr_t, entry ) { + switch(attr->type) { + case ATTR_CUSTOM: + set_custdata_attr(msft, attr->u.pval, &msft->typelib_header.CustomDataOffset); + break; + default: + break; + } + } + + /* midl adds three sets of custom data to the library: + * - 2147483647 (INT_MAX, previously the current Unix time) + * - midl's version number + * - a string representation of those + */ + cur_time = 2147483647; + snprintf(info_string, sizeof(info_string), "Created by WIDL version %s at %s", PACKAGE_VERSION, asctime(gmtime(&cur_time))); set_custdata(msft, &midl_info_guid, VT_BSTR, info_string, &msft->typelib_header.CustomDataOffset); set_custdata(msft, &midl_time_guid, VT_UI4, &cur_time, &msft->typelib_header.CustomDataOffset); set_custdata(msft, &midl_version_guid, VT_UI4, &version, &msft->typelib_header.CustomDataOffset); diff --git a/sdk/tools/widl/write_sltg.c b/sdk/tools/widl/write_sltg.c index 0fb5ffe642e..77720adc2ae 100644 --- a/sdk/tools/widl/write_sltg.c +++ b/sdk/tools/widl/write_sltg.c @@ -19,7 +19,6 @@ */ #include "config.h" -#include "wine/port.h" #include #include @@ -28,23 +27,37 @@ #include #include -#define NONAMELESSUNION - +#include "widl.h" #ifdef __REACTOS__ #include #include +#include #else #include "windef.h" #include "winbase.h" #endif -#include "widl.h" #include "typelib.h" #include "typelib_struct.h" #include "utils.h" #include "header.h" #include "typetree.h" +#ifdef __REACTOS__ + +typedef struct _GUID +{ +#ifdef _MSC_VER + unsigned long Data1; +#else + unsigned int Data1; +#endif + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[ 8 ]; +} GUID; +#endif + static const GUID sltg_library_guid = { 0x204ff,0,0,{ 0xc0,0,0,0,0,0,0,0x46 } }; struct sltg_data @@ -71,7 +84,6 @@ struct sltg_block int length; int index_string; void *data; - struct sltg_block *next; }; struct sltg_typelib @@ -81,9 +93,9 @@ struct sltg_typelib struct sltg_data name_table; struct sltg_library library; struct sltg_block *blocks; - int n_file_blocks; + int block_count; int first_block; - int typeinfo_count; + short typeinfo_count; int typeinfo_size; struct sltg_block *typeinfo; }; @@ -133,7 +145,7 @@ struct sltg_variable int memid; short helpcontext; short helpstring; - short varflags; /* only present if magic & 0x02 */ + short varflags; /* only present if magic & 0x20 */ }; struct sltg_tail @@ -171,23 +183,7 @@ struct sltg_hrefinfo { char magic; /* 0xdf */ char res01; /* 0x00 */ - int res02; /* 0xffffffff */ - int res06; /* 0xffffffff */ - int res0a; /* 0xffffffff */ - int res0e; /* 0xffffffff */ - int res12; /* 0xffffffff */ - int res16; /* 0xffffffff */ - int res1a; /* 0xffffffff */ - int res1e; /* 0xffffffff */ - int res22; /* 0xffffffff */ - int res26; /* 0xffffffff */ - int res2a; /* 0xffffffff */ - int res2e; /* 0xffffffff */ - int res32; /* 0xffffffff */ - int res36; /* 0xffffffff */ - int res3a; /* 0xffffffff */ - int res3e; /* 0xffffffff */ - short res42;/* 0xffff */ + char res02[0x42]; /* 0xff... */ int number; /* this is 8 times the number of refs */ /* Now we have number bytes (8 for each ref) of SLTG_UnknownRefInfo */ @@ -257,8 +253,8 @@ static void add_coclass_typeinfo(struct sltg_typelib *typelib, type_t *type); static void init_sltg_data(struct sltg_data *data) { data->size = 0; - data->allocated = 0x10; - data->data = xmalloc(0x10); + data->allocated = 0; + data->data = NULL; } static int add_index(struct sltg_data *index, const char *name) @@ -270,7 +266,7 @@ static int add_index(struct sltg_data *index, const char *name) if (new_size > index->allocated) { - index->allocated = max(index->allocated * 2, new_size); + index->allocated = index->allocated ? max(index->allocated * 2, new_size) : new_size; index->data = xrealloc(index->data, index->allocated); } @@ -289,10 +285,10 @@ static void init_index(struct sltg_data *index) add_index(index, compobj); } -static int add_name(struct sltg_typelib *sltg, const char *name) +static int add_name(struct sltg_data *name_table, const char *name) { - int name_offset = sltg->name_table.size; - int new_size = sltg->name_table.size + strlen(name) + 1 + 8; + int name_offset = name_table->size; + int new_size = name_table->size + strlen(name) + 1 + 8; int aligned_size; chat("add_name: %s\n", name); @@ -303,33 +299,37 @@ static int add_name(struct sltg_typelib *sltg, const char *name) else new_size = (new_size + 1) & ~1; - if (new_size > sltg->name_table.allocated) + if (new_size > name_table->allocated) { - sltg->name_table.allocated = max(sltg->name_table.allocated * 2, new_size); - sltg->name_table.data = xrealloc(sltg->name_table.data, sltg->name_table.allocated); + name_table->allocated = name_table->allocated ? max(name_table->allocated * 2, new_size) : new_size; + name_table->data = xrealloc(name_table->data, name_table->allocated); } - memset(sltg->name_table.data + sltg->name_table.size, 0xff, 8); - strcpy(sltg->name_table.data + sltg->name_table.size + 8, name); - sltg->name_table.size = new_size; - sltg->name_table.data[sltg->name_table.size - 1] = 0; /* clear alignment */ + memset(name_table->data + name_table->size, 0xff, 8); + strcpy(name_table->data + name_table->size + 8, name); + name_table->size = new_size; + name_table->data[name_table->size - 1] = 0; /* clear alignment */ return name_offset; } -static void init_name_table(struct sltg_typelib *sltg) +static void init_name_table(struct sltg_data *name_table) { - init_sltg_data(&sltg->name_table); + init_sltg_data(name_table); } static void init_library(struct sltg_typelib *sltg) { const attr_t *attr; - sltg->library.name = add_name(sltg, sltg->typelib->name); + sltg->library.name = add_name(&sltg->name_table, sltg->typelib->name); sltg->library.helpstring = NULL; sltg->library.helpcontext = 0; +#ifdef __REACTOS__ sltg->library.syskind = (pointer_size == 8) ? SYS_WIN64 : SYS_WIN32; +#else + sltg->library.syskind = SYS_WIN32; +#endif sltg->library.lcid = 0x0409; sltg->library.libflags = 0; sltg->library.version = 0; @@ -379,28 +379,13 @@ static void init_library(struct sltg_typelib *sltg) } } -static void add_block_index(struct sltg_typelib *sltg, void *data, int size, int index) +static void add_block_index(struct sltg_typelib *sltg, void *data, int length, int index) { - struct sltg_block *block = xmalloc(sizeof(*block)); - - block->length = size; - block->data = data; - block->index_string = index; - block->next = NULL; - - if (sltg->blocks) - { - struct sltg_block *blocks = sltg->blocks; - - while (blocks->next) - blocks = blocks->next; - - blocks->next = block; - } - else - sltg->blocks = block; - - sltg->n_file_blocks++; + sltg->blocks = xrealloc(sltg->blocks, sizeof(sltg->blocks[0]) * (sltg->block_count + 1)); + sltg->blocks[sltg->block_count].length = length; + sltg->blocks[sltg->block_count].data = data; + sltg->blocks[sltg->block_count].index_string = index; + sltg->block_count++; } static void add_block(struct sltg_typelib *sltg, void *data, int size, const char *name) @@ -464,7 +449,7 @@ static void *create_library_block(struct sltg_typelib *typelib, int *size, int * static const char *new_index_name(void) { - static char name[11] = "0000000000"; + static char name[11] = "AAAAAAAAAA"; static int pos = 0; char *new_name; @@ -482,31 +467,16 @@ static const char *new_index_name(void) return new_name; } -static void sltg_add_typeinfo(struct sltg_typelib *sltg, void *data, int size, const char *name) +static void sltg_add_typeinfo(struct sltg_typelib *sltg, void *data, int length, const char *name) { - struct sltg_block *block = xmalloc(sizeof(*block)); - - chat("sltg_add_typeinfo: %p,%d,%s\n", data, size, name); - - block->length = size; - block->data = data; - block->index_string = 0; - block->next = NULL; - - if (sltg->typeinfo) - { - struct sltg_block *typeinfo = sltg->typeinfo; - - while (typeinfo->next) - typeinfo = typeinfo->next; - - typeinfo->next = block; - } - else - sltg->typeinfo = block; + chat("sltg_add_typeinfo: %p,%d,%s\n", data, length, name); + sltg->typeinfo = xrealloc(sltg->typeinfo, sizeof(sltg->typeinfo[0]) * (sltg->typeinfo_count + 1)); + sltg->typeinfo[sltg->typeinfo_count].length = length; + sltg->typeinfo[sltg->typeinfo_count].data = data; + sltg->typeinfo[sltg->typeinfo_count].index_string = 0; sltg->typeinfo_count++; - sltg->typeinfo_size += size; + sltg->typeinfo_size += length; } static void append_data(struct sltg_data *block, const void *data, int size) @@ -528,12 +498,13 @@ static void add_module_typeinfo(struct sltg_typelib *typelib, type_t *type) error("add_module_typeinfo: %s not implemented\n", type->name); } -static const char *add_typeinfo_block(struct sltg_typelib *typelib, const type_t *type, int kind) +static const char *add_typeinfo_block(struct sltg_typelib *typelib, const type_t *type, short kind) { + struct sltg_data block; const char *index_name, *other_name; - void *block; - short *p; - int size, helpcontext = 0; + short val; + void *p; + int helpcontext = 0; GUID guid = { 0 }; const expr_t *expr; @@ -546,38 +517,40 @@ static const char *add_typeinfo_block(struct sltg_typelib *typelib, const type_t p = get_attrp(type->attrs, ATTR_UUID); if (p) guid = *(GUID *)p; - size = sizeof(short) * 8 + 10 /* index_name */ * 2 + sizeof(int) + sizeof(GUID); + init_sltg_data(&block); - block = xmalloc(size); - p = block; - *p++ = strlen(index_name); - strcpy((char *)p, index_name); - p = (short *)((char *)p + strlen(index_name)); - *p++ = strlen(other_name); - strcpy((char *)p, other_name); - p = (short *)((char *)p + strlen(other_name)); - *p++ = -1; /* res1a */ - *p++ = add_name(typelib, type->name); /* name offset */ - *p++ = 0; /* FIXME: helpstring */ - *p++ = -1; /* res20 */ - *(int *)p = helpcontext; - p += 2; - *p++ = -1; /* res26 */ - *(GUID *)p = guid; - p += sizeof(GUID)/2; - *p = kind; + val = strlen(index_name); + append_data(&block, &val, sizeof(val)); + append_data(&block, index_name, val); + val = strlen(other_name); + append_data(&block, &val, sizeof(val)); + append_data(&block, other_name, val); + val = -1; /* res1a */ + append_data(&block, &val, sizeof(val)); + val = add_name(&typelib->name_table, type->name); /* name offset */ + append_data(&block, &val, sizeof(val)); + val = 0; /* FIXME: helpstring */ + append_data(&block, &val, sizeof(val)); + val = -1; /* res20 */ + append_data(&block, &val, sizeof(val)); + append_data(&block, &helpcontext, sizeof(helpcontext)); + val = -1; /* res26 */ + append_data(&block, &val, sizeof(val)); + append_data(&block, &guid, sizeof(guid)); + append_data(&block, &kind, sizeof(kind)); - sltg_add_typeinfo(typelib, block, size, index_name); + sltg_add_typeinfo(typelib, block.data, block.size, index_name); return index_name; } -static void init_typeinfo(struct sltg_typeinfo_header *ti, const type_t *type, int kind, +static void init_typeinfo(struct sltg_typeinfo_header *ti, const type_t *type, short kind, const struct sltg_hrefmap *hrefmap) { ti->magic = 0x0501; ti->href_offset = -1; ti->res06 = -1; + ti->member_offset = sizeof(*ti); ti->res0e = -1; ti->version = get_attrv(type->attrs, ATTR_VERSION); ti->res16 = 0xfffe0000; @@ -587,8 +560,6 @@ static void init_typeinfo(struct sltg_typeinfo_header *ti, const type_t *type, i ti->misc.typekind = kind; ti->res1e = 0; - ti->member_offset = sizeof(*ti); - if (hrefmap->href_count) { char name[64]; @@ -598,7 +569,7 @@ static void init_typeinfo(struct sltg_typeinfo_header *ti, const type_t *type, i for (i = 0; i < hrefmap->href_count; i++) { - sprintf(name, "*\\Rffff*#%x", hrefmap->href[i]); + snprintf(name, sizeof(name), "*\\Rffff*#%x", hrefmap->href[i]); hrefinfo_size += 8 + 2 + strlen(name); } @@ -607,37 +578,6 @@ static void init_typeinfo(struct sltg_typeinfo_header *ti, const type_t *type, i } } -static void init_sltg_tail(struct sltg_tail *tail) -{ - tail->cFuncs = 0; - tail->cVars = 0; - tail->cImplTypes = 0; - tail->res06 = 0; - tail->funcs_off = -1; - tail->vars_off = -1; - tail->impls_off = -1; - tail->funcs_bytes = -1; - tail->vars_bytes = -1; - tail->impls_bytes = -1; - tail->tdescalias_vt = -1; - tail->res16 = -1; - tail->res18 = 0; - tail->res1a = 0; - tail->simple_alias = 0; - tail->res1e = 0; - tail->cbSizeInstance = 0; - tail->cbAlignment = 4; - tail->res24 = -1; - tail->res26 = -1; - tail->cbSizeVft = 0; - tail->res2a = -1; - tail->res2c = -1; - tail->res2e = -1; - tail->res30 = -1; - tail->res32 = 0; - tail->type_bytes = 0; -} - static void write_hrefmap(struct sltg_data *data, const struct sltg_hrefmap *hrefmap) { struct sltg_hrefinfo hrefinfo; @@ -648,23 +588,7 @@ static void write_hrefmap(struct sltg_data *data, const struct sltg_hrefmap *hre hrefinfo.magic = 0xdf; hrefinfo.res01 = 0; - hrefinfo.res02 = -1; - hrefinfo.res06 = -1; - hrefinfo.res0a = -1; - hrefinfo.res0e = -1; - hrefinfo.res12 = -1; - hrefinfo.res16 = -1; - hrefinfo.res1a = -1; - hrefinfo.res1e = -1; - hrefinfo.res22 = -1; - hrefinfo.res26 = -1; - hrefinfo.res2a = -1; - hrefinfo.res2e = -1; - hrefinfo.res32 = -1; - hrefinfo.res36 = -1; - hrefinfo.res3a = -1; - hrefinfo.res3e = -1; - hrefinfo.res42 = -1; + memset(hrefinfo.res02, 0xff, sizeof(hrefinfo.res02)); hrefinfo.number = hrefmap->href_count * 8; hrefinfo.res50 = -1; hrefinfo.res52 = 1; @@ -682,7 +606,7 @@ static void write_hrefmap(struct sltg_data *data, const struct sltg_hrefmap *hre { short len; - sprintf(name, "*\\Rffff*#%x", hrefmap->href[i]); + snprintf(name, sizeof(name), "*\\Rffff*#%x", hrefmap->href[i]); len = strlen(name); append_data(data, &len, sizeof(len)); @@ -717,15 +641,13 @@ static int get_element_size(type_t *type) case VT_UI1: return 1; - case VT_INT: - case VT_UINT: - return /* typelib_kind == SYS_WIN16 ? 2 : */ 4; - case VT_UI2: case VT_I2: case VT_BOOL: return 2; + case VT_INT: + case VT_UINT: case VT_I4: case VT_UI4: case VT_R4: @@ -749,13 +671,21 @@ static int get_element_size(type_t *type) case VT_BSTR: case VT_LPSTR: case VT_LPWSTR: +#ifdef __REACTOS__ return pointer_size; +#else + return 4; +#endif case VT_VOID: return 0; case VT_VARIANT: +#ifdef __REACTOS__ return pointer_size == 8 ? 24 : 16; +#else + return 16; +#endif case VT_USERDEFINED: return 0; @@ -817,7 +747,7 @@ static short write_var_desc(struct sltg_typelib *typelib, struct sltg_data *data short fFeatures; int cbElements; int cLocks; - void *pvData; + int pvData; int bound[2]; } *array; int *bound; @@ -833,7 +763,7 @@ static short write_var_desc(struct sltg_typelib *typelib, struct sltg_data *data num_dims++; elements *= type_array_get_dim(atype); - atype = type_array_get_element(atype); + atype = type_array_get_element_type(atype); } chat("write_var_desc: VT_CARRAY: %d dimensions, %d elements\n", num_dims, elements); @@ -847,7 +777,7 @@ static short write_var_desc(struct sltg_typelib *typelib, struct sltg_data *data array->fFeatures = 0x0004; /* FADF_EMBEDDED */ array->cbElements = get_element_size(atype); array->cLocks = 0; - array->pvData = NULL; + array->pvData = 0; bound = array->bound; @@ -861,7 +791,7 @@ static short write_var_desc(struct sltg_typelib *typelib, struct sltg_data *data bound[1] = 0; bound += 2; - atype = type_array_get_element(atype); + atype = type_array_get_element_type(atype); } if (size_instance) @@ -888,7 +818,7 @@ static short write_var_desc(struct sltg_typelib *typelib, struct sltg_data *data if (vt == VT_PTR) { - type_t *ref = is_ptr(type) ? type_pointer_get_ref(type) : type_array_get_element(type); + type_t *ref = is_ptr(type) ? type_pointer_get_ref_type(type) : type_array_get_element_type(type); if (is_ptr(ref)) { @@ -912,7 +842,7 @@ static short write_var_desc(struct sltg_typelib *typelib, struct sltg_data *data short href; while (type->typelib_idx < 0 && type_is_alias(type)) - type = type_alias_get_aliasee(type); + type = type_alias_get_aliasee_type(type); chat("write_var_desc: VT_USERDEFINED, type %p, name %s, real type %d, href %d\n", type, type->name, type_get_type(type), type->typelib_idx); @@ -959,6 +889,37 @@ static short write_var_desc(struct sltg_typelib *typelib, struct sltg_data *data return desc_offset; } +static void init_sltg_tail(struct sltg_tail *tail) +{ + tail->cFuncs = 0; + tail->cVars = 0; + tail->cImplTypes = 0; + tail->res06 = 0; + tail->funcs_off = -1; + tail->vars_off = -1; + tail->impls_off = -1; + tail->funcs_bytes = -1; + tail->vars_bytes = -1; + tail->impls_bytes = -1; + tail->tdescalias_vt = -1; + tail->res16 = -1; + tail->res18 = 0; + tail->res1a = 0; + tail->simple_alias = 0; + tail->res1e = 0; + tail->cbSizeInstance = 0; + tail->cbAlignment = 4; + tail->res24 = -1; + tail->res26 = -1; + tail->cbSizeVft = 0; + tail->res2a = -1; + tail->res2c = -1; + tail->res2e = -1; + tail->res30 = -1; + tail->res32 = 0; + tail->type_bytes = 0; +} + static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type) { struct sltg_data data, *var_data = NULL; @@ -974,7 +935,7 @@ static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type) chat("add_structure_typeinfo: type %p, type->name %s\n", type, type->name); - type->typelib_idx = typelib->n_file_blocks; + type->typelib_idx = typelib->block_count; hrefmap.href_count = 0; hrefmap.href = NULL; @@ -994,12 +955,12 @@ static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type) short base_offset; chat("add_structure_typeinfo: var %p (%s), type %p (%s)\n", - var, var->name, var->type, var->type->name); + var, var->name, var->declspec.type, var->declspec.type->name); init_sltg_data(&var_data[i]); base_offset = var_data_size + (i + 1) * sizeof(struct sltg_variable); - type_desc_offset[i] = write_var_desc(typelib, &var_data[i], var->type, 0, 0, + type_desc_offset[i] = write_var_desc(typelib, &var_data[i], var->declspec.type, 0, 0, base_offset, &size_instance, &hrefmap); dump_var_desc(var_data[i].data, var_data[i].size); @@ -1041,7 +1002,7 @@ static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type) next += sizeof(variable); variable.magic = 0x2a; /* always write flags to simplify calculations */ - variable.name = add_name(typelib, var->name); + variable.name = add_name(&typelib->name_table, var->name); variable.byte_offs = 0; if (var_data[i].size > sizeof(short)) { @@ -1070,7 +1031,6 @@ static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type) } init_sltg_tail(&tail); - tail.cVars = var_count; tail.vars_off = 0; tail.vars_bytes = var_data_size; @@ -1133,7 +1093,7 @@ static int get_func_flags(const var_t *func, int *dispid, int *invokekind, int * flags |= 0x10; /* FUNCFLAG_FDISPLAYBIND */ break; case ATTR_HELPCONTEXT: - *helpcontext = expr->u.lval; + *helpcontext = expr->u.integer.value; break; case ATTR_HELPSTRING: *helpstring = attr->u.pval; @@ -1216,12 +1176,7 @@ static int get_param_flags(const var_t *param) } if (out) - { - if (in) - flags |= 0x8000; - else - flags |= 0x4000; - } + flags |= in ? 0x8000 : 0x4000; else if (!in) flags |= 0xc000; @@ -1233,7 +1188,7 @@ static int add_func_desc(struct sltg_typelib *typelib, struct sltg_data *data, v int idx, int dispid, short base_offset, struct sltg_hrefmap *hrefmap) { struct sltg_data ret_data, *arg_data; - int arg_count = 0, arg_data_size, optional = 0, defaults = 0, old_size; + int arg_count = 0, arg_data_size, optional = 0, old_size; int funcflags = 0, invokekind = 1 /* INVOKE_FUNC */, helpcontext; const char *helpstring; const var_t *arg; @@ -1245,7 +1200,7 @@ static int add_func_desc(struct sltg_typelib *typelib, struct sltg_data *data, v old_size = data->size; init_sltg_data(&ret_data); - ret_desc_offset = write_var_desc(typelib, &ret_data, type_function_get_rettype(func->type), + ret_desc_offset = write_var_desc(typelib, &ret_data, type_function_get_rettype(func->declspec.type), 0, 0, base_offset, NULL, hrefmap); dump_var_desc(ret_data.data, ret_data.size); @@ -1258,35 +1213,36 @@ static int add_func_desc(struct sltg_typelib *typelib, struct sltg_data *data, v arg_offset += ret_data.size; } - if (type_get_function_args(func->type)) + if (type_function_get_args(func->declspec.type)) { int i = 0; - arg_count = list_count(type_get_function_args(func->type)); + arg_count = list_count(type_function_get_args(func->declspec.type)); arg_data = xmalloc(arg_count * sizeof(*arg_data)); arg_desc_offset = xmalloc(arg_count * sizeof(*arg_desc_offset)); arg_offset += arg_count * 2 * sizeof(short); - LIST_FOR_EACH_ENTRY(arg, type_get_function_args(func->type), const var_t, entry) + LIST_FOR_EACH_ENTRY(arg, type_function_get_args(func->declspec.type), const var_t, entry) { const attr_t *attr; short param_flags = get_param_flags(arg); chat("add_func_desc: arg[%d] %p (%s), type %p (%s)\n", - i, arg, arg->name, arg->type, arg->type->name); + i, arg, arg->name, arg->declspec.type, arg->declspec.type->name); init_sltg_data(&arg_data[i]); - arg_desc_offset[i] = write_var_desc(typelib, &arg_data[i], arg->type, param_flags, 0, + + arg_desc_offset[i] = write_var_desc(typelib, &arg_data[i], arg->declspec.type, param_flags, 0, arg_offset, NULL, hrefmap); dump_var_desc(arg_data[i].data, arg_data[i].size); if (arg_data[i].size > sizeof(short)) { arg_data_size += arg_data[i].size; - arg_offset += arg_data[i].size;; + arg_offset += arg_data[i].size; } i++; @@ -1295,9 +1251,7 @@ static int add_func_desc(struct sltg_typelib *typelib, struct sltg_data *data, v LIST_FOR_EACH_ENTRY(attr, arg->attrs, const attr_t, entry) { - if (attr->type == ATTR_DEFAULTVALUE) - defaults++; - else if(attr->type == ATTR_OPTIONAL) + if (attr->type == ATTR_OPTIONAL) optional++; } } @@ -1318,10 +1272,10 @@ static int add_func_desc(struct sltg_typelib *typelib, struct sltg_data *data, v } else func_desc.next = base_offset + sizeof(func_desc) + arg_data_size + arg_count * 2 * sizeof(short); - func_desc.name = base_offset != -1 ? add_name(typelib, func->name) : -1; + func_desc.name = base_offset != -1 ? add_name(&typelib->name_table, func->name) : -1; func_desc.dispid = dispid; func_desc.helpcontext = helpcontext; - func_desc.helpstring = (helpstring && base_offset != -1) ? add_name(typelib, helpstring) : -1; + func_desc.helpstring = (helpstring && base_offset != -1) ? add_name(&typelib->name_table, helpstring) : -1; func_desc.arg_off = arg_count ? base_offset + sizeof(func_desc) : -1; func_desc.nacc = (arg_count << 3) | 4 /* CC_STDCALL */; func_desc.retnextopt = (optional << 1); @@ -1356,11 +1310,11 @@ static int add_func_desc(struct sltg_typelib *typelib, struct sltg_data *data, v arg_offset += arg_count * 2 * sizeof(short); - LIST_FOR_EACH_ENTRY(arg, type_get_function_args(func->type), const var_t, entry) + LIST_FOR_EACH_ENTRY(arg, type_function_get_args(func->declspec.type), const var_t, entry) { short name, type_offset; - name = base_offset != -1 ? add_name(typelib, arg->name) : -1; + name = base_offset != -1 ? add_name(&typelib->name_table, arg->name) : -1; if (arg_data[i].size > sizeof(short)) { @@ -1476,7 +1430,7 @@ static void add_interface_typeinfo(struct sltg_typelib *typelib, type_t *iface) /* check typelib_idx again, it could have been added while resolving the parent interface */ if (iface->typelib_idx != -1) return; - iface->typelib_idx = typelib->n_file_blocks; + iface->typelib_idx = typelib->block_count; /* pass 1: calculate function descriptions data size */ init_sltg_data(&data); @@ -1617,11 +1571,15 @@ static void add_statement(struct sltg_typelib *typelib, const statement_t *stmt) case STMT_TYPEDEF: { - const type_list_t *type_entry = stmt->u.type_list; - for (; type_entry; type_entry = type_entry->next) + typeref_t *ref; + + if (!stmt->u.type_list) + break; + + LIST_FOR_EACH_ENTRY(ref, stmt->u.type_list, typeref_t, entry) { /* in old style typelibs all types are public */ - add_type_typeinfo(typelib, type_entry->type); + add_type_typeinfo(typelib, ref->type); } break; } @@ -1650,7 +1608,7 @@ static void sltg_write_header(struct sltg_typelib *sltg, int *library_block_star struct sltg_header { int magic; - short n_file_blocks; + short block_count; short res06; short size_of_index; short first_blk; @@ -1664,40 +1622,37 @@ static void sltg_write_header(struct sltg_typelib *sltg, int *library_block_star short index_string; short next; } entry; - struct sltg_block *block; int i; header.magic = 0x47544c53; - header.n_file_blocks = sltg->n_file_blocks + 1; + header.block_count = sltg->block_count + 1; /* 1-based */ header.res06 = 9; header.size_of_index = sltg->index.size; - header.first_blk = 1; + header.first_blk = 1; /* 1-based */ header.uuid = sltg_library_guid; header.res1c = 0x00000044; header.res20 = 0xffff0000; put_data(&header, sizeof(header)); - block = sltg->blocks; - for (i = 0; i < sltg->n_file_blocks - 1; i++) + /* library block is written separately */ + for (i = 0; i < sltg->block_count - 1; i++) { - assert(block->next != NULL); - - entry.length = block->length; - entry.index_string = block->index_string; - entry.next = header.first_blk + i + 1; + entry.length = sltg->blocks[i].length; + entry.index_string = sltg->blocks[i].index_string; + entry.next = header.first_blk + i + 1; /* point to next block */ chat("sltg_write_header: writing block entry %d: length %#x, index_string %#x, next %#x\n", i, entry.length, entry.index_string, entry.next); put_data(&entry, sizeof(entry)); - - block = block->next; } - assert(block->next == NULL); - /* library block length includes helpstrings and name table */ - entry.length = block->length + 0x40 + 2 + sltg->typeinfo_size + 4 + 6 + 12 + 0x200 + sltg->name_table.size + 12; - entry.index_string = block->index_string; + entry.length = sltg->blocks[sltg->block_count - 1].length + 0x40 /* pad after library block */ + + sizeof(sltg->typeinfo_count) + sltg->typeinfo_size + 4 /* library block size */ + 6 /* dummy help strings */ + + 12 /* name table header */ + 0x200 /* name table hash */ + + sizeof(sltg->name_table.size) + sltg->name_table.size + + 4 /* 0x01ffff01 */ + 4 /* 0 */; + entry.index_string = sltg->blocks[sltg->block_count - 1].index_string; entry.next = 0; chat("sltg_write_header: writing library block entry %d: length %#x, index_string %#x, next %#x\n", i, entry.length, entry.index_string, entry.next); @@ -1708,22 +1663,18 @@ static void sltg_write_header(struct sltg_typelib *sltg, int *library_block_star memset(pad, 0, 9); put_data(pad, 9); - block = sltg->blocks; - for (i = 0; i < sltg->n_file_blocks - 1; i++) + /* library block is written separately */ + for (i = 0; i < sltg->block_count - 1; i++) { - chat("sltg_write_header: writing block %d: %d bytes\n", i, block->length); - - put_data(block->data, block->length); - block = block->next; + chat("sltg_write_header: writing block %d: %d bytes\n", i, sltg->blocks[i].length); + put_data(sltg->blocks[i].data, sltg->blocks[i].length); } - assert(block->next == NULL); - /* library block */ - chat("library_block_start = %#lx\n", (SIZE_T)output_buffer_pos); + chat("library_block_start = %#x\n", (int)output_buffer_pos); *library_block_start = output_buffer_pos; - chat("sltg_write_header: writing library block %d: %d bytes\n", i, block->length); - put_data(block->data, block->length); + chat("sltg_write_header: writing library block %d: %d bytes\n", i, sltg->blocks[i].length); + put_data(sltg->blocks[sltg->block_count - 1].data, sltg->blocks[sltg->block_count - 1].length); chat("sltg_write_header: writing pad 0x40 bytes\n"); memset(pad, 0xff, 0x40); @@ -1732,21 +1683,15 @@ static void sltg_write_header(struct sltg_typelib *sltg, int *library_block_star static void sltg_write_typeinfo(struct sltg_typelib *typelib) { - int i; - struct sltg_block *block; - short count = typelib->typeinfo_count; + short i; - put_data(&count, sizeof(count)); + put_data(&typelib->typeinfo_count, sizeof(typelib->typeinfo_count)); - block = typelib->typeinfo; for (i = 0; i < typelib->typeinfo_count; i++) { - chat("sltg_write_typeinfo: writing block %d: %d bytes\n", i, block->length); - - put_data(block->data, block->length); - block = block->next; + chat("sltg_write_typeinfo: writing block %d: %d bytes\n", i, typelib->typeinfo[i].length); + put_data(typelib->typeinfo[i].data, typelib->typeinfo[i].length); } - assert(block == NULL); } static void sltg_write_helpstrings(struct sltg_typelib *typelib) @@ -1804,7 +1749,7 @@ static void save_all_changes(struct sltg_typelib *typelib) sltg_write_typeinfo(typelib); name_table_offset = (int *)(output_buffer + output_buffer_pos); - chat("name_table_offset = %#lx\n", (SIZE_T)output_buffer_pos); + chat("name_table_offset = %#x\n", (int)output_buffer_pos); put_data(&library_block_start, sizeof(library_block_start)); sltg_write_helpstrings(typelib); @@ -1821,9 +1766,10 @@ static void save_all_changes(struct sltg_typelib *typelib) expr_t *expr = get_attrp(typelib->typelib->attrs, ATTR_ID); if (expr) - sprintf(typelib_id, "#%d", expr->cval); + snprintf(typelib_id, sizeof(typelib_id), "#%d", expr->cval); add_output_to_resources("TYPELIB", typelib_id); - output_typelib_regscript(typelib->typelib); + if (strendswith(typelib_name, "_t.res")) /* add typelib registration */ + output_typelib_regscript(typelib->typelib); } else flush_output_buffer(typelib_name); } @@ -1835,16 +1781,21 @@ int create_sltg_typelib(typelib_t *typelib) void *library_block; int library_block_size, library_block_index; +#ifndef __REACTOS__ + if (pointer_size != 4) + error("Only 32-bit platform is supported\n"); +#endif + sltg.typelib = typelib; sltg.typeinfo_count = 0; sltg.typeinfo_size = 0; sltg.typeinfo = NULL; sltg.blocks = NULL; - sltg.n_file_blocks = 0; + sltg.block_count = 0; sltg.first_block = 1; init_index(&sltg.index); - init_name_table(&sltg); + init_name_table(&sltg.name_table); init_library(&sltg); library_block = create_library_block(&sltg, &library_block_size, &library_block_index); diff --git a/sdk/tools/wpp/CMakeLists.txt b/sdk/tools/wpp/CMakeLists.txt index 8722016491d..bda8cdb0cbf 100644 --- a/sdk/tools/wpp/CMakeLists.txt +++ b/sdk/tools/wpp/CMakeLists.txt @@ -20,7 +20,8 @@ if(MSVC) # Disable warnings add_compile_options( /wd4146 # "unary minus operator applied to unsigned type, result still unsigned" - /wd4244) # "'=': conversion from 'a' to 'b', possible loss of data" + /wd4244 # "'=': conversion from 'a' to 'b', possible loss of data" + /wd4090) # 'function': different 'const' qualifiers endif() @@ -35,12 +36,13 @@ if(CMAKE_CROSSCOMPILING) include_directories(${REACTOS_SOURCE_DIR}/sdk/include/wine) endif() +include_directories(${REACTOS_SOURCE_DIR}/sdk/tools/widl) + FLEX_TARGET(pp_scanner ppl.l ${CMAKE_CURRENT_BINARY_DIR}/ppl.yy.c) -BISON_TARGET(pp_parser ppy.y ${CMAKE_CURRENT_BINARY_DIR}/ppy.tab.c COMPILE_FLAGS "-p ppy_") +BISON_TARGET(pp_parser ppy.y ${CMAKE_CURRENT_BINARY_DIR}/ppy.tab.c) ADD_FLEX_BISON_DEPENDENCY(pp_scanner pp_parser) list(APPEND SOURCE - preproc.c wpp.c) if(CMAKE_CROSSCOMPILING) diff --git a/sdk/tools/wpp/ppl.l b/sdk/tools/wpp/ppl.l index 243049a47b2..b5ef1db8ce6 100644 --- a/sdk/tools/wpp/ppl.l +++ b/sdk/tools/wpp/ppl.l @@ -17,16 +17,6 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * - * History: - * 24-Apr-2000 BS - Started from scratch to restructure everything - * and reintegrate the source into the wine-tree. - * 04-Jan-2000 BS - Added comments about the lexicographical - * grammar to give some insight in the complexity. - * 28-Dec-1999 BS - Eliminated backing-up of the flexer by running - * `flex -b' on the source. This results in some - * weirdo extra rules, but a much faster scanner. - * 23-Dec-1999 BS - Started this file - * *------------------------------------------------------------------------- * The preprocessor's lexographical grammar (approximately): * @@ -123,7 +113,6 @@ %top{ #include "config.h" -#include "wine/port.h" } /* @@ -150,6 +139,7 @@ %x pp_macexp %x pp_if %x pp_ifd +%x pp_ifignored %x pp_endif %x pp_line %x pp_defined @@ -162,6 +152,7 @@ ul [uUlL]|[uUlL][lL]|[lL][uU]|[lL][lL][uU]|[uU][lL][lL]|[lL][uU][lL] %{ #include +#include #include #include #include @@ -170,18 +161,17 @@ ul [uUlL]|[uUlL][lL]|[lL][uU]|[lL][lL][uU]|[uU][lL][lL]|[lL][uU][lL] #include #ifndef LLONG_MAX -# define LLONG_MAX ((long long)0x7fffffff << 32 | 0xffffffff) +# define LLONG_MAX ((__int64)0x7fffffff << 32 | 0xffffffff) # define LLONG_MIN (-LLONG_MAX - 1) #endif #ifndef ULLONG_MAX -# define ULLONG_MAX ((long long)0xffffffff << 32 | 0xffffffff) +# define ULLONG_MAX ((__int64)0xffffffff << 32 | 0xffffffff) #endif -#ifndef HAVE_UNISTD_H #define YY_NO_UNISTD_H -#endif -#include "wine/wpp.h" +#include "../tools.h" +#include "utils.h" #include "wpp_private.h" #include "ppy.tab.h" @@ -209,7 +199,7 @@ ul [uUlL]|[uUlL][lL]|[lL][uU]|[lL][lL][uU]|[uU][lL][lL]|[lL][uU][lL] typedef struct bufferstackentry { YY_BUFFER_STATE bufferstate; /* Buffer to switch back to */ - void *filehandle; /* Handle to be used with wpp_callbacks->read */ + FILE *file; /* File handle */ pp_entry_t *define; /* Points to expanding define or NULL if handling includes */ int line_number; /* Line that we were handling */ int char_number; /* The current position on that line */ @@ -250,7 +240,7 @@ typedef struct macexpstackentry { * Prototypes */ static void newline(int); -static int make_number(int radix, YYSTYPE *val, const char *str, int len); +static int make_number(int radix, PPY_STYPE *val, const char *str, int len); static void put_buffer(const char *s, int len); /* Buffer management */ static void push_buffer(pp_entry_t *ppp, char *filename, char *incname, int pop); @@ -301,60 +291,13 @@ include_state_t pp_incl_state = 0 /* seen_junk */ }; -includelogicentry_t *pp_includelogiclist = NULL; +static struct list pp_includelogiclist = LIST_INIT( pp_includelogiclist ); #define YY_INPUT(buf,result,max_size) \ { \ - result = wpp_callbacks->read(pp_status.file, buf, max_size); \ + result = fread(buf, 1, max_size, pp_status.file); \ } -#define BUFFERINITIALCAPACITY 256 - -void pp_writestring(const char *format, ...) -{ - va_list valist; - int len; - static char *buffer; - static int buffercapacity; - char *new_buffer; - - if(buffercapacity == 0) - { - buffer = pp_xmalloc(BUFFERINITIALCAPACITY); - if(buffer == NULL) - return; - buffercapacity = BUFFERINITIALCAPACITY; - } - - va_start(valist, format); - len = vsnprintf(buffer, buffercapacity, - format, valist); - va_end(valist); - /* If the string is longer than buffersize, vsnprintf returns - * the string length with glibc >= 2.1, -1 with glibc < 2.1 */ - while(len > buffercapacity || len < 0) - { - do - { - buffercapacity *= 2; - } while(len > buffercapacity); - - new_buffer = pp_xrealloc(buffer, buffercapacity); - if(new_buffer == NULL) - { - va_end(valist); - return; - } - buffer = new_buffer; - va_start(valist, format); - len = vsnprintf(buffer, buffercapacity, - format, valist); - va_end(valist); - } - - wpp_callbacks->write(buffer, len); -} - %} /* @@ -390,7 +333,7 @@ void pp_writestring(const char *format, ...) {ws}*undef{ws}* if(yy_top_state() != pp_ignore) {yy_pp_state(pp_ifd); return tUNDEF;} else {yy_pp_state(pp_eol);} {ws}*ifdef{ws}* yy_pp_state(pp_ifd); return tIFDEF; {ws}*ifndef{ws}* pp_incl_state.seen_junk--; yy_pp_state(pp_ifd); return tIFNDEF; -{ws}*if{ws}* yy_pp_state(pp_if); return tIF; +{ws}*if{ws}* if(yy_top_state() != pp_ignore) {yy_pp_state(pp_if);} else {yy_pp_state(pp_ifignored);} return tIF; {ws}*elif{ws}* yy_pp_state(pp_if); return tELIF; {ws}*else{ws}* yy_pp_state(pp_endif); return tELSE; {ws}*endif{ws}* yy_pp_state(pp_endif); return tENDIF; @@ -450,11 +393,14 @@ void pp_writestring(const char *format, ...) \" ppy_error("String constants not allowed in conditionals"); . return *ppy_text; +[^\n]+ ppy_lval.sint = 0; return tSINT; +\n newline(1); yy_pop_state(); return tNL; + /* * Handle #ifdef, #ifndef and #undef * to get only an untranslated/unexpanded identifier */ -{cident} ppy_lval.cptr = pp_xstrdup(ppy_text); return tIDENT; +{cident} ppy_lval.cptr = xstrdup(ppy_text); return tIDENT; {ws}+ ; \n newline(1); yy_pop_state(); return tNL; \\\r?\n newline(0); @@ -473,7 +419,7 @@ void pp_writestring(const char *format, ...) * This is necessary to get the identifier prior to any * substitutions. */ -{cident} yy_pop_state(); ppy_lval.cptr = pp_xstrdup(ppy_text); return tIDENT; +{cident} yy_pop_state(); ppy_lval.cptr = xstrdup(ppy_text); return tIDENT; {ws}+ ; (\()|(\)) return *ppy_text; \\\r?\n newline(0); @@ -485,27 +431,27 @@ void pp_writestring(const char *format, ...) * will act appropriately. * Comments are stripped from the literal text. */ -[^/\\\n]+ if(yy_top_state() != pp_ignore) { ppy_lval.cptr = pp_xstrdup(ppy_text); return tLITERAL; } -\/[^/\\\n*]* if(yy_top_state() != pp_ignore) { ppy_lval.cptr = pp_xstrdup(ppy_text); return tLITERAL; } -(\\\r?)|(\/[^/*]) if(yy_top_state() != pp_ignore) { ppy_lval.cptr = pp_xstrdup(ppy_text); return tLITERAL; } +[^/\\\n]+ if(yy_top_state() != pp_ignore) { ppy_lval.cptr = xstrdup(ppy_text); return tLITERAL; } +\/[^/\\\n*]* if(yy_top_state() != pp_ignore) { ppy_lval.cptr = xstrdup(ppy_text); return tLITERAL; } +(\\\r?)|(\/[^/*]) if(yy_top_state() != pp_ignore) { ppy_lval.cptr = xstrdup(ppy_text); return tLITERAL; } \n newline(1); yy_pop_state(); if(yy_current_state() != pp_ignore) { return tNL; } \\\r?\n newline(0); /* * Handle left side of #define */ -{cident}\( ppy_lval.cptr = pp_xstrdup(ppy_text); if(ppy_lval.cptr) ppy_lval.cptr[ppy_leng-1] = '\0'; yy_pp_state(pp_macro); return tMACRO; -{cident} ppy_lval.cptr = pp_xstrdup(ppy_text); yy_pp_state(pp_define); return tDEFINE; +{cident}\( ppy_lval.cptr = xstrdup(ppy_text); ppy_lval.cptr[ppy_leng-1] = '\0'; yy_pp_state(pp_macro); return tMACRO; +{cident} ppy_lval.cptr = xstrdup(ppy_text); yy_pp_state(pp_define); return tDEFINE; {ws}+ ; \\\r?\n newline(0); -(\\\r?)|(\n)|(.) perror("Identifier expected"); +(\\\r?)|(\n)|(.) ppy_error("Identifier expected"); /* * Scan the substitution of a define */ -[^'"/\\\n]+ ppy_lval.cptr = pp_xstrdup(ppy_text); return tLITERAL; -(\\\r?)|(\/[^/*]) ppy_lval.cptr = pp_xstrdup(ppy_text); return tLITERAL; -\\\r?\n{ws}+ newline(0); ppy_lval.cptr = pp_xstrdup(" "); return tLITERAL; +[^'"/\\\n]+ ppy_lval.cptr = xstrdup(ppy_text); return tLITERAL; +(\\\r?)|(\/[^/*]) ppy_lval.cptr = xstrdup(ppy_text); return tLITERAL; +\\\r?\n{ws}+ newline(0); ppy_lval.cptr = xstrdup(" "); return tLITERAL; \\\r?\n newline(0); \n newline(1); yy_pop_state(); return tNL; \' new_string(); add_string(ppy_text, ppy_leng); yy_push_state(pp_sqs); @@ -516,22 +462,22 @@ void pp_writestring(const char *format, ...) */ \){ws}* yy_pp_state(pp_mbody); return tMACROEND; {ws}+ ; -{cident} ppy_lval.cptr = pp_xstrdup(ppy_text); return tIDENT; +{cident} ppy_lval.cptr = xstrdup(ppy_text); return tIDENT; , return ','; -"..." return tELIPSIS; +"..." return tELLIPSIS; (\\\r?)|(\n)|(.)|(\.\.?) ppy_error("Argument identifier expected"); \\\r?\n newline(0); /* * Scan the substitution of a macro */ -[^a-zA-Z0-9'"#/\\\n]+ ppy_lval.cptr = pp_xstrdup(ppy_text); return tLITERAL; -{cident} ppy_lval.cptr = pp_xstrdup(ppy_text); return tIDENT; +[^a-zA-Z0-9'"#/\\\n]+ ppy_lval.cptr = xstrdup(ppy_text); return tLITERAL; +{cident} ppy_lval.cptr = xstrdup(ppy_text); return tIDENT; \#\# return tCONCAT; \# return tSTRINGIZE; -[0-9][a-zA-Z0-9]*[^a-zA-Z0-9'"#/\\\n]* ppy_lval.cptr = pp_xstrdup(ppy_text); return tLITERAL; -(\\\r?)|(\/[^/*'"#\\\n]*) ppy_lval.cptr = pp_xstrdup(ppy_text); return tLITERAL; -\\\r?\n{ws}+ newline(0); ppy_lval.cptr = pp_xstrdup(" "); return tLITERAL; +[0-9][a-zA-Z0-9]*[^a-zA-Z0-9'"#/\\\n]* ppy_lval.cptr = xstrdup(ppy_text); return tLITERAL; +(\\\r?)|(\/[^/*'"#\\\n]*) ppy_lval.cptr = xstrdup(ppy_text); return tLITERAL; +\\\r?\n{ws}+ newline(0); ppy_lval.cptr = xstrdup(" "); return tLITERAL; \\\r?\n newline(0); \n newline(1); yy_pop_state(); return tNL; \' new_string(); add_string(ppy_text, ppy_leng); yy_push_state(pp_sqs); @@ -698,7 +644,7 @@ void pp_writestring(const char *format, ...) else if(yy_current_state() == pp_if) { - ppy_lval.cptr = pp_xstrdup(ppy_text); + ppy_lval.cptr = xstrdup(ppy_text); return tIDENT; } else { @@ -724,7 +670,7 @@ void pp_writestring(const char *format, ...) push_macro(ppp); break; default: - pp_internal_error(__FILE__, __LINE__, "Invalid define type %d\n", ppp->type); + assert(0); } } else put_buffer(ppy_text, ppy_leng); @@ -747,8 +693,8 @@ void pp_writestring(const char *format, ...) (\n)|(.)|(\\\r?(\n|.)) put_buffer(ppy_text, ppy_leng); [A-Za-z0-9_\.\\/]+ { - ppy_lval.cptr=pp_xstrdup(ppy_text); - yy_pop_state(); + ppy_lval.cptr = xstrdup(ppy_text); + yy_pop_state(); return tRCINCLUDEPATH; } @@ -847,14 +793,10 @@ static void newline(int dowrite) * * FIXME: * The sizes of resulting 'int' and 'long' are compiler specific. - * I depend on sizeof(int) > 2 here (although a relatively safe - * assumption). - * Long longs are not yet implemented because this is very compiler - * specific and I don't want to think too much about the problems. * *------------------------------------------------------------------------- */ -static int make_number(int radix, YYSTYPE *val, const char *str, int len) +static int make_number(int radix, PPY_STYPE *val, const char *str, int len) { int is_l = 0; int is_ll = 0; @@ -895,29 +837,21 @@ static int make_number(int radix, YYSTYPE *val, const char *str, int len) is_u++; } - if(is_ll) + if(is_u && is_ll) { -/* Assume as in the declaration of wrc_ull_t and wrc_sll_t */ -#ifdef HAVE_LONG_LONG - if (is_u) - { - errno = 0; - val->ull = strtoull(str, NULL, radix); - if (val->ull == ULLONG_MAX && errno == ERANGE) - ppy_error("integer constant %s is too large\n", str); - return tULONGLONG; - } - else - { - errno = 0; - val->sll = strtoll(str, NULL, radix); - if ((val->sll == LLONG_MIN || val->sll == LLONG_MAX) && errno == ERANGE) - ppy_error("integer constant %s is too large\n", str); - return tSLONGLONG; - } -#else - pp_internal_error(__FILE__, __LINE__, "long long constants not supported on this platform"); -#endif + errno = 0; + val->ull = strtoull(str, NULL, radix); + if (val->ull == ULLONG_MAX && errno == ERANGE) + ppy_error("integer constant %s is too large\n", str); + return tULONGLONG; + } + else if(!is_u && is_ll) + { + errno = 0; + val->sll = strtoll(str, NULL, radix); + if ((val->sll == LLONG_MIN || val->sll == LLONG_MAX) && errno == ERANGE) + ppy_error("integer constant %s is too large\n", str); + return tSLONGLONG; } else if(is_u && is_l) { @@ -967,28 +901,19 @@ static int make_number(int radix, YYSTYPE *val, const char *str, int len) static void expand_special(pp_entry_t *ppp) { static char *buf = NULL; - char *new_buf; assert(ppp->type == def_special); if(!strcmp(ppp->ident, "__LINE__")) { - new_buf = pp_xrealloc(buf, 32); - if(!new_buf) - return; - buf = new_buf; - sprintf(buf, "%d", pp_status.line_number); + buf = xrealloc(buf, 32); + snprintf(buf, 32, "%d", pp_status.line_number); } else if(!strcmp(ppp->ident, "__FILE__")) { - new_buf = pp_xrealloc(buf, strlen(pp_status.input) + 3); - if(!new_buf) - return; - buf = new_buf; - sprintf(buf, "\"%s\"", pp_status.input); + buf = xrealloc(buf, strlen(pp_status.input) + 3); + snprintf(buf, strlen(pp_status.input) + 3, "\"%s\"", pp_status.input); } - else - pp_internal_error(__FILE__, __LINE__, "Special macro '%s' not found...\n", ppp->ident); if(pp_flex_debug) fprintf(stderr, "expand_special(%d): %s:%d: '%s' -> '%s'\n", @@ -1029,21 +954,12 @@ static char *curdef_text = NULL; static void add_text(const char *str, int len) { - int new_alloc; - char *new_text; - if(len == 0) return; if(curdef_idx >= curdef_alloc || curdef_alloc - curdef_idx < len) { - new_alloc = curdef_alloc + ((len + ALLOCBLOCKSIZE-1) & ~(ALLOCBLOCKSIZE-1)); - new_text = pp_xrealloc(curdef_text, new_alloc * sizeof(curdef_text[0])); - if(!new_text) - return; - curdef_text = new_text; - curdef_alloc = new_alloc; - if(curdef_alloc > 65536) - ppy_warning("Reallocating macro-expansion buffer larger than 64kB"); + curdef_alloc += (len + ALLOCBLOCKSIZE-1) & ~(ALLOCBLOCKSIZE-1); + curdef_text = xrealloc(curdef_text, curdef_alloc * sizeof(curdef_text[0])); } memcpy(&curdef_text[curdef_idx], str, len); curdef_idx += len; @@ -1139,9 +1055,6 @@ static mtext_t *add_expand_text(mtext_t *mtp, macexpstackentry_t *mep, int *nnl) if(pp_flex_debug) fprintf(stderr, "add_expand_text: exp_subst(%d): '%s'\n", mtp->subst.argidx, exp); break; - - default: - pp_internal_error(__FILE__, __LINE__, "Invalid expansion type (%d) in macro expansion\n", mtp->type); } return mtp; } @@ -1158,9 +1071,9 @@ static void expand_macro(macexpstackentry_t *mep) assert(ppp->type == def_macro); assert(ppp->expanding == 0); - if((ppp->nargs >= 0 && nargs != ppp->nargs) || (ppp->nargs < 0 && nargs < -ppp->nargs)) + if((!ppp->variadic && nargs != ppp->nargs) || (ppp->variadic && nargs < ppp->nargs)) { - ppy_error("Too %s macro arguments (%d)", nargs < abs(ppp->nargs) ? "few" : "many", nargs); + ppy_error("Too %s macro arguments (%d)", nargs < ppp->nargs ? "few" : "many", nargs); return; } @@ -1229,31 +1142,18 @@ static void expand_macro(macexpstackentry_t *mep) */ static void new_string(void) { -#ifdef DEBUG - if(strbuf_idx) - ppy_warning("new_string: strbuf_idx != 0"); -#endif strbuf_idx = 0; str_startline = pp_status.line_number; } static void add_string(const char *str, int len) { - int new_alloc; - char *new_buffer; - if(len == 0) return; if(strbuf_idx >= strbuf_alloc || strbuf_alloc - strbuf_idx < len) { - new_alloc = strbuf_alloc + ((len + ALLOCBLOCKSIZE-1) & ~(ALLOCBLOCKSIZE-1)); - new_buffer = pp_xrealloc(strbuffer, new_alloc * sizeof(strbuffer[0])); - if(!new_buffer) - return; - strbuffer = new_buffer; - strbuf_alloc = new_alloc; - if(strbuf_alloc > 65536) - ppy_warning("Reallocating string buffer larger than 64kB"); + strbuf_alloc += (len + ALLOCBLOCKSIZE-1) & ~(ALLOCBLOCKSIZE-1); + strbuffer = xrealloc(strbuffer, strbuf_alloc * sizeof(strbuffer[0])); } memcpy(&strbuffer[strbuf_idx], str, len); strbuf_idx += len; @@ -1261,23 +1161,16 @@ static void add_string(const char *str, int len) static char *get_string(void) { - char *str = pp_xmalloc(strbuf_idx + 1); - if(!str) - return NULL; + char *str = xmalloc(strbuf_idx + 1); + memcpy(str, strbuffer, strbuf_idx); str[strbuf_idx] = '\0'; -#ifdef DEBUG - strbuf_idx = 0; -#endif return str; } static void put_string(void) { put_buffer(strbuffer, strbuf_idx); -#ifdef DEBUG - strbuf_idx = 0; -#endif } static int string_start(void) @@ -1296,11 +1189,11 @@ static void push_buffer(pp_entry_t *ppp, char *filename, char *incname, int pop) if(ppy_debug) printf("push_buffer(%d): %p %p %p %d\n", bufferstackidx, ppp, filename, incname, pop); if(bufferstackidx >= MAXBUFFERSTACK) - pp_internal_error(__FILE__, __LINE__, "Buffer stack overflow"); + error("Buffer stack overflow\n"); memset(&bufferstack[bufferstackidx], 0, sizeof(bufferstack[0])); bufferstack[bufferstackidx].bufferstate = YY_CURRENT_BUFFER; - bufferstack[bufferstackidx].filehandle = pp_status.file; + bufferstack[bufferstackidx].file = pp_status.file; bufferstack[bufferstackidx].define = ppp; bufferstack[bufferstackidx].line_number = pp_status.line_number; bufferstack[bufferstackidx].char_number = pp_status.char_number; @@ -1321,16 +1214,11 @@ static void push_buffer(pp_entry_t *ppp, char *filename, char *incname, int pop) pp_status.input = filename; ncontinuations = 0; } - else if(!pop) - pp_internal_error(__FILE__, __LINE__, "Pushing buffer without knowing where to go to"); bufferstackidx++; } static bufferstackentry_t *pop_buffer(void) { - if(bufferstackidx < 0) - pp_internal_error(__FILE__, __LINE__, "Bufferstack underflow?"); - if(bufferstackidx == 0) return NULL; @@ -1344,8 +1232,8 @@ static bufferstackentry_t *pop_buffer(void) if(!bufferstack[bufferstackidx].should_pop) { - wpp_callbacks->close(pp_status.file); - pp_writestring("# %d \"%s\" 2\n", bufferstack[bufferstackidx].line_number, bufferstack[bufferstackidx].filename); + fclose(pp_status.file); + fprintf(ppy_out, "# %d \"%s\" 2\n", bufferstack[bufferstackidx].line_number, bufferstack[bufferstackidx].filename); /* We have EOF, check the include logic */ if(pp_incl_state.state == 2 && !pp_incl_state.seen_junk && pp_incl_state.ppp) @@ -1353,21 +1241,14 @@ static bufferstackentry_t *pop_buffer(void) pp_entry_t *ppp = pplookup(pp_incl_state.ppp); if(ppp) { - iep = pp_xmalloc(sizeof(includelogicentry_t)); - if (iep) - { - iep->ppp = ppp; - ppp->iep = iep; - iep->filename = bufferstack[bufferstackidx].include_filename; - iep->prev = NULL; - iep->next = pp_includelogiclist; - if(iep->next) - iep->next->prev = iep; - pp_includelogiclist = iep; - if(pp_status.debug) - fprintf(stderr, "pop_buffer: %s:%d: includelogic added, include_ppp='%s', file='%s'\n", - bufferstack[bufferstackidx].filename, bufferstack[bufferstackidx].line_number, pp_incl_state.ppp, iep->filename); - } + iep = xmalloc(sizeof(includelogicentry_t)); + iep->ppp = ppp; + ppp->iep = iep; + iep->filename = bufferstack[bufferstackidx].include_filename; + list_add_head( &pp_includelogiclist, &iep->entry ); + if(pp_status.debug) + fprintf(stderr, "pop_buffer: %s:%d: includelogic added, include_ppp='%s', file='%s'\n", + bufferstack[bufferstackidx].filename, bufferstack[bufferstackidx].line_number, pp_incl_state.ppp, iep->filename); } } free(pp_incl_state.ppp); @@ -1397,15 +1278,13 @@ static bufferstackentry_t *pop_buffer(void) bufferstack[bufferstackidx].filename, bufferstack[bufferstackidx].should_pop); - pp_status.file = bufferstack[bufferstackidx].filehandle; + pp_status.file = bufferstack[bufferstackidx].file; ppy__switch_to_buffer(bufferstack[bufferstackidx].bufferstate); if(bufferstack[bufferstackidx].should_pop) { - if(yy_current_state() == pp_macexp) - macro_add_expansion(); - else - pp_internal_error(__FILE__, __LINE__, "Pop buffer and state without macro expansion state"); + assert( yy_current_state() == pp_macexp ); + macro_add_expansion(); yy_pop_state(); } @@ -1426,9 +1305,7 @@ static void push_macro(pp_entry_t *ppp) return; } - macexpstack[macexpstackidx] = pp_xmalloc(sizeof(macexpstack[0][0])); - if(!macexpstack[macexpstackidx]) - return; + macexpstack[macexpstackidx] = xmalloc(sizeof(macexpstack[0][0])); memset( macexpstack[macexpstackidx], 0, sizeof(macexpstack[0][0])); macexpstack[macexpstackidx]->ppp = ppp; macexpstackidx++; @@ -1441,8 +1318,7 @@ static macexpstackentry_t *top_macro(void) static macexpstackentry_t *pop_macro(void) { - if(macexpstackidx <= 0) - pp_internal_error(__FILE__, __LINE__, "Macro expansion stack underflow\n"); + assert(macexpstackidx > 0); return macexpstack[--macexpstackidx]; } @@ -1466,13 +1342,8 @@ static void add_text_to_macro(const char *text, int len) if(mep->curargalloc - mep->curargsize <= len+1) /* +1 for '\0' */ { - char *new_curarg; - int new_alloc = mep->curargalloc + ((ALLOCBLOCKSIZE > len+1) ? ALLOCBLOCKSIZE : len+1); - new_curarg = pp_xrealloc(mep->curarg, new_alloc * sizeof(mep->curarg[0])); - if(!new_curarg) - return; - mep->curarg = new_curarg; - mep->curargalloc = new_alloc; + mep->curargalloc += (ALLOCBLOCKSIZE > len+1) ? ALLOCBLOCKSIZE : len+1; + mep->curarg = xrealloc(mep->curarg, mep->curargalloc * sizeof(mep->curarg[0])); } memcpy(mep->curarg + mep->curargsize, text, len); mep->curargsize += len; @@ -1483,30 +1354,15 @@ static void macro_add_arg(int last) { int nnl = 0; char *cptr; - char **new_args, **new_ppargs; - int *new_nnls; macexpstackentry_t *mep = top_macro(); assert(mep->ppp->expanding == 0); - new_args = pp_xrealloc(mep->args, (mep->nargs+1) * sizeof(mep->args[0])); - if(!new_args) - return; - mep->args = new_args; + mep->args = xrealloc(mep->args, (mep->nargs+1) * sizeof(mep->args[0])); + mep->ppargs = xrealloc(mep->ppargs, (mep->nargs+1) * sizeof(mep->ppargs[0])); + mep->nnls = xrealloc(mep->nnls, (mep->nargs+1) * sizeof(mep->nnls[0])); - new_ppargs = pp_xrealloc(mep->ppargs, (mep->nargs+1) * sizeof(mep->ppargs[0])); - if(!new_ppargs) - return; - mep->ppargs = new_ppargs; - - new_nnls = pp_xrealloc(mep->nnls, (mep->nargs+1) * sizeof(mep->nnls[0])); - if(!new_nnls) - return; - mep->nnls = new_nnls; - - mep->args[mep->nargs] = pp_xstrdup(mep->curarg ? mep->curarg : ""); - if(!mep->args[mep->nargs]) - return; + mep->args[mep->nargs] = xstrdup(mep->curarg ? mep->curarg : ""); cptr = mep->args[mep->nargs]-1; while((cptr = strchr(cptr+1, '\n'))) { @@ -1541,7 +1397,7 @@ static void macro_add_expansion(void) assert(mep->ppp->expanding == 0); - mep->ppargs[mep->nargs-1] = pp_xstrdup(mep->curarg ? mep->curarg : ""); + mep->ppargs[mep->nargs-1] = xstrdup(mep->curarg ? mep->curarg : ""); free(mep->curarg); mep->curargalloc = mep->curargsize = 0; mep->curarg = NULL; @@ -1565,7 +1421,7 @@ static void put_buffer(const char *s, int len) if(top_macro()) add_text_to_macro(s, len); else - wpp_callbacks->write(s, len); + fwrite(s, 1, len, ppy_out); } @@ -1584,7 +1440,7 @@ void pp_do_include(char *fname, int type) if(!fname) return; - for(iep = pp_includelogiclist; iep; iep = iep->next) + LIST_FOR_EACH_ENTRY( iep, &pp_includelogiclist, includelogicentry_t, entry ) { if(!strcmp(iep->filename, fname)) { @@ -1624,12 +1480,12 @@ void pp_do_include(char *fname, int type) pp_incl_state.ppp = NULL; if(pp_status.debug) - fprintf(stderr, "pp_do_include: %s:%d: include_state=%d, include_ppp='%s', include_ifdepth=%d\n", - pp_status.input, pp_status.line_number, pp_incl_state.state, pp_incl_state.ppp, pp_incl_state.ifdepth); + fprintf(stderr, "pp_do_include: %s:%d: include_state=%d, include_ifdepth=%d\n", + pp_status.input, pp_status.line_number, pp_incl_state.state, pp_incl_state.ifdepth); pp_status.file = fp; ppy__switch_to_buffer(ppy__create_buffer(NULL, YY_BUF_SIZE)); - pp_writestring("# 1 \"%s\" 1%s\n", newpath, type ? "" : " 3"); + fprintf(ppy_out, "# 1 \"%s\" 1%s\n", newpath, type ? "" : " 3"); } /* diff --git a/sdk/tools/wpp/ppy.y b/sdk/tools/wpp/ppy.y index dbbe9722df8..ce3c409e735 100644 --- a/sdk/tools/wpp/ppy.y +++ b/sdk/tools/wpp/ppy.y @@ -3,7 +3,6 @@ * * Copyright 1999-2000 Bertho A. Stultiens (BS) * - * * 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 @@ -18,18 +17,10 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * - * History: - * 24-Apr-2000 BS Restructured the lot to fit the new scanner - * and reintegrate into the wine-tree. - * 01-Jan-2000 BS FIXME: win16 preprocessor calculates with - * 16 bit ints and overflows...? - * 26-Dec-1999 BS Started this file - * */ %{ #include "config.h" -#include "wine/port.h" #include #include @@ -38,6 +29,8 @@ #include #include +#include "../tools.h" +#include "utils.h" #include "wpp_private.h" @@ -81,9 +74,9 @@ if(cv_signed(v1) && cv_signed(v2)) \ r.val.sll = v1.val.sll OP v2.val.sll; \ else if(cv_signed(v1) && !cv_signed(v2)) \ - r.val.sll = v1.val.sll OP (wrc_sll_t) v2.val.ull; \ + r.val.sll = v1.val.sll OP (__int64) v2.val.ull; \ else if(!cv_signed(v1) && cv_signed(v2)) \ - r.val.sll = (wrc_sll_t) v1.val.ull OP v2.val.sll; \ + r.val.sll = (__int64) v1.val.ull OP v2.val.sll; \ else \ r.val.ull = v1.val.ull OP v2.val.ull; @@ -93,7 +86,7 @@ case SIZE_INT: BIN_OP_INT(r, v1, v2, OP); break; \ case SIZE_LONG: BIN_OP_LONG(r, v1, v2, OP); break; \ case SIZE_LONGLONG: BIN_OP_LONGLONG(r, v1, v2, OP); break; \ - default: pp_internal_error(__FILE__, __LINE__, "Invalid type indicator (0x%04x)", v1.type); \ + default: assert(0); \ } @@ -108,8 +101,7 @@ static void cast_to_slong(cval_t *v); static void cast_to_ulong(cval_t *v); static void cast_to_sll(cval_t *v); static void cast_to_ull(cval_t *v); -static marg_t *new_marg(char *str, def_arg_t type); -static marg_t *add_new_marg(char *str, def_arg_t type); +static char *add_new_marg(char *str); static int marg_index(char *id); static mtext_t *new_mtext(char *str, int idx, def_exp_t type); static mtext_t *combine_mtext(mtext_t *tail, mtext_t *mtp); @@ -118,29 +110,32 @@ static char *merge_text(char *s1, char *s2); /* * Local variables */ -static marg_t **macro_args; /* Macro parameters array while parsing */ +static char **macro_args; /* Macro parameters array while parsing */ static int nmacro_args; +static int macro_variadic; /* Macro arguments end with (or consist entirely of) '...' */ %} +%define api.prefix {ppy_} + %union{ int sint; unsigned int uint; long slong; unsigned long ulong; - wrc_sll_t sll; - wrc_ull_t ull; + __int64 sll; + unsigned __int64 ull; int *iptr; char *cptr; cval_t cval; - marg_t *marg; + char *marg; mtext_t *mtext; } %token tRCINCLUDE %token tIF tIFDEF tIFNDEF tELSE tELIF tENDIF tDEFINED tNL %token tINCLUDE tLINE tGCCLINE tERROR tWARNING tPRAGMA tPPIDENT -%token tUNDEF tMACROEND tCONCAT tELIPSIS tSTRINGIZE +%token tUNDEF tMACROEND tCONCAT tELLIPSIS tSTRINGIZE %token tIDENT tLITERAL tMACRO tDEFINE %token tDQSTRING tSQSTRING tIQSTRING %token tUINT @@ -227,8 +222,6 @@ preprocessor break; case if_error: break; - default: - pp_internal_error(__FILE__, __LINE__, "Invalid pp_if_state (%d) in #elif directive", s); } } | tELSE tNL { @@ -253,8 +246,6 @@ preprocessor break; case if_error: break; - default: - pp_internal_error(__FILE__, __LINE__, "Invalid pp_if_state (%d) in #else directive", s); } } | tENDIF tNL { @@ -277,35 +268,25 @@ preprocessor | tUNDEF tIDENT tNL { pp_del_define($2); free($2); } | tDEFINE opt_text tNL { pp_add_define($1, $2); free($1); free($2); } | tMACRO res_arg allmargs tMACROEND opt_mtexts tNL { - pp_add_macro($1, macro_args, nmacro_args, $5); + pp_add_macro($1, macro_args, nmacro_args, macro_variadic, $5); } - | tLINE tSINT tDQSTRING tNL { if($3) pp_writestring("# %d %s\n", $2 , $3); free($3); } - | tGCCLINE tSINT tDQSTRING tNL { if($3) pp_writestring("# %d %s\n", $2 , $3); free($3); } + | tLINE tSINT tDQSTRING tNL { if($3) fprintf(ppy_out, "# %d %s\n", $2 , $3); free($3); } + | tGCCLINE tSINT tDQSTRING tNL { if($3) fprintf(ppy_out, "# %d %s\n", $2 , $3); free($3); } | tGCCLINE tSINT tDQSTRING tSINT tNL - { if($3) pp_writestring("# %d %s %d\n", $2, $3, $4); free($3); } + { if($3) fprintf(ppy_out, "# %d %s %d\n", $2, $3, $4); free($3); } | tGCCLINE tSINT tDQSTRING tSINT tSINT tNL - { if($3) pp_writestring("# %d %s %d %d\n", $2 ,$3, $4, $5); free($3); } + { if($3) fprintf(ppy_out, "# %d %s %d %d\n", $2 ,$3, $4, $5); free($3); } | tGCCLINE tSINT tDQSTRING tSINT tSINT tSINT tNL - { if($3) pp_writestring("# %d %s %d %d %d\n", $2 ,$3 ,$4 ,$5, $6); free($3); } + { if($3) fprintf(ppy_out, "# %d %s %d %d %d\n", $2 ,$3 ,$4 ,$5, $6); free($3); } | tGCCLINE tSINT tDQSTRING tSINT tSINT tSINT tSINT tNL - { if($3) pp_writestring("# %d %s %d %d %d %d\n", $2 ,$3 ,$4 ,$5, $6, $7); free($3); } + { if($3) fprintf(ppy_out, "# %d %s %d %d %d %d\n", $2 ,$3 ,$4 ,$5, $6, $7); free($3); } | tGCCLINE tNL /* The null-token */ | tERROR opt_text tNL { ppy_error("#error directive: '%s'", $2); free($2); } | tWARNING opt_text tNL { ppy_warning("#warning directive: '%s'", $2); free($2); } - | tPRAGMA opt_text tNL { pp_writestring("#pragma %s\n", $2 ? $2 : ""); free($2); } - | tPPIDENT opt_text tNL { if(pp_status.pedantic) ppy_warning("#ident ignored (arg: '%s')", $2); free($2); } + | tPRAGMA opt_text tNL { fprintf(ppy_out, "#pragma %s\n", $2 ? $2 : ""); free($2); } + | tPPIDENT opt_text tNL { if(pedantic) ppy_warning("#ident ignored (arg: '%s')", $2); free($2); } | tRCINCLUDE tRCINCLUDEPATH { - if($2) - { - int nl=strlen($2) +3; - char *fn=pp_xmalloc(nl); - if(fn) - { - sprintf(fn,"\"%s\"",$2); - pp_do_include(fn,1); - } - free($2); - } + pp_do_include(strmake( "\"%s\"", $2 ),1); } | tRCINCLUDE tDQSTRING { pp_do_include($2,1); @@ -325,19 +306,20 @@ text : tLITERAL { $$ = $1; } | text tSQSTRING { $$ = merge_text($1, $2); } ; -res_arg : /* Empty */ { macro_args = NULL; nmacro_args = 0; } +res_arg : /* Empty */ { macro_args = NULL; nmacro_args = 0; macro_variadic = 0; } ; -allmargs: /* Empty */ { $$ = 0; macro_args = NULL; nmacro_args = 0; } +allmargs: /* Empty */ { $$ = 0; macro_args = NULL; nmacro_args = 0; macro_variadic = 0; } | emargs { $$ = nmacro_args; } ; emargs : margs { $$ = $1; } - | margs ',' tELIPSIS { $$ = add_new_marg(NULL, arg_list); nmacro_args *= -1; } + | margs ',' tELLIPSIS { macro_variadic = 1; } + | tELLIPSIS { macro_args = NULL; nmacro_args = 0; macro_variadic = 1; } ; -margs : margs ',' tIDENT { $$ = add_new_marg($3, arg_single); } - | tIDENT { $$ = add_new_marg($1, arg_single); } +margs : margs ',' tIDENT { $$ = add_new_marg($3); } + | tIDENT { $$ = add_new_marg($1); } ; opt_mtexts @@ -539,42 +521,21 @@ static int boolean(cval_t *v) { switch(v->type) { - case cv_sint: return v->val.si != (int)0; - case cv_uint: return v->val.ui != (unsigned int)0; - case cv_slong: return v->val.sl != (long)0; - case cv_ulong: return v->val.ul != (unsigned long)0; - case cv_sll: return v->val.sll != (wrc_sll_t)0; - case cv_ull: return v->val.ull != (wrc_ull_t)0; + case cv_sint: return v->val.si != 0; + case cv_uint: return v->val.ui != 0; + case cv_slong: return v->val.sl != 0; + case cv_ulong: return v->val.ul != 0; + case cv_sll: return v->val.sll != 0; + case cv_ull: return v->val.ull != 0; } return 0; } -static marg_t *new_marg(char *str, def_arg_t type) +static char *add_new_marg(char *str) { - marg_t *ma = pp_xmalloc(sizeof(marg_t)); - if(!ma) - return NULL; - ma->arg = str; - ma->type = type; - ma->nnl = 0; - return ma; -} - -static marg_t *add_new_marg(char *str, def_arg_t type) -{ - marg_t **new_macro_args; - marg_t *ma; - if(!str) - return NULL; - new_macro_args = pp_xrealloc(macro_args, (nmacro_args+1) * sizeof(macro_args[0])); - if(!new_macro_args) - return NULL; - macro_args = new_macro_args; - ma = new_marg(str, type); - if(!ma) - return NULL; - macro_args[nmacro_args] = ma; - nmacro_args++; + char *ma; + macro_args = xrealloc(macro_args, (nmacro_args+1) * sizeof(macro_args[0])); + macro_args[nmacro_args++] = ma = xstrdup(str); return ma; } @@ -585,7 +546,7 @@ static int marg_index(char *id) return -1; for(t = 0; t < nmacro_args; t++) { - if(!strcmp(id, macro_args[t]->arg)) + if(!strcmp(id, macro_args[t])) break; } return t < nmacro_args ? t : -1; @@ -593,9 +554,8 @@ static int marg_index(char *id) static mtext_t *new_mtext(char *str, int idx, def_exp_t type) { - mtext_t *mt = pp_xmalloc(sizeof(mtext_t)); - if(!mt) - return NULL; + mtext_t *mt = xmalloc(sizeof(mtext_t)); + if(str == NULL) mt->subst.argidx = idx; else @@ -615,11 +575,7 @@ static mtext_t *combine_mtext(mtext_t *tail, mtext_t *mtp) if(tail->type == exp_text && mtp->type == exp_text) { - char *new_text; - new_text = pp_xrealloc(tail->subst.text, strlen(tail->subst.text)+strlen(mtp->subst.text)+1); - if(!new_text) - return mtp; - tail->subst.text = new_text; + tail->subst.text = xrealloc(tail->subst.text, strlen(tail->subst.text)+strlen(mtp->subst.text)+1); strcat(tail->subst.text, mtp->subst.text); free(mtp->subst.text); free(mtp); @@ -683,22 +639,9 @@ static mtext_t *combine_mtext(mtext_t *tail, mtext_t *mtp) static char *merge_text(char *s1, char *s2) { - int l1; - int l2; - char *snew; - if(!s1) - return s2; - if(!s2) - return s1; - l1 = strlen(s1); - l2 = strlen(s2); - snew = pp_xrealloc(s1, l1+l2+1); - if(!snew) - { - free(s2); - return s1; - } - s1 = snew; + int l1 = strlen(s1); + int l2 = strlen(s2); + s1 = xrealloc(s1, l1+l2+1); memcpy(s1+l1, s2, l2+1); free(s2); return s1; diff --git a/sdk/tools/wpp/preproc.c b/sdk/tools/wpp/preproc.c deleted file mode 100644 index 21830d65fb2..00000000000 --- a/sdk/tools/wpp/preproc.c +++ /dev/null @@ -1,763 +0,0 @@ -/* - * Copyright 1998 Bertho A. Stultiens (BS) - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif -#ifdef HAVE_IO_H -# include -#endif - -#include "wine/wpp.h" -#include "wpp_private.h" - -struct pp_status pp_status; - -#define HASHKEY 2039 - -typedef struct pp_def_state -{ - struct pp_def_state *next; - pp_entry_t *defines[HASHKEY]; -} pp_def_state_t; - -static pp_def_state_t *pp_def_state; - -#define MAXIFSTACK 64 -static pp_if_state_t if_stack[MAXIFSTACK]; -static int if_stack_idx = 0; - -#if 0 -void pp_print_status(void) __attribute__((destructor)); -void pp_print_status(void) -{ - int i; - int sum; - int total = 0; - pp_entry_t *ppp; - - fprintf(stderr, "Defines statistics:\n"); - for(i = 0; i < HASHKEY; i++) - { - sum = 0; - for(ppp = pp_def_state->defines[i]; ppp; ppp = ppp->next) - sum++; - total += sum; - if (sum) fprintf(stderr, "%4d, %3d\n", i, sum); - } - fprintf(stderr, "Total defines: %d\n", total); -} -#endif - -void *pp_xmalloc(size_t size) -{ - void *res; - - assert(size > 0); - res = malloc(size); - if(res == NULL) - { - /* Set the error flag */ - pp_status.state = 1; - } - return res; -} - -void *pp_xrealloc(void *p, size_t size) -{ - void *res; - - assert(size > 0); - res = realloc(p, size); - if(res == NULL) - { - /* Set the error flag */ - pp_status.state = 1; - } - return res; -} - -char *pp_xstrdup(const char *str) -{ - char *s; - int len; - - assert(str != NULL); - len = strlen(str)+1; - s = pp_xmalloc(len); - if(!s) - return NULL; - return memcpy(s, str, len); -} - -static char *wpp_default_lookup(const char *name, int type, const char *parent_name, - char **include_path, int include_path_count) -{ - char *cpy; - char *cptr; - char *path; - const char *ccptr; - int i, fd; - - cpy = pp_xmalloc(strlen(name)+1); - if(!cpy) - return NULL; - cptr = cpy; - - for(ccptr = name; *ccptr; ccptr++) - { - /* Convert to forward slash */ - if(*ccptr == '\\') { - /* kill double backslash */ - if(ccptr[1] == '\\') - ccptr++; - *cptr = '/'; - }else { - *cptr = *ccptr; - } - cptr++; - } - *cptr = '\0'; - - if(type && parent_name) - { - /* Search directory of parent include and then -I path */ - const char *p; - - if ((p = strrchr( parent_name, '/' ))) p++; - else p = parent_name; - path = pp_xmalloc( (p - parent_name) + strlen(cpy) + 1 ); - if(!path) - { - free(cpy); - return NULL; - } - memcpy( path, parent_name, p - parent_name ); - strcpy( path + (p - parent_name), cpy ); - fd = open( path, O_RDONLY ); - if (fd != -1) - { - close( fd ); - free( cpy ); - return path; - } - free( path ); - } - /* Search -I path */ - for(i = 0; i < include_path_count; i++) - { - path = pp_xmalloc(strlen(include_path[i]) + strlen(cpy) + 2); - if(!path) - { - free(cpy); - return NULL; - } - strcpy(path, include_path[i]); - strcat(path, "/"); - strcat(path, cpy); - fd = open( path, O_RDONLY ); - if (fd != -1) - { - close( fd ); - free( cpy ); - return path; - } - free( path ); - } - free( cpy ); - return NULL; -} - -static void *wpp_default_open(const char *filename, int type) { - return fopen(filename,"rt"); -} - -static void wpp_default_close(void *file) { - fclose(file); -} - -static int wpp_default_read(void *file, char *buffer, unsigned int len){ - return fread(buffer, 1, len, file); -} - -static void wpp_default_write( const char *buffer, unsigned int len ) { - fwrite(buffer, 1, len, ppy_out); -} - -/* Don't comment on the hash, it's primitive but functional... */ -static int pphash(const char *str) -{ - int sum = 0; - while(*str) - sum += *str++; - return sum % HASHKEY; -} - -pp_entry_t *pplookup(const char *ident) -{ - int idx; - pp_entry_t *ppp; - - if(!ident) - return NULL; - idx = pphash(ident); - for(ppp = pp_def_state->defines[idx]; ppp; ppp = ppp->next) - { - if(!strcmp(ident, ppp->ident)) - return ppp; - } - return NULL; -} - -static void free_pp_entry( pp_entry_t *ppp, int idx ) -{ - if(ppp->iep) - { - if(ppp->iep == pp_includelogiclist) - { - pp_includelogiclist = ppp->iep->next; - if(pp_includelogiclist) - pp_includelogiclist->prev = NULL; - } - else - { - ppp->iep->prev->next = ppp->iep->next; - if(ppp->iep->next) - ppp->iep->next->prev = ppp->iep->prev; - } - free(ppp->iep->filename); - free(ppp->iep); - } - - if(pp_def_state->defines[idx] == ppp) - { - pp_def_state->defines[idx] = ppp->next; - if(pp_def_state->defines[idx]) - pp_def_state->defines[idx]->prev = NULL; - } - else - { - ppp->prev->next = ppp->next; - if(ppp->next) - ppp->next->prev = ppp->prev; - } - - free(ppp); -} - -/* push a new (empty) define state */ -int pp_push_define_state(void) -{ - pp_def_state_t *state = pp_xmalloc( sizeof(*state) ); - if(!state) - return 1; - - memset( state->defines, 0, sizeof(state->defines) ); - state->next = pp_def_state; - pp_def_state = state; - return 0; -} - -/* pop the current define state */ -void pp_pop_define_state(void) -{ - int i; - pp_entry_t *ppp; - pp_def_state_t *state; - - for (i = 0; i < HASHKEY; i++) - { - while ((ppp = pp_def_state->defines[i]) != NULL) pp_del_define( ppp->ident ); - } - state = pp_def_state; - pp_def_state = state->next; - free( state ); -} - -void pp_del_define(const char *name) -{ - pp_entry_t *ppp; - int idx = pphash(name); - - if((ppp = pplookup(name)) == NULL) - { - if(pp_status.pedantic) - ppy_warning("%s was not defined", name); - return; - } - - if(pp_status.debug) - printf("Deleting (%s, %d) <%s>\n", pp_status.input, pp_status.line_number, name); - - free( ppp->ident ); - free( ppp->subst.text ); - free( ppp->filename ); - free_pp_entry( ppp, idx ); -} - -pp_entry_t *pp_add_define(const char *def, const char *text) -{ - int len; - char *cptr; - int idx; - pp_entry_t *ppp; - - if(!def) - return NULL; - idx = pphash(def); - if((ppp = pplookup(def)) != NULL) - { - if(pp_status.pedantic) - ppy_warning("Redefinition of %s\n\tPrevious definition: %s:%d", def, ppp->filename, ppp->linenumber); - pp_del_define(def); - } - ppp = pp_xmalloc(sizeof(pp_entry_t)); - if(!ppp) - return NULL; - memset( ppp, 0, sizeof(*ppp) ); - ppp->ident = pp_xstrdup(def); - if(!ppp->ident) - goto error; - ppp->type = def_define; - ppp->subst.text = text ? pp_xstrdup(text) : NULL; - if(text && !ppp->subst.text) - goto error; - ppp->filename = pp_xstrdup(pp_status.input ? pp_status.input : ""); - if(!ppp->filename) - goto error; - ppp->linenumber = pp_status.input ? pp_status.line_number : 0; - ppp->next = pp_def_state->defines[idx]; - pp_def_state->defines[idx] = ppp; - if(ppp->next) - ppp->next->prev = ppp; - if(ppp->subst.text) - { - /* Strip trailing white space from subst text */ - len = strlen(ppp->subst.text); - while(len && strchr(" \t\r\n", ppp->subst.text[len-1])) - { - ppp->subst.text[--len] = '\0'; - } - /* Strip leading white space from subst text */ - for(cptr = ppp->subst.text; *cptr && strchr(" \t\r", *cptr); cptr++) - ; - if(ppp->subst.text != cptr) - memmove(ppp->subst.text, cptr, strlen(cptr)+1); - } - if(pp_status.debug) - printf("Added define (%s, %d) <%s> to <%s>\n", pp_status.input, pp_status.line_number, ppp->ident, ppp->subst.text ? ppp->subst.text : "(null)"); - - return ppp; - -error: - free(ppp->ident); - free(ppp->subst.text); - free(ppp); - return NULL; -} - -pp_entry_t *pp_add_macro(char *id, marg_t *args[], int nargs, mtext_t *exp) -{ - int idx; - pp_entry_t *ppp; - - if(!id) - return NULL; - idx = pphash(id); - if((ppp = pplookup(id)) != NULL) - { - if(pp_status.pedantic) - ppy_warning("Redefinition of %s\n\tPrevious definition: %s:%d", id, ppp->filename, ppp->linenumber); - pp_del_define(id); - } - ppp = pp_xmalloc(sizeof(pp_entry_t)); - if(!ppp) - return NULL; - memset( ppp, 0, sizeof(*ppp) ); - ppp->ident = id; - ppp->type = def_macro; - ppp->margs = args; - ppp->nargs = nargs; - ppp->subst.mtext= exp; - ppp->filename = pp_xstrdup(pp_status.input ? pp_status.input : ""); - if(!ppp->filename) - { - free(ppp); - return NULL; - } - ppp->linenumber = pp_status.input ? pp_status.line_number : 0; - ppp->next = pp_def_state->defines[idx]; - pp_def_state->defines[idx] = ppp; - if(ppp->next) - ppp->next->prev = ppp; - - if(pp_status.debug) - { - fprintf(stderr, "Added macro (%s, %d) <%s(%d)> to <", pp_status.input, pp_status.line_number, ppp->ident, nargs); - for(; exp; exp = exp->next) - { - switch(exp->type) - { - case exp_text: - fprintf(stderr, " \"%s\" ", exp->subst.text); - break; - case exp_stringize: - fprintf(stderr, " #(%d) ", exp->subst.argidx); - break; - case exp_concat: - fprintf(stderr, "##"); - break; - case exp_subst: - fprintf(stderr, " <%d> ", exp->subst.argidx); - break; - } - } - fprintf(stderr, ">\n"); - } - return ppp; -} - - -/* - *------------------------------------------------------------------------- - * Include management - *------------------------------------------------------------------------- - */ -#if defined(_WIN32) || defined(__MSDOS__) -#define INCLUDESEPARATOR ";" -#else -#define INCLUDESEPARATOR ":" -#endif - -static char **includepath; -static int nincludepath = 0; - -int wpp_add_include_path(const char *path) -{ - char *tok; - char *cpy = pp_xstrdup(path); - if(!cpy) - return 1; - - tok = strtok(cpy, INCLUDESEPARATOR); - while(tok) - { - if(*tok) { - char *dir; - char *cptr; - char **new_path; - - dir = pp_xstrdup(tok); - if(!dir) - { - free(cpy); - return 1; - } - for(cptr = dir; *cptr; cptr++) - { - /* Convert to forward slash */ - if(*cptr == '\\') - *cptr = '/'; - } - /* Kill eventual trailing '/' */ - if(*(cptr = dir + strlen(dir)-1) == '/') - *cptr = '\0'; - - /* Add to list */ - new_path = pp_xrealloc(includepath, (nincludepath+1) * sizeof(*includepath)); - if(!new_path) - { - free(dir); - free(cpy); - return 1; - } - includepath = new_path; - includepath[nincludepath] = dir; - nincludepath++; - } - tok = strtok(NULL, INCLUDESEPARATOR); - } - free(cpy); - return 0; -} - -char *wpp_find_include(const char *name, const char *parent_name) -{ - return wpp_default_lookup(name, !!parent_name, parent_name, includepath, nincludepath); -} - -void *pp_open_include(const char *name, int type, const char *parent_name, char **newpath) -{ - char *path; - void *fp; - - if (!(path = wpp_callbacks->lookup(name, type, parent_name, includepath, - nincludepath))) return NULL; - fp = wpp_callbacks->open(path, type); - - if (fp) - { - if (pp_status.debug) - printf("Going to include <%s>\n", path); - if (newpath) *newpath = path; - else free( path ); - return fp; - } - free( path ); - return NULL; -} - -/* - *------------------------------------------------------------------------- - * #if, #ifdef, #ifndef, #else, #elif and #endif state management - * - * #if state transitions are made on basis of the current TOS and the next - * required state. The state transitions are required to housekeep because - * #if:s can be nested. The ignore case is activated to prevent output from - * within a false clause. - * Some special cases come from the fact that the #elif cases are not - * binary, but three-state. The problem is that all other elif-cases must - * be false when one true one has been found. A second problem is that the - * #else clause is a final clause. No extra #else:s may follow. - * - * The states mean: - * if_true Process input to output - * if_false Process input but no output - * if_ignore Process input but no output - * if_elif Process input but no output - * if_elsefalse Process input but no output - * if_elsettrue Process input to output - * - * The possible state-sequences are [state(stack depth)] (rest can be deduced): - * TOS #if 1 #else #endif - * if_true(n) if_true(n+1) if_elsefalse(n+1) - * if_false(n) if_ignore(n+1) if_ignore(n+1) - * if_elsetrue(n) if_true(n+1) if_elsefalse(n+1) - * if_elsefalse(n) if_ignore(n+1) if_ignore(n+1) - * if_elif(n) if_ignore(n+1) if_ignore(n+1) - * if_ignore(n) if_ignore(n+1) if_ignore(n+1) - * - * TOS #if 1 #elif 0 #else #endif - * if_true(n) if_true(n+1) if_elif(n+1) if_elif(n+1) - * if_false(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1) - * if_elsetrue(n) if_true(n+1) if_elif(n+1) if_elif(n+1) - * if_elsefalse(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1) - * if_elif(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1) - * if_ignore(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1) - * - * TOS #if 0 #elif 1 #else #endif - * if_true(n) if_false(n+1) if_true(n+1) if_elsefalse(n+1) - * if_false(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1) - * if_elsetrue(n) if_false(n+1) if_true(n+1) if_elsefalse(n+1) - * if_elsefalse(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1) - * if_elif(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1) - * if_ignore(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1) - * - *------------------------------------------------------------------------- - */ -static const char * const pp_if_state_str[] = { - "if_false", - "if_true", - "if_elif", - "if_elsefalse", - "if_elsetrue", - "if_ignore" -}; - -void pp_push_if(pp_if_state_t s) -{ - if(if_stack_idx >= MAXIFSTACK) - pp_internal_error(__FILE__, __LINE__, "#if-stack overflow; #{if,ifdef,ifndef} nested too deeply (> %d)", MAXIFSTACK); - - if(pp_flex_debug) - fprintf(stderr, "Push if %s:%d: %s(%d) -> %s(%d)\n", pp_status.input, pp_status.line_number, pp_if_state_str[pp_if_state()], if_stack_idx, pp_if_state_str[s], if_stack_idx+1); - - if_stack[if_stack_idx++] = s; - - switch(s) - { - case if_true: - case if_elsetrue: - break; - case if_false: - case if_elsefalse: - case if_elif: - case if_ignore: - pp_push_ignore_state(); - break; - default: - pp_internal_error(__FILE__, __LINE__, "Invalid pp_if_state (%d)", (int)pp_if_state()); - } -} - -pp_if_state_t pp_pop_if(void) -{ - if(if_stack_idx <= 0) - { - ppy_error("#{endif,else,elif} without #{if,ifdef,ifndef} (#if-stack underflow)"); - return if_error; - } - - switch(pp_if_state()) - { - case if_true: - case if_elsetrue: - break; - case if_false: - case if_elsefalse: - case if_elif: - case if_ignore: - pp_pop_ignore_state(); - break; - default: - pp_internal_error(__FILE__, __LINE__, "Invalid pp_if_state (%d)", (int)pp_if_state()); - } - - if(pp_flex_debug) - fprintf(stderr, "Pop if %s:%d: %s(%d) -> %s(%d)\n", - pp_status.input, - pp_status.line_number, - pp_if_state_str[pp_if_state()], - if_stack_idx, - pp_if_state_str[if_stack[if_stack_idx <= 1 ? if_true : if_stack_idx-2]], - if_stack_idx-1); - - return if_stack[--if_stack_idx]; -} - -pp_if_state_t pp_if_state(void) -{ - if(!if_stack_idx) - return if_true; - else - return if_stack[if_stack_idx-1]; -} - - -void pp_next_if_state(int i) -{ - switch(pp_if_state()) - { - case if_true: - case if_elsetrue: - pp_push_if(i ? if_true : if_false); - break; - case if_false: - case if_elsefalse: - case if_elif: - case if_ignore: - pp_push_if(if_ignore); - break; - default: - pp_internal_error(__FILE__, __LINE__, "Invalid pp_if_state (%d) in #{if,ifdef,ifndef} directive", (int)pp_if_state()); - } -} - -int pp_get_if_depth(void) -{ - return if_stack_idx; -} - -/* #define WANT_NEAR_INDICATION */ - -static void generic_msg(const char *s, const char *t, const char *n, va_list ap) -{ - fprintf(stderr, "%s:%d:%d: %s: ", pp_status.input ? pp_status.input : "stdin", - pp_status.line_number, pp_status.char_number, t); - vfprintf(stderr, s, ap); -#ifdef WANT_NEAR_INDICATION - { - char *cpy, *p; - if(n) - { - cpy = pp_xstrdup(n); - if(!cpy) - goto end; - for (p = cpy; *p; p++) if(!isprint(*p)) *p = ' '; - fprintf(stderr, " near '%s'", cpy); - free(cpy); - } - } -end: -#endif - fprintf(stderr, "\n"); -} - -static void wpp_default_error(const char *file, int line, int col, const char *near, const char *msg, va_list ap) -{ - generic_msg(msg, "Error", near, ap); - exit(1); -} - -static void wpp_default_warning(const char *file, int line, int col, const char *near, const char *msg, va_list ap) -{ - generic_msg(msg, "Warning", near, ap); -} - -static const struct wpp_callbacks default_callbacks = -{ - wpp_default_lookup, - wpp_default_open, - wpp_default_close, - wpp_default_read, - wpp_default_write, - wpp_default_error, - wpp_default_warning, -}; - -const struct wpp_callbacks *wpp_callbacks = &default_callbacks; - -int ppy_error(const char *s, ...) -{ - va_list ap; - va_start(ap, s); - wpp_callbacks->error(pp_status.input, pp_status.line_number, pp_status.char_number, ppy_text, s, ap); - va_end(ap); - pp_status.state = 1; - return 1; -} - -int ppy_warning(const char *s, ...) -{ - va_list ap; - va_start(ap, s); - wpp_callbacks->warning(pp_status.input, pp_status.line_number, pp_status.char_number, ppy_text, s, ap); - va_end(ap); - return 0; -} - -void pp_internal_error(const char *file, int line, const char *s, ...) -{ - va_list ap; - va_start(ap, s); - fprintf(stderr, "Internal error (please report) %s %d: ", file, line); - vfprintf(stderr, s, ap); - fprintf(stderr, "\n"); - va_end(ap); - exit(3); -} diff --git a/sdk/tools/wpp/wpp.c b/sdk/tools/wpp/wpp.c index 60b2d388581..57baf44862b 100644 --- a/sdk/tools/wpp/wpp.c +++ b/sdk/tools/wpp/wpp.c @@ -20,45 +20,510 @@ */ #include "config.h" -#include "wine/port.h" -#include +#include +#include +#include +#include #include +#include +#include +#include +#include "../tools.h" +#include "utils.h" #include "wpp_private.h" -#include "wine/wpp.h" + +struct pp_status pp_status; + +#define HASHKEY 2039 + +static struct list pp_defines[HASHKEY]; + +#define MAXIFSTACK 64 +static pp_if_state_t if_stack[MAXIFSTACK]; +static int if_stack_idx = 0; int ppy_debug, pp_flex_debug; struct define { - struct define *next; + struct list entry; char *name; char *value; }; -static struct define *cmdline_defines; +static struct list cmdline_defines = LIST_INIT( cmdline_defines ); +static struct strarray includes; + +static char *wpp_lookup(const char *name, int type, const char *parent_name) +{ + char *cpy; + char *cptr; + char *path; + const char *ccptr; + int i, fd; + + cpy = xmalloc(strlen(name)+1); + cptr = cpy; + + for(ccptr = name; *ccptr; ccptr++) + { + /* Convert to forward slash */ + if(*ccptr == '\\') { + /* kill double backslash */ + if(ccptr[1] == '\\') + ccptr++; + *cptr = '/'; + }else { + *cptr = *ccptr; + } + cptr++; + } + *cptr = '\0'; + + if(type && parent_name) + { + /* Search directory of parent include and then -I path */ + path = strmake( "%s/%s", get_dirname(parent_name), cpy ); + fd = open( path, O_RDONLY ); + if (fd != -1) + { + close( fd ); + free( cpy ); + return path; + } + free( path ); + } + /* Search -I path */ + for(i = 0; i < includes.count; i++) + { + path = strmake("%s/%s", includes.str[i], cpy); + fd = open( path, O_RDONLY ); + if (fd != -1) + { + close( fd ); + free( cpy ); + return path; + } + free( path ); + } + free( cpy ); + return NULL; +} + +/* Don't comment on the hash, it's primitive but functional... */ +static int pphash(const char *str) +{ + int sum = 0; + while(*str) + sum += *str++; + return sum % HASHKEY; +} + +pp_entry_t *pplookup(const char *ident) +{ + int idx; + pp_entry_t *ppp; + + if(!ident) + return NULL; + idx = pphash(ident); + LIST_FOR_EACH_ENTRY( ppp, &pp_defines[idx], pp_entry_t, entry ) + { + if(!strcmp(ident, ppp->ident)) + return ppp; + } + return NULL; +} + +static void free_pp_entry( pp_entry_t *ppp, int idx ) +{ + if(ppp->iep) + { + list_remove( &ppp->iep->entry ); + free(ppp->iep->filename); + free(ppp->iep); + } + list_remove( &ppp->entry ); + free(ppp); +} + +/* initialize the define state */ +static void pp_init_define_state(void) +{ + int i; + + for (i = 0; i < HASHKEY; i++) list_init( &pp_defines[i] ); +} + +/* free the current define state */ +static void pp_free_define_state(void) +{ + int i; + pp_entry_t *ppp, *ppp2; + + for (i = 0; i < HASHKEY; i++) + { + LIST_FOR_EACH_ENTRY_SAFE( ppp, ppp2, &pp_defines[i], pp_entry_t, entry ) + { + free( ppp->ident ); + free( ppp->subst.text ); + free( ppp->filename ); + free_pp_entry( ppp, i ); + } + } +} + +void pp_del_define(const char *name) +{ + pp_entry_t *ppp; + int idx = pphash(name); + + if((ppp = pplookup(name)) == NULL) + { + if(pedantic) + ppy_warning("%s was not defined", name); + return; + } + + if(pp_status.debug) + printf("Deleting (%s, %d) <%s>\n", pp_status.input, pp_status.line_number, name); + + free( ppp->ident ); + free( ppp->subst.text ); + free( ppp->filename ); + free_pp_entry( ppp, idx ); +} + +pp_entry_t *pp_add_define(const char *def, const char *text) +{ + int len; + char *cptr; + int idx; + pp_entry_t *ppp; + + idx = pphash(def); + if((ppp = pplookup(def)) != NULL) + { + if(pedantic) + ppy_warning("Redefinition of %s\n%s:%d: note: previous definition was here", + def, ppp->filename, ppp->linenumber); + pp_del_define(def); + } + ppp = xmalloc(sizeof(pp_entry_t)); + memset( ppp, 0, sizeof(*ppp) ); + ppp->ident = xstrdup(def); + ppp->type = def_define; + ppp->subst.text = text ? xstrdup(text) : NULL; + ppp->filename = xstrdup(pp_status.input ? pp_status.input : ""); + ppp->linenumber = pp_status.input ? pp_status.line_number : 0; + list_add_head( &pp_defines[idx], &ppp->entry ); + if(ppp->subst.text) + { + /* Strip trailing white space from subst text */ + len = strlen(ppp->subst.text); + while(len && strchr(" \t\r\n", ppp->subst.text[len-1])) + { + ppp->subst.text[--len] = '\0'; + } + /* Strip leading white space from subst text */ + for(cptr = ppp->subst.text; *cptr && strchr(" \t\r", *cptr); cptr++) + ; + if(ppp->subst.text != cptr) + memmove(ppp->subst.text, cptr, strlen(cptr)+1); + } + if(pp_status.debug) + printf("Added define (%s, %d) <%s> to <%s>\n", pp_status.input, pp_status.line_number, ppp->ident, ppp->subst.text ? ppp->subst.text : "(null)"); + + return ppp; +} + +pp_entry_t *pp_add_macro(char *id, char *args[], int nargs, int variadic, mtext_t *exp) +{ + int idx; + pp_entry_t *ppp; + + idx = pphash(id); + if((ppp = pplookup(id)) != NULL) + { + if(pedantic) + ppy_warning("Redefinition of %s\n%s:%d: note: previous definition was here", + id, ppp->filename, ppp->linenumber); + pp_del_define(id); + } + ppp = xmalloc(sizeof(pp_entry_t)); + memset( ppp, 0, sizeof(*ppp) ); + ppp->ident = id; + ppp->type = def_macro; + ppp->margs = args; + ppp->nargs = nargs; + ppp->variadic = variadic; + ppp->subst.mtext= exp; + ppp->filename = xstrdup(pp_status.input ? pp_status.input : ""); + ppp->linenumber = pp_status.input ? pp_status.line_number : 0; + list_add_head( &pp_defines[idx], &ppp->entry ); + if(pp_status.debug) + { + fprintf(stderr, "Added macro (%s, %d) <%s(%d%s)> to <", pp_status.input, pp_status.line_number, ppp->ident, nargs, variadic ? ",va" : ""); + for(; exp; exp = exp->next) + { + switch(exp->type) + { + case exp_text: + fprintf(stderr, " \"%s\" ", exp->subst.text); + break; + case exp_stringize: + fprintf(stderr, " #(%d) ", exp->subst.argidx); + break; + case exp_concat: + fprintf(stderr, "##"); + break; + case exp_subst: + fprintf(stderr, " <%d> ", exp->subst.argidx); + break; + } + } + fprintf(stderr, ">\n"); + } + return ppp; +} + + +/* + *------------------------------------------------------------------------- + * Include management + *------------------------------------------------------------------------- + */ +void wpp_add_include_path(const char *path) +{ + char *dir = xstrdup(path); + char *cptr; + + for(cptr = dir; *cptr; cptr++) + { + /* Convert to forward slash */ + if(*cptr == '\\') + *cptr = '/'; + } + /* Kill eventual trailing '/' */ + if(*(cptr = dir + strlen(dir)-1) == '/') *cptr = '\0'; + + strarray_add( &includes, dir ); +} + +char *wpp_find_include(const char *name, const char *parent_name) +{ + return wpp_lookup(name, !!parent_name, parent_name); +} + +void *pp_open_include(const char *name, int type, const char *parent_name, char **newpath) +{ + char *path; + void *fp; + + if (!(path = wpp_lookup(name, type, parent_name))) return NULL; + fp = fopen(path, "rt"); + + if (fp) + { + if (pp_status.debug) + printf("Going to include <%s>\n", path); + if (newpath) *newpath = path; + else free( path ); + return fp; + } + free( path ); + return NULL; +} + +/* + *------------------------------------------------------------------------- + * #if, #ifdef, #ifndef, #else, #elif and #endif state management + * + * #if state transitions are made on basis of the current TOS and the next + * required state. The state transitions are required to housekeep because + * #if:s can be nested. The ignore case is activated to prevent output from + * within a false clause. + * Some special cases come from the fact that the #elif cases are not + * binary, but three-state. The problem is that all other elif-cases must + * be false when one true one has been found. A second problem is that the + * #else clause is a final clause. No extra #else:s may follow. + * + * The states mean: + * if_true Process input to output + * if_false Process input but no output + * if_ignore Process input but no output + * if_elif Process input but no output + * if_elsefalse Process input but no output + * if_elsettrue Process input to output + * + * The possible state-sequences are [state(stack depth)] (rest can be deduced): + * TOS #if 1 #else #endif + * if_true(n) if_true(n+1) if_elsefalse(n+1) + * if_false(n) if_ignore(n+1) if_ignore(n+1) + * if_elsetrue(n) if_true(n+1) if_elsefalse(n+1) + * if_elsefalse(n) if_ignore(n+1) if_ignore(n+1) + * if_elif(n) if_ignore(n+1) if_ignore(n+1) + * if_ignore(n) if_ignore(n+1) if_ignore(n+1) + * + * TOS #if 1 #elif 0 #else #endif + * if_true(n) if_true(n+1) if_elif(n+1) if_elif(n+1) + * if_false(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1) + * if_elsetrue(n) if_true(n+1) if_elif(n+1) if_elif(n+1) + * if_elsefalse(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1) + * if_elif(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1) + * if_ignore(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1) + * + * TOS #if 0 #elif 1 #else #endif + * if_true(n) if_false(n+1) if_true(n+1) if_elsefalse(n+1) + * if_false(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1) + * if_elsetrue(n) if_false(n+1) if_true(n+1) if_elsefalse(n+1) + * if_elsefalse(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1) + * if_elif(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1) + * if_ignore(n) if_ignore(n+1) if_ignore(n+1) if_ignore(n+1) + * + *------------------------------------------------------------------------- + */ +static const char * const pp_if_state_str[] = { + "if_false", + "if_true", + "if_elif", + "if_elsefalse", + "if_elsetrue", + "if_ignore" +}; + +void pp_push_if(pp_if_state_t s) +{ + if(if_stack_idx >= MAXIFSTACK) + error("#if-stack overflow; #{if,ifdef,ifndef} nested too deeply (> %d)\n", MAXIFSTACK); + + if(pp_flex_debug) + fprintf(stderr, "Push if %s:%d: %s(%d) -> %s(%d)\n", pp_status.input, pp_status.line_number, pp_if_state_str[pp_if_state()], if_stack_idx, pp_if_state_str[s], if_stack_idx+1); + + if_stack[if_stack_idx++] = s; + + switch(s) + { + case if_true: + case if_elsetrue: + break; + case if_false: + case if_elsefalse: + case if_elif: + case if_ignore: + pp_push_ignore_state(); + break; + case if_error: + assert(0); + } +} + +pp_if_state_t pp_pop_if(void) +{ + if(if_stack_idx <= 0) + { + ppy_error("#{endif,else,elif} without #{if,ifdef,ifndef} (#if-stack underflow)"); + return if_error; + } + + switch(pp_if_state()) + { + case if_true: + case if_elsetrue: + break; + case if_false: + case if_elsefalse: + case if_elif: + case if_ignore: + pp_pop_ignore_state(); + break; + case if_error: + assert(0); + } + + if(pp_flex_debug) + fprintf(stderr, "Pop if %s:%d: %s(%d) -> %s(%d)\n", + pp_status.input, + pp_status.line_number, + pp_if_state_str[pp_if_state()], + if_stack_idx, + pp_if_state_str[if_stack[if_stack_idx <= 1 ? if_true : if_stack_idx-2]], + if_stack_idx-1); + + return if_stack[--if_stack_idx]; +} + +pp_if_state_t pp_if_state(void) +{ + if(!if_stack_idx) + return if_true; + else + return if_stack[if_stack_idx-1]; +} + + +void pp_next_if_state(int i) +{ + switch(pp_if_state()) + { + case if_true: + case if_elsetrue: + pp_push_if(i ? if_true : if_false); + break; + case if_false: + case if_elsefalse: + case if_elif: + case if_ignore: + pp_push_if(if_ignore); + break; + case if_error: + assert(0); + } +} + +int pp_get_if_depth(void) +{ + return if_stack_idx; +} + +static void generic_msg(const char *s, const char *t, const char *n, va_list ap) +{ + fprintf(stderr, "%s:%d:%d: %s: ", pp_status.input ? pp_status.input : "stdin", + pp_status.line_number, pp_status.char_number, t); + vfprintf(stderr, s, ap); + fprintf(stderr, "\n"); +} + +int ppy_error(const char *s, ...) +{ + va_list ap; + va_start(ap, s); + generic_msg(s, "error", ppy_text, ap); + va_end(ap); + exit(1); +} + +int ppy_warning(const char *s, ...) +{ + va_list ap; + va_start(ap, s); + generic_msg(s, "warning", ppy_text, ap); + va_end(ap); + return 0; +} static void add_cmdline_defines(void) { struct define *def; - for (def = cmdline_defines; def; def = def->next) + LIST_FOR_EACH_ENTRY( def, &cmdline_defines, struct define, entry ) { if (def->value) pp_add_define( def->name, def->value ); } } -static void del_cmdline_defines(void) -{ - struct define *def; - - for (def = cmdline_defines; def; def = def->next) - { - if (def->value) pp_del_define( def->name ); - } -} - static void add_special_defines(void) { time_t now = time(NULL); @@ -72,63 +537,33 @@ static void add_special_defines(void) pp_add_define( "__TIME__", buf ); ppp = pp_add_define( "__FILE__", "" ); - if(ppp) - ppp->type = def_special; + ppp->type = def_special; ppp = pp_add_define( "__LINE__", "" ); - if(ppp) - ppp->type = def_special; + ppp->type = def_special; } -static void del_special_defines(void) -{ - pp_del_define( "__DATE__" ); - pp_del_define( "__TIME__" ); - pp_del_define( "__FILE__" ); - pp_del_define( "__LINE__" ); -} - - /* add a define to the preprocessor list */ -int wpp_add_define( const char *name, const char *value ) +static void wpp_add_define( const char *name, const char *value ) { struct define *def; if (!value) value = ""; - for (def = cmdline_defines; def; def = def->next) + LIST_FOR_EACH_ENTRY( def, &cmdline_defines, struct define, entry ) { if (!strcmp( def->name, name )) { - char *new_value = pp_xstrdup(value); - if(!new_value) - return 1; free( def->value ); - def->value = new_value; - - return 0; + def->value = xstrdup(value); + return; } } - def = pp_xmalloc( sizeof(*def) ); - if(!def) - return 1; - def->next = cmdline_defines; - def->name = pp_xstrdup(name); - if(!def->name) - { - free(def); - return 1; - } - def->value = pp_xstrdup(value); - if(!def->value) - { - free(def->name); - free(def); - return 1; - } - cmdline_defines = def; - return 0; + def = xmalloc( sizeof(*def) ); + def->name = xstrdup(name); + def->value = xstrdup(value); + list_add_head( &cmdline_defines, &def->entry ); } @@ -137,7 +572,7 @@ void wpp_del_define( const char *name ) { struct define *def; - for (def = cmdline_defines; def; def = def->next) + LIST_FOR_EACH_ENTRY( def, &cmdline_defines, struct define, entry ) { if (!strcmp( def->name, name )) { @@ -150,17 +585,15 @@ void wpp_del_define( const char *name ) /* add a command-line define of the form NAME=VALUE */ -int wpp_add_cmdline_define( const char *value ) +void wpp_add_cmdline_define( const char *value ) { char *p; - char *str = pp_xstrdup(value); - if(!str) - return 1; + char *str = xstrdup(value); + p = strchr( str, '=' ); if (p) *p++ = 0; wpp_add_define( str, p ); free( str ); - return 0; } @@ -173,13 +606,6 @@ void wpp_set_debug( int lex_debug, int parser_debug, int msg_debug ) } -/* set the pedantic mode */ -void wpp_set_pedantic( int on ) -{ - pp_status.pedantic = on; -} - - /* the main preprocessor parsing loop */ int wpp_parse( const char *input, FILE *output ) { @@ -188,48 +614,29 @@ int wpp_parse( const char *input, FILE *output ) pp_status.input = NULL; pp_status.line_number = 1; pp_status.char_number = 1; - pp_status.state = 0; - ret = pp_push_define_state(); - if(ret) - return ret; + pp_init_define_state(); add_cmdline_defines(); add_special_defines(); if (!input) pp_status.file = stdin; - else if (!(pp_status.file = wpp_callbacks->open(input, 1))) - { + else if (!(pp_status.file = fopen(input, "rt"))) ppy_error("Could not open %s\n", input); - del_special_defines(); - del_cmdline_defines(); - pp_pop_define_state(); - return 2; - } - pp_status.input = input ? pp_xstrdup(input) : NULL; + pp_status.input = input ? xstrdup(input) : NULL; ppy_out = output; - pp_writestring("# 1 \"%s\" 1\n", input ? input : ""); + fprintf(ppy_out, "# 1 \"%s\" 1\n", input ? input : ""); ret = ppy_parse(); - /* If there were errors during processing, return an error code */ - if (!ret && pp_status.state) ret = pp_status.state; if (input) { - wpp_callbacks->close(pp_status.file); + fclose(pp_status.file); free(pp_status.input); } /* Clean if_stack, it could remain dirty on errors */ while (pp_get_if_depth()) pp_pop_if(); - del_special_defines(); - del_cmdline_defines(); - pp_pop_define_state(); + pp_free_define_state(); return ret; } - - -void wpp_set_callbacks( const struct wpp_callbacks *callbacks ) -{ - wpp_callbacks = callbacks; -} diff --git a/sdk/tools/wpp/wpp_private.h b/sdk/tools/wpp/wpp_private.h index caa52b9c563..998c426179d 100644 --- a/sdk/tools/wpp/wpp_private.h +++ b/sdk/tools/wpp/wpp_private.h @@ -20,12 +20,17 @@ #ifndef __WINE_WPP_PRIVATE_H #define __WINE_WPP_PRIVATE_H -#ifndef __WINE_CONFIG_H -# error You must include config.h to use this header -#endif - #include #include +#include "wine/list.h" + +extern void wpp_del_define( const char *name ); +extern void wpp_add_cmdline_define( const char *value ); +extern void wpp_set_debug( int lex_debug, int parser_debug, int msg_debug ); +extern void wpp_add_include_path( const char *path ); +extern char *wpp_find_include( const char *name, const char *parent_name ); +/* Return value == 0 means successful execution */ +extern int wpp_parse( const char *input, FILE *output ); struct pp_entry; /* forward */ /* @@ -34,26 +39,11 @@ struct pp_entry; /* forward */ * are protected in the #ifndef/#endif way. */ typedef struct includelogicentry { - struct includelogicentry *next; - struct includelogicentry *prev; + struct list entry; struct pp_entry *ppp; /* The define which protects the file */ char *filename; /* The filename of the include */ } includelogicentry_t; -/* - * The arguments of a macrodefinition - */ -typedef enum { - arg_single, - arg_list -} def_arg_t; - -typedef struct marg { - def_arg_t type; /* Normal or ... argument */ - char *arg; /* The textual argument */ - int nnl; /* Number of newlines in the text to subst */ -} marg_t; - /* * The expansiontext of a macro */ @@ -85,12 +75,12 @@ typedef enum { } def_type_t; typedef struct pp_entry { - struct pp_entry *next; - struct pp_entry *prev; + struct list entry; def_type_t type; /* Define or macro */ char *ident; /* The key */ - marg_t **margs; /* Macro arguments array or NULL if none */ + char **margs; /* Macro arguments array or NULL if none */ int nargs; + int variadic; union { mtext_t *mtext; /* The substitution sequence or NULL if none */ char *text; @@ -136,40 +126,13 @@ typedef struct int seen_junk; /* Set when junk is seen */ } include_state_t; - -/* - * If the configure says we have long long then we can use it. Presumably - * if we have long long then we have strtoull and strtoll too. If that is - * not the case we will need to add to the configure tests. - * If we do not have long long , then we revert to a simple 'long' for now. - * This should prevent most unexpected things with other compilers than - * gcc and egcs for now. - * In the future it should be possible to use another way, like a - * structure, so that we can emulate the MS compiler. - */ -#ifdef HAVE_LONG_LONG -typedef long long wrc_sll_t; -typedef unsigned long long wrc_ull_t; -#else -typedef long wrc_sll_t; -typedef unsigned long wrc_ull_t; -#endif - -#define SIZE_CHAR 1 -#define SIZE_SHORT 2 -#define SIZE_INT 3 -#define SIZE_LONG 4 -#define SIZE_LONGLONG 5 +#define SIZE_INT 1 +#define SIZE_LONG 2 +#define SIZE_LONGLONG 3 #define SIZE_MASK 0x00ff #define FLAG_SIGNED 0x0100 typedef enum { -#if 0 - cv_schar = SIZE_CHAR + FLAG_SIGNED, - cv_uchar = SIZE_CHAR, - cv_sshort = SIZE_SHORT + FLAG_SIGNED, - cv_ushort = SIZE_SHORT, -#endif cv_sint = SIZE_INT + FLAG_SIGNED, cv_uint = SIZE_INT, cv_slong = SIZE_LONG + FLAG_SIGNED, @@ -181,31 +144,20 @@ typedef enum { typedef struct cval { ctype_t type; union { -#if 0 - signed char sc; /* Explicitly signed because compilers are stupid */ - unsigned char uc; - short ss; - unsigned short us; -#endif int si; unsigned int ui; long sl; unsigned long ul; - wrc_sll_t sll; - wrc_ull_t ull; + __int64 sll; + unsigned __int64 ull; } val; } cval_t; -void *pp_xmalloc(size_t); -void *pp_xrealloc(void *, size_t); -char *pp_xstrdup(const char *str); pp_entry_t *pplookup(const char *ident); -int pp_push_define_state(void); -void pp_pop_define_state(void); pp_entry_t *pp_add_define(const char *def, const char *text); -pp_entry_t *pp_add_macro(char *ident, marg_t *args[], int nargs, mtext_t *exp); +pp_entry_t *pp_add_macro(char *ident, char *args[], int nargs, int variadic, mtext_t *exp); void pp_del_define(const char *name); void *pp_open_include(const char *name, int type, const char *parent_name, char **newpath); void pp_push_if(pp_if_state_t s); @@ -214,32 +166,29 @@ pp_if_state_t pp_pop_if(void); pp_if_state_t pp_if_state(void); int pp_get_if_depth(void); +#ifdef __REACTOS__ #ifndef __GNUC__ #define __attribute__(x) /*nothing*/ #endif - -extern const struct wpp_callbacks *wpp_callbacks; +#endif int ppy_error(const char *s, ...) __attribute__((format (printf, 1, 2))); int ppy_warning(const char *s, ...) __attribute__((format (printf, 1, 2))); -void pp_internal_error(const char *file, int line, const char *s, ...) __attribute__((format (printf, 3, 4))); /* current preprocessor state */ /* everything is in this structure to avoid polluting the global symbol space */ struct pp_status { char *input; /* current input file name */ - void *file; /* current input file descriptor */ + FILE *file; /* current input file descriptor */ int line_number; /* current line number */ int char_number; /* current char number in line */ - int state; /* current error state */ - int pedantic; /* pedantic option */ int debug; /* debug messages flag */ }; extern struct pp_status pp_status; extern include_state_t pp_incl_state; -extern includelogicentry_t *pp_includelogiclist; +extern int pedantic; /* * From ppl.l @@ -254,8 +203,6 @@ void pp_do_include(char *fname, int type); void pp_push_ignore_state(void); void pp_pop_ignore_state(void); -void pp_writestring(const char *format, ...) __attribute__((format (printf, 1, 2))); - /* * From ppy.y */