Added widl-winrt-support patchset

This commit is contained in:
Alistair Leslie-Hughes 2020-10-14 17:33:30 +11:00
parent 3cea972271
commit ae8bdc6121
32 changed files with 6362 additions and 58 deletions

View File

@ -268,10 +268,9 @@ patch_enable_all ()
enable_uxtheme_GTK_Theming="$1"
enable_version_VerQueryValue="$1"
enable_widl_SLTG_Typelib_Support="$1"
enable_widl_winrt_support="$1"
enable_windows_gaming_input_dll="$1"
enable_windows_globalization_dll="$1"
enable_windows_media_speech_dll="$1"
enable_windows_networking_connectivity_dll="$1"
enable_windowscodecs_GIF_Encoder="$1"
enable_windowscodecs_TIFF_Support="$1"
enable_wine_inf_Directory_ContextMenuHandlers="$1"
@ -893,18 +892,15 @@ patch_enable ()
widl-SLTG_Typelib_Support)
enable_widl_SLTG_Typelib_Support="$2"
;;
widl-winrt-support)
enable_widl_winrt_support="$2"
;;
windows.gaming.input-dll)
enable_windows_gaming_input_dll="$2"
;;
windows.globalization-dll)
enable_windows_globalization_dll="$2"
;;
windows.media.speech.dll)
enable_windows_media_speech_dll="$2"
;;
windows.networking.connectivity.dll)
enable_windows_networking_connectivity_dll="$2"
;;
windowscodecs-GIF_Encoder)
enable_windowscodecs_GIF_Encoder="$2"
;;
@ -1455,20 +1451,6 @@ if test "$enable_wineboot_ProxySettings" -eq 1; then
enable_wineboot_drivers_etc_Stubs=1
fi
if test "$enable_windows_networking_connectivity_dll" -eq 1; then
if test "$enable_windows_globalization_dll" -gt 1; then
abort "Patchset windows.globalization-dll disabled, but windows.networking.connectivity.dll depends on that."
fi
enable_windows_globalization_dll=1
fi
if test "$enable_windows_globalization_dll" -eq 1; then
if test "$enable_windows_media_speech_dll" -gt 1; then
abort "Patchset windows.media.speech.dll disabled, but windows.globalization-dll depends on that."
fi
enable_windows_media_speech_dll=1
fi
if test "$enable_windows_media_speech_dll" -eq 1; then
if test "$enable_windows_gaming_input_dll" -gt 1; then
abort "Patchset windows.gaming.input-dll disabled, but windows.media.speech.dll depends on that."
@ -4332,6 +4314,48 @@ if test "$enable_version_VerQueryValue" -eq 1; then
patch_apply version-VerQueryValue/0001-version-Test-for-VerQueryValueA-try-2.patch
fi
# Patchset widl-winrt-support
# |
# | This patchset fixes the following Wine bugs:
# | * [#68403] widl - Support WinRT idls
# |
# | Modified files:
# | * include/Makefile.in, include/windows.foundation.idl, include/windows.media.speechsynthesis.idl,
# | include/windowscontracts.idl, tools/widl/expr.c, tools/widl/hash.c, tools/widl/hash.h, tools/widl/header.c,
# | tools/widl/parser.l, tools/widl/parser.y, tools/widl/typegen.c, tools/widl/typelib.c, tools/widl/typetree.c,
# | tools/widl/typetree.h, tools/widl/widltypes.h
# |
if test "$enable_widl_winrt_support" -eq 1; then
patch_apply widl-winrt-support/0001-include-Add-windows.media.speechsynthesis.idl-draft.patch
patch_apply widl-winrt-support/0002-widl-Restrict-some-keywords-to-WinRT-mode-only.patch
patch_apply widl-winrt-support/0003-widl-Introduce-format_namespace_buffer-helper.patch
patch_apply widl-winrt-support/0004-widl-Support-WinRT-contractversion-attribute-parsing.patch
patch_apply widl-winrt-support/0005-widl-Support-WinRT-apicontract-type.patch
patch_apply widl-winrt-support/0006-widl-Prefer-mangled-name-over-typedef-in-WinRT-mode.patch
patch_apply widl-winrt-support/0007-widl-Don-t-output-typedef-statement-in-WinRT-mode.patch
patch_apply widl-winrt-support/0008-widl-Support-WinRT-contract-attribute.patch
patch_apply widl-winrt-support/0009-widl-Support-WinRT-marshaling_behavior-attribute-par.patch
patch_apply widl-winrt-support/0010-widl-Support-WinRT-mta-threading-attribute-parsing.patch
patch_apply widl-winrt-support/0011-widl-Support-WinRT-exclusiveto-attribute-parsing.patch
patch_apply widl-winrt-support/0012-widl-Support-WinRT-runtimeclass-type.patch
patch_apply widl-winrt-support/0013-widl-Support-WinRT-eventadd-eventremove-attributes.patch
patch_apply widl-winrt-support/0014-widl-Support-WinRT-flags-attribute-parsing.patch
patch_apply widl-winrt-support/0015-widl-Support-using-qualified-names-for-interfaces.patch
patch_apply widl-winrt-support/0016-widl-Support-repeated-attributes-for-WinRT-static.patch
patch_apply widl-winrt-support/0017-widl-Support-WinRT-static-attribute-parsing.patch
patch_apply widl-winrt-support/0018-widl-Support-WinRT-requires-keyword.patch
patch_apply widl-winrt-support/0019-widl-Support-WinRT-activatable-attribute.patch
patch_apply widl-winrt-support/0020-widl-Support-WinRT-parameterized-type-parsing.patch
patch_apply widl-winrt-support/0021-widl-Support-partially-specialized-parameterized-typ.patch
patch_apply widl-winrt-support/0022-widl-Support-WinRT-parameterized-interface-type.patch
patch_apply widl-winrt-support/0023-widl-Support-WinRT-delegate-type.patch
patch_apply widl-winrt-support/0024-widl-Support-WinRT-parameterized-delegate-type.patch
patch_apply widl-winrt-support/0025-widl-Compute-signatures-for-parameterized-types.patch
patch_apply widl-winrt-support/0026-widl-Compute-uuids-for-parameterized-types.patch
patch_apply widl-winrt-support/0027-widl-Generate-helper-macros-for-WinRT-implementation.patch
patch_apply widl-winrt-support/0028-include-Add-IVectorView-HSTRING-declaration-to-windo.patch
fi
# Patchset windows.gaming.input-dll
# |
# | This patchset fixes the following Wine bugs:
@ -4364,42 +4388,6 @@ if test "$enable_windows_media_speech_dll" -eq 1; then
patch_apply windows.media.speech.dll/0001-windows.media.speech-Add-stub-dll.patch
fi
# Patchset windows.globalization-dll
# |
# | This patchset has the following (direct or indirect) dependencies:
# | * windows.gaming.input-dll, windows.media.speech.dll
# |
# | This patchset fixes the following Wine bugs:
# | * [#49740] windows.globalization: New DLL
# |
# | Modified files:
# | * configure.ac, dlls/windows.globalization.dll/Makefile.in, dlls/windows.globalization.dll/windows.globalization.spec,
# | dlls/windows.globalization.dll/windows.globalization_main.c, include/Makefile.in, include/windows.globalization.idl,
# | loader/wine.inf.in
# |
if test "$enable_windows_globalization_dll" -eq 1; then
patch_apply windows.globalization-dll/0001-windows.globalization-Add-stub-dll.patch
fi
# Patchset windows.networking.connectivity.dll
# |
# | This patchset has the following (direct or indirect) dependencies:
# | * windows.gaming.input-dll, windows.media.speech.dll, windows.globalization-dll
# |
# | This patchset fixes the following Wine bugs:
# | * [#46534] windows.networking.connectivity: New DLL
# |
# | Modified files:
# | * configure.ac, dlls/windows.networking.connectivity.dll/Makefile.in,
# | dlls/windows.networking.connectivity.dll/windows.networking.connectivity.spec,
# | dlls/windows.networking.connectivity.dll/windows.networking.connectivity_main.c, loader/wine.inf.in
# |
if test "$enable_windows_networking_connectivity_dll" -eq 1; then
patch_apply windows.networking.connectivity.dll/0001-windows.networking.connectivity-Add-stub-dll.patch
patch_apply windows.networking.connectivity.dll/0002-windows.networking.connectivity-Implement-IActivatio.patch
patch_apply windows.networking.connectivity.dll/0003-windows.networking.connectivity-Implement-INetworkIn.patch
fi
# Patchset windowscodecs-GIF_Encoder
# |
# | Modified files:

View File

@ -0,0 +1,69 @@
From 5dc312c4a09e51410c217919511b84323923607e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Wed, 23 Sep 2020 19:23:45 +0200
Subject: [PATCH 01/28] include: Add windows.media.speechsynthesis.idl draft.
This IDL is used by windows.media.speech.dll, which is itself required
by Flight Simulator. It will here be used as an illustration and test
case for WIDL WinRT features.
---
include/Makefile.in | 1 +
include/windows.media.speechsynthesis.idl | 34 +++++++++++++++++++++++
2 files changed, 35 insertions(+)
create mode 100644 include/windows.media.speechsynthesis.idl
diff --git a/include/Makefile.in b/include/Makefile.in
index 23306689cab..d59b0be715d 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -735,6 +735,7 @@ SOURCES = \
windef.h \
windns.h \
windows.foundation.idl \
+ windows.media.speechsynthesis.idl \
windows.h \
windowsx.h \
wine/debug.h \
diff --git a/include/windows.media.speechsynthesis.idl b/include/windows.media.speechsynthesis.idl
new file mode 100644
index 00000000000..d3dedfe0709
--- /dev/null
+++ b/include/windows.media.speechsynthesis.idl
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2020 Rémi Bernon for CodeWeavers
+ *
+ * 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
+ */
+
+#ifdef __WIDL__
+#pragma winrt ns_prefix
+#endif
+
+import "inspectable.idl";
+import "windows.foundation.idl";
+
+namespace Windows {
+ namespace Media {
+ namespace SpeechSynthesis {
+ typedef enum VoiceGender VoiceGender;
+ interface IInstalledVoicesStatic;
+ interface IVoiceInformation;
+ }
+ }
+}
--
2.28.0

View File

@ -0,0 +1,381 @@
From 58eea69462505e4ea88675adcbe85b49b9cf2e35 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 22 Sep 2020 18:03:23 +0200
Subject: [PATCH 02/28] widl: Restrict some keywords to WinRT mode only.
---
tools/widl/parser.l | 333 ++++++++++++++++++++++----------------------
1 file changed, 167 insertions(+), 166 deletions(-)
diff --git a/tools/widl/parser.l b/tools/widl/parser.l
index 925265d00db..eb1782d32f5 100644
--- a/tools/widl/parser.l
+++ b/tools/widl/parser.l
@@ -248,67 +248,68 @@ int parser_wrap(void)
struct keyword {
const char *kw;
int token;
+ int winrt_only : 1;
};
/* 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},
+ {"FALSE", tFALSE, 0},
+ {"NULL", tNULL, 0},
+ {"TRUE", tTRUE, 0},
+ {"__cdecl", tCDECL, 0},
+ {"__fastcall", tFASTCALL, 0},
+ {"__int32", tINT32, 0},
+ {"__int3264", tINT3264, 0},
+ {"__int64", tINT64, 0},
+ {"__pascal", tPASCAL, 0},
+ {"__stdcall", tSTDCALL, 0},
+ {"_cdecl", tCDECL, 0},
+ {"_fastcall", tFASTCALL, 0},
+ {"_pascal", tPASCAL, 0},
+ {"_stdcall", tSTDCALL, 0},
+ {"boolean", tBOOLEAN, 0},
+ {"byte", tBYTE, 0},
+ {"case", tCASE, 0},
+ {"cdecl", tCDECL, 0},
+ {"char", tCHAR, 0},
+ {"coclass", tCOCLASS, 0},
+ {"const", tCONST, 0},
+ {"cpp_quote", tCPPQUOTE, 0},
+ {"default", tDEFAULT, 0},
+ {"dispinterface", tDISPINTERFACE, 0},
+ {"double", tDOUBLE, 0},
+ {"enum", tENUM, 0},
+ {"error_status_t", tERRORSTATUST, 0},
+ {"extern", tEXTERN, 0},
+ {"float", tFLOAT, 0},
+ {"handle_t", tHANDLET, 0},
+ {"hyper", tHYPER, 0},
+ {"import", tIMPORT, 0},
+ {"importlib", tIMPORTLIB, 0},
+ {"inline", tINLINE, 0},
+ {"int", tINT, 0},
+ {"interface", tINTERFACE, 0},
+ {"library", tLIBRARY, 0},
+ {"long", tLONG, 0},
+ {"methods", tMETHODS, 0},
+ {"module", tMODULE, 0},
+ {"namespace", tNAMESPACE, 1},
+ {"pascal", tPASCAL, 0},
+ {"properties", tPROPERTIES, 0},
+ {"register", tREGISTER, 0},
+ {"short", tSHORT, 0},
+ {"signed", tSIGNED, 0},
+ {"sizeof", tSIZEOF, 0},
+ {"small", tSMALL, 0},
+ {"static", tSTATIC, 0},
+ {"stdcall", tSTDCALL, 0},
+ {"struct", tSTRUCT, 0},
+ {"switch", tSWITCH, 0},
+ {"typedef", tTYPEDEF, 0},
+ {"union", tUNION, 0},
+ {"unsigned", tUNSIGNED, 0},
+ {"void", tVOID, 0},
+ {"wchar_t", tWCHAR, 0},
};
#define NKEYWORDS (sizeof(keywords)/sizeof(keywords[0]))
@@ -317,113 +318,113 @@ static const struct keyword keywords[] = {
*/
static const struct keyword attr_keywords[] =
{
- {"aggregatable", tAGGREGATABLE},
- {"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},
- {"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},
- {"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},
+ {"aggregatable", tAGGREGATABLE, 0},
+ {"allocate", tALLOCATE, 0},
+ {"annotation", tANNOTATION, 0},
+ {"apartment", tAPARTMENT, 0},
+ {"appobject", tAPPOBJECT, 0},
+ {"async", tASYNC, 0},
+ {"async_uuid", tASYNCUUID, 0},
+ {"auto_handle", tAUTOHANDLE, 0},
+ {"bindable", tBINDABLE, 0},
+ {"both", tBOTH, 0},
+ {"broadcast", tBROADCAST, 0},
+ {"byte_count", tBYTECOUNT, 0},
+ {"call_as", tCALLAS, 0},
+ {"callback", tCALLBACK, 0},
+ {"code", tCODE, 0},
+ {"comm_status", tCOMMSTATUS, 0},
+ {"context_handle", tCONTEXTHANDLE, 0},
+ {"context_handle_noserialize", tCONTEXTHANDLENOSERIALIZE, 0},
+ {"context_handle_serialize", tCONTEXTHANDLENOSERIALIZE, 0},
+ {"control", tCONTROL, 0},
+ {"decode", tDECODE, 0},
+ {"defaultbind", tDEFAULTBIND, 0},
+ {"defaultcollelem", tDEFAULTCOLLELEM, 0},
+ {"defaultvalue", tDEFAULTVALUE, 0},
+ {"defaultvtable", tDEFAULTVTABLE, 0},
+ {"disable_consistency_check", tDISABLECONSISTENCYCHECK, 0},
+ {"displaybind", tDISPLAYBIND, 0},
+ {"dllname", tDLLNAME, 0},
+ {"dual", tDUAL, 0},
+ {"enable_allocate", tENABLEALLOCATE, 0},
+ {"encode", tENCODE, 0},
+ {"endpoint", tENDPOINT, 0},
+ {"entry", tENTRY, 0},
+ {"explicit_handle", tEXPLICITHANDLE, 0},
+ {"fault_status", tFAULTSTATUS, 0},
+ {"force_allocate", tFORCEALLOCATE, 0},
+ {"free", tFREE, 0},
+ {"handle", tHANDLE, 0},
+ {"helpcontext", tHELPCONTEXT, 0},
+ {"helpfile", tHELPFILE, 0},
+ {"helpstring", tHELPSTRING, 0},
+ {"helpstringcontext", tHELPSTRINGCONTEXT, 0},
+ {"helpstringdll", tHELPSTRINGDLL, 0},
+ {"hidden", tHIDDEN, 0},
+ {"id", tID, 0},
+ {"idempotent", tIDEMPOTENT, 0},
+ {"ignore", tIGNORE, 0},
+ {"iid_is", tIIDIS, 0},
+ {"immediatebind", tIMMEDIATEBIND, 0},
+ {"implicit_handle", tIMPLICITHANDLE, 0},
+ {"in", tIN, 0},
+ {"in_line", tIN_LINE, 0},
+ {"input_sync", tINPUTSYNC, 0},
+ {"lcid", tLCID, 0},
+ {"length_is", tLENGTHIS, 0},
+ {"licensed", tLICENSED, 0},
+ {"local", tLOCAL, 0},
+ {"maybe", tMAYBE, 0},
+ {"message", tMESSAGE, 0},
+ {"neutral", tNEUTRAL, 0},
+ {"nocode", tNOCODE, 0},
+ {"nonbrowsable", tNONBROWSABLE, 0},
+ {"noncreatable", tNONCREATABLE, 0},
+ {"nonextensible", tNONEXTENSIBLE, 0},
+ {"notify", tNOTIFY, 0},
+ {"notify_flag", tNOTIFYFLAG, 0},
+ {"object", tOBJECT, 0},
+ {"odl", tODL, 0},
+ {"oleautomation", tOLEAUTOMATION, 0},
+ {"optimize", tOPTIMIZE, 0},
+ {"optional", tOPTIONAL, 0},
+ {"out", tOUT, 0},
+ {"partial_ignore", tPARTIALIGNORE, 0},
+ {"pointer_default", tPOINTERDEFAULT, 0},
+ {"progid", tPROGID, 0},
+ {"propget", tPROPGET, 0},
+ {"propput", tPROPPUT, 0},
+ {"propputref", tPROPPUTREF, 0},
+ {"proxy", tPROXY, 0},
+ {"ptr", tPTR, 0},
+ {"public", tPUBLIC, 0},
+ {"range", tRANGE, 0},
+ {"readonly", tREADONLY, 0},
+ {"ref", tREF, 0},
+ {"represent_as", tREPRESENTAS, 0},
+ {"requestedit", tREQUESTEDIT, 0},
+ {"restricted", tRESTRICTED, 0},
+ {"retval", tRETVAL, 0},
+ {"single", tSINGLE, 0},
+ {"size_is", tSIZEIS, 0},
+ {"source", tSOURCE, 0},
+ {"strict_context_handle", tSTRICTCONTEXTHANDLE, 0},
+ {"string", tSTRING, 0},
+ {"switch_is", tSWITCHIS, 0},
+ {"switch_type", tSWITCHTYPE, 0},
+ {"threading", tTHREADING, 0},
+ {"transmit_as", tTRANSMITAS, 0},
+ {"uidefault", tUIDEFAULT, 0},
+ {"unique", tUNIQUE, 0},
+ {"user_marshal", tUSERMARSHAL, 0},
+ {"usesgetlasterror", tUSESGETLASTERROR, 0},
+ {"uuid", tUUID, 0},
+ {"v1_enum", tV1ENUM, 0},
+ {"vararg", tVARARG, 0},
+ {"version", tVERSION, 0},
+ {"vi_progid", tVIPROGID, 0},
+ {"wire_marshal", tWIREMARSHAL, 0},
};
/* attributes TODO:
@@ -446,7 +447,7 @@ static int kw_token(const char *kw)
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)) {
+ if (kwp && (!kwp->winrt_only || winrt_mode)) {
parser_lval.str = xstrdup(kwp->kw);
return kwp->token;
}
@@ -460,7 +461,7 @@ static int attr_token(const char *kw)
key.kw = kw;
kwp = bsearch(&key, attr_keywords, sizeof(attr_keywords)/sizeof(attr_keywords[0]),
sizeof(attr_keywords[0]), kw_cmp_func);
- if (kwp) {
+ if (kwp && (!kwp->winrt_only || winrt_mode)) {
parser_lval.str = xstrdup(kwp->kw);
return kwp->token;
}
--
2.28.0

View File

@ -0,0 +1,129 @@
From ee1ce628835376e5054972ef3c39996a2b015309 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Wed, 23 Sep 2020 14:14:01 +0200
Subject: [PATCH 03/28] widl: Introduce format_namespace_buffer helper.
To compute format_namespace length and write to an existing buffer.
Also add explicit abi_prefix parameter.
---
tools/widl/header.c | 2 +-
tools/widl/parser.y | 2 +-
tools/widl/typetree.c | 54 +++++++++++++++++++-----------------------
tools/widl/widltypes.h | 3 ++-
4 files changed, 29 insertions(+), 32 deletions(-)
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 743d86f0ee9..d67fea4cc95 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -132,7 +132,7 @@ static void write_guid(FILE *f, const char *guid_prefix, const char *name, const
static void write_uuid_decl(FILE *f, type_t *type, const UUID *uuid)
{
- char *name = format_namespace(type->namespace, "", "::", type->name);
+ char *name = format_namespace(type->namespace, "", "::", type->name, use_abi_namespace ? "ABI" : NULL);
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",
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 5bc0d82703e..306e5194467 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -1905,7 +1905,7 @@ type_t *reg_type(type_t *type, const char *name, struct namespace *namespace, in
if (is_global_namespace(namespace))
type->c_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);
nt->type = type;
nt->t = t;
nt->next = namespace->type_hash[hash];
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index e9afc6fdd28..ebba2c4c6bb 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -89,41 +89,37 @@ const char *type_get_name(const type_t *type, enum name_type name_type)
return NULL;
}
-static char *append_namespace(char *ptr, struct namespace *namespace, const char *separator)
-{
- if(is_global_namespace(namespace)) {
- if(!use_abi_namespace)
- return ptr;
- strcpy(ptr, "ABI");
- strcat(ptr, separator);
- return ptr + strlen(ptr);
- }
+#define append_buf(f, ...) \
+ do { int r = f(buf + ret, max(ret, len) - ret, __VA_ARGS__); assert(r >= 0); ret += r; } while(0)
- ptr = append_namespace(ptr, namespace->parent, separator);
- strcpy(ptr, namespace->name);
- strcat(ptr, separator);
- return ptr + strlen(ptr);
+static int append_namespace(char *buf, size_t len, struct namespace *namespace, const char *separator, const char *abi_prefix)
+{
+ const char *name = namespace && !is_global_namespace(namespace) ? namespace->name : abi_prefix;
+ int ret = 0;
+ if (!name) return 0;
+ if (namespace && !is_global_namespace(namespace)) append_buf(append_namespace, namespace->parent, separator, abi_prefix);
+ append_buf(snprintf, "%s%s", name, separator);
+ return ret;
}
-char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix)
+static int format_namespace_buffer(char *buf, size_t len, struct namespace *namespace, const char *prefix,
+ const char *separator, const char *suffix, const char *abi_prefix)
{
- unsigned len = strlen(prefix) + strlen(suffix);
- unsigned sep_len = strlen(separator);
- struct namespace *iter;
- char *ret, *ptr;
-
- if(use_abi_namespace && !is_global_namespace(namespace))
- len += 3 /* strlen("ABI") */ + sep_len;
-
- for(iter = namespace; !is_global_namespace(iter); iter = iter->parent)
- len += strlen(iter->name) + sep_len;
+ int ret = 0;
+ append_buf(snprintf, "%s", prefix);
+ append_buf(append_namespace, namespace, separator, abi_prefix);
+ append_buf(snprintf, "%s", suffix);
+ return ret;
+}
- ret = xmalloc(len+1);
- strcpy(ret, prefix);
- ptr = append_namespace(ret + strlen(ret), namespace, separator);
- strcpy(ptr, suffix);
+#undef append_buf
- return ret;
+char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, const char *abi_prefix)
+{
+ int len = format_namespace_buffer(NULL, 0, namespace, prefix, separator, suffix, abi_prefix);
+ char *buf = xmalloc(len + 1);
+ format_namespace_buffer(buf, len + 1, namespace, prefix, separator, suffix, abi_prefix);
+ return buf;
}
type_t *type_new_function(var_list_t *args)
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 085a0ff55f5..630f42860f1 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -605,7 +605,8 @@ 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);
+char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix,
+ const char *abi_prefix);
static inline enum type_type type_get_type_detect_alias(const type_t *type)
{
--
2.28.0

View File

@ -0,0 +1,89 @@
From 8f57c43dd3adceb5baf529a6e42a1e813c024e20 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 13 Oct 2020 14:04:28 +0200
Subject: [PATCH 04/28] widl: Support WinRT contractversion attribute parsing.
---
tools/widl/parser.l | 1 +
tools/widl/parser.y | 12 +++++++++++-
tools/widl/widltypes.h | 1 +
3 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/tools/widl/parser.l b/tools/widl/parser.l
index eb1782d32f5..dafd17ab2f9 100644
--- a/tools/widl/parser.l
+++ b/tools/widl/parser.l
@@ -337,6 +337,7 @@ static const struct keyword attr_keywords[] =
{"context_handle", tCONTEXTHANDLE, 0},
{"context_handle_noserialize", tCONTEXTHANDLENOSERIALIZE, 0},
{"context_handle_serialize", tCONTEXTHANDLENOSERIALIZE, 0},
+ {"contractversion", tCONTRACTVERSION, 1},
{"control", tCONTROL, 0},
{"decode", tDECODE, 0},
{"defaultbind", tDEFAULTBIND, 0},
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 306e5194467..88cb9a10863 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -176,7 +176,9 @@ static typelib_t *current_typelib;
%token tAUTOHANDLE tBINDABLE tBOOLEAN tBROADCAST tBYTE tBYTECOUNT
%token tCALLAS tCALLBACK tCASE tCDECL tCHAR tCOCLASS tCODE tCOMMSTATUS
%token tCONST tCONTEXTHANDLE tCONTEXTHANDLENOSERIALIZE
-%token tCONTEXTHANDLESERIALIZE tCONTROL tCPPQUOTE
+%token tCONTEXTHANDLESERIALIZE
+%token tCONTRACTVERSION
+%token tCONTROL tCPPQUOTE
%token tDECODE tDEFAULT tDEFAULTBIND
%token tDEFAULTCOLLELEM
%token tDEFAULTVALUE
@@ -288,6 +290,7 @@ static typelib_t *current_typelib;
%type <declarator> m_abstract_declarator abstract_declarator abstract_declarator_no_direct abstract_direct_declarator
%type <declarator_list> declarator_list struct_declarator_list
%type <type> coclass coclasshdr coclassdef
+%type <num> contract_ver
%type <num> pointer_type threading_type version
%type <str> libraryhdr callconv cppquote importlib import t_ident
%type <uuid> uuid_string
@@ -489,6 +492,11 @@ str_list: aSTRING { $$ = append_str( NULL, $1 ); }
| str_list ',' aSTRING { $$ = append_str( $1, $3 ); }
;
+contract_ver:
+ aNUM { $$ = MAKEVERSION(0, $1); }
+ | aNUM '.' aNUM { $$ = MAKEVERSION($3, $1); }
+ ;
+
attribute: { $$ = NULL; }
| tAGGREGATABLE { $$ = make_attr(ATTR_AGGREGATABLE); }
| tANNOTATION '(' aSTRING ')' { $$ = make_attrp(ATTR_ANNOTATION, $3); }
@@ -504,6 +512,7 @@ attribute: { $$ = NULL; }
| 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 */ }
+ | tCONTRACTVERSION '(' contract_ver ')' { $$ = make_attrv(ATTR_CONTRACTVERSION, $3); }
| tCONTROL { $$ = make_attr(ATTR_CONTROL); }
| tDECODE { $$ = make_attr(ATTR_DECODE); }
| tDEFAULT { $$ = make_attr(ATTR_DEFAULT); }
@@ -2135,6 +2144,7 @@ struct allowed_attr allowed_attr[] =
/* ATTR_CODE */ { 0, 1, 1, 1, 0, 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, 0, "comm_status" },
/* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" },
+ /* ATTR_CONTRACTVERSION */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "contractversion" },
/* ATTR_CONTROL */ { 0, 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, 0, "decode" },
/* ATTR_DEFAULT */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, "default" },
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 630f42860f1..1b00b8da002 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -82,6 +82,7 @@ enum attr_type
ATTR_CODE,
ATTR_COMMSTATUS,
ATTR_CONTEXTHANDLE,
+ ATTR_CONTRACTVERSION,
ATTR_CONTROL,
ATTR_DECODE,
ATTR_DEFAULT,
--
2.28.0

View File

@ -0,0 +1,551 @@
From 70534016bc2963703a003e9a0888ad21f5bf026e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 13 Oct 2020 13:37:19 +0200
Subject: [PATCH 05/28] widl: Support WinRT apicontract type.
---
include/Makefile.in | 1 +
include/windows.foundation.idl | 1 +
include/windowscontracts.idl | 33 +++++
tools/widl/expr.c | 1 +
tools/widl/header.c | 24 ++++
tools/widl/parser.l | 1 +
tools/widl/parser.y | 235 +++++++++++++++++++--------------
tools/widl/typegen.c | 6 +
tools/widl/typelib.c | 3 +-
tools/widl/typetree.h | 3 +
tools/widl/widltypes.h | 1 +
11 files changed, 206 insertions(+), 103 deletions(-)
create mode 100644 include/windowscontracts.idl
diff --git a/include/Makefile.in b/include/Makefile.in
index d59b0be715d..91297753b12 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -737,6 +737,7 @@ SOURCES = \
windows.foundation.idl \
windows.media.speechsynthesis.idl \
windows.h \
+ windowscontracts.idl \
windowsx.h \
wine/debug.h \
wine/exception.h \
diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl
index 2c16fa2da22..2a38e9f671b 100644
--- a/include/windows.foundation.idl
+++ b/include/windows.foundation.idl
@@ -22,6 +22,7 @@
import "inspectable.idl";
/* import "asyncinfo.idl"; */
+import "windowscontracts.idl";
/* import "eventtoken.idl"; */
/* import "ivectorchangedeventargs.idl"; */
diff --git a/include/windowscontracts.idl b/include/windowscontracts.idl
new file mode 100644
index 00000000000..6bcf80ac954
--- /dev/null
+++ b/include/windowscontracts.idl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2020 Rémi Bernon for CodeWeavers
+ *
+ * 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
+ */
+
+#ifdef __WIDL__
+#pragma winrt ns_prefix
+#endif
+
+namespace Windows {
+ namespace Foundation {
+ [contractversion(4)]
+ apicontract FoundationContract
+ {};
+
+ [contractversion(10)]
+ apicontract UniversalApiContract
+ {};
+ }
+}
diff --git a/tools/widl/expr.c b/tools/widl/expr.c
index d1ee599a39e..be8311cfb7f 100644
--- a/tools/widl/expr.c
+++ b/tools/widl/expr.c
@@ -462,6 +462,7 @@ 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:
/* nothing to do */
break;
case TYPE_ALIAS:
diff --git a/tools/widl/header.c b/tools/widl/header.c
index d67fea4cc95..607d156ccf4 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -464,6 +464,7 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i
break;
}
case TYPE_ALIAS:
+ case TYPE_APICONTRACT:
/* handled elsewhere */
assert(0);
break;
@@ -529,6 +530,10 @@ void write_type_right(FILE *h, type_t *t, int is_field)
case TYPE_COCLASS:
case TYPE_INTERFACE:
break;
+ case TYPE_APICONTRACT:
+ /* not supposed to be here */
+ assert(0);
+ break;
}
}
@@ -1446,6 +1451,14 @@ static void write_forward(FILE *header, type_t *iface)
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_com_interface_start(FILE *header, const type_t *iface)
{
int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE);
@@ -1610,6 +1623,15 @@ 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_import(FILE *header, const char *fname)
{
char *hname, *p;
@@ -1728,6 +1750,8 @@ 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
{
write_type_definition(header, stmt->u.type, stmt->declonly);
diff --git a/tools/widl/parser.l b/tools/widl/parser.l
index dafd17ab2f9..11debca2ebd 100644
--- a/tools/widl/parser.l
+++ b/tools/widl/parser.l
@@ -267,6 +267,7 @@ static const struct keyword keywords[] = {
{"_fastcall", tFASTCALL, 0},
{"_pascal", tPASCAL, 0},
{"_stdcall", tSTDCALL, 0},
+ {"apicontract", tAPICONTRACT, 1},
{"boolean", tBOOLEAN, 0},
{"byte", tBYTE, 0},
{"case", tCASE, 0},
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 88cb9a10863..bdd019a2880 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -99,6 +99,7 @@ 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);
+static attr_list_t *check_apicontract_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);
@@ -172,7 +173,9 @@ static typelib_t *current_typelib;
%token GREATEREQUAL LESSEQUAL
%token LOGICALOR LOGICALAND
%token ELLIPSIS
-%token tAGGREGATABLE tALLOCATE tANNOTATION tAPPOBJECT tASYNC tASYNCUUID
+%token tAGGREGATABLE 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 tCONST tCONTEXTHANDLE tCONTEXTHANDLENOSERIALIZE
@@ -290,6 +293,7 @@ static typelib_t *current_typelib;
%type <declarator> m_abstract_declarator abstract_declarator abstract_declarator_no_direct abstract_direct_declarator
%type <declarator_list> declarator_list struct_declarator_list
%type <type> coclass coclasshdr coclassdef
+%type <type> apicontract
%type <num> contract_ver
%type <num> pointer_type threading_type version
%type <str> libraryhdr callconv cppquote importlib import t_ident
@@ -346,6 +350,8 @@ gbl_statements: { $$ = NULL; }
| gbl_statements coclassdef { $$ = append_statement($1, make_statement_type_decl($2));
reg_type($2, $2->name, current_namespace, 0);
}
+ | gbl_statements apicontract ';' { $$ = 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); }
@@ -360,6 +366,8 @@ imp_statements: { $$ = NULL; }
| imp_statements coclassdef { $$ = append_statement($1, make_statement_type_decl($2));
reg_type($2, $2->name, current_namespace, 0);
}
+ | imp_statements apicontract ';' { $$ = 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)); }
@@ -864,6 +872,13 @@ coclassdef: coclasshdr '{' coclass_ints '}' semicolon_opt
{ $$ = type_coclass_define($1, $3); }
;
+apicontract: attributes tAPICONTRACT aIDENTIFIER '{' '}'
+ { $$ = get_type(TYPE_APICONTRACT, $3, current_namespace, 0);
+ check_def($$);
+ $$->attrs = check_apicontract_attrs($$->name, $1);
+ }
+ ;
+
namespacedef: tNAMESPACE aIDENTIFIER { $$ = $2; }
| tNAMESPACE aNAMESPACE { $$ = $2; }
;
@@ -2124,112 +2139,113 @@ struct allowed_attr
unsigned int on_dispinterface : 1;
unsigned int on_module : 1;
unsigned int on_coclass : 1;
+ unsigned int on_apicontract : 1;
const char *display_name;
};
struct allowed_attr allowed_attr[] =
{
- /* attr { D ACF I Fn ARG T En Enm St Un Fi L DI M C <display name> } */
- /* ATTR_AGGREGATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "aggregatable" },
- /* ATTR_ANNOTATION */ { 0, 0, 0, 0, 1, 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, 1, "appobject" },
- /* ATTR_ASYNC */ { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "async" },
- /* ATTR_ASYNCUUID */ { 1, 0, 1, 0, 0, 1, 1, 0, 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, 0, "auto_handle" },
- /* ATTR_BINDABLE */ { 0, 0, 0, 1, 0, 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, 0, "broadcast" },
- /* ATTR_CALLAS */ { 0, 0, 0, 1, 0, 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, 0, NULL },
- /* ATTR_CASE */ { 1, 0, 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, 0, "code" },
- /* ATTR_COMMSTATUS */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "comm_status" },
- /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" },
- /* ATTR_CONTRACTVERSION */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "contractversion" },
- /* ATTR_CONTROL */ { 0, 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, 0, "decode" },
- /* ATTR_DEFAULT */ { 0, 0, 1, 0, 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, 0, "defaultbind" },
- /* ATTR_DEFAULTCOLLELEM */ { 0, 0, 0, 1, 0, 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, 0, "defaultvalue" },
- /* ATTR_DEFAULTVTABLE */ { 0, 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, 0, "disable_consistency_check" },
- /* ATTR_DISPINTERFACE */ { 0, 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, 0, "displaybind" },
- /* ATTR_DLLNAME */ { 0, 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, 0, "dual" },
- /* ATTR_ENABLEALLOCATE */ { 0, 0, 1, 0, 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, 0, "encode" },
- /* ATTR_ENDPOINT */ { 1, 0, 1, 0, 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, 0, "entry" },
- /* ATTR_EXPLICIT_HANDLE */ { 1, 1, 1, 0, 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, 0, "fault_status" },
- /* ATTR_FORCEALLOCATE */ { 0, 0, 0, 0, 1, 0, 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, 0, "handle" },
- /* ATTR_HELPCONTEXT */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, "helpcontext" },
- /* ATTR_HELPFILE */ { 0, 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, 0, 1, 1, 1, 1, "helpstring" },
- /* ATTR_HELPSTRINGCONTEXT */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, "helpstringcontext" },
- /* ATTR_HELPSTRINGDLL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "helpstringdll" },
- /* ATTR_HIDDEN */ { 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, "hidden" },
- /* ATTR_ID */ { 0, 0, 0, 1, 0, 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, 0, "idempotent" },
- /* ATTR_IGNORE */ { 0, 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, 0, 1, 0, 0, 0, 0, "iid_is" },
- /* ATTR_IMMEDIATEBIND */ { 0, 0, 0, 1, 0, 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, 0, "implicit_handle" },
- /* ATTR_IN */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" },
- /* ATTR_INPUTSYNC */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" },
- /* ATTR_LENGTHIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "length_is" },
- /* ATTR_LIBLCID */ { 0, 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, 0, 1, "licensed" },
- /* ATTR_LOCAL */ { 1, 0, 1, 1, 0, 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, 0, "maybe" },
- /* ATTR_MESSAGE */ { 0, 0, 0, 1, 0, 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, 0, "nocode" },
- /* ATTR_NONBROWSABLE */ { 0, 0, 0, 1, 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, 1, "noncreatable" },
- /* ATTR_NONEXTENSIBLE */ { 0, 0, 1, 0, 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, 0, "notify" },
- /* ATTR_NOTIFYFLAG */ { 0, 0, 0, 1, 0, 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, 0, "object" },
- /* ATTR_ODL */ { 0, 0, 1, 0, 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, 0, "oleautomation" },
- /* ATTR_OPTIMIZE */ { 0, 0, 1, 1, 0, 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, 0, "optional" },
- /* ATTR_OUT */ { 1, 0, 0, 0, 1, 0, 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, 0, "lcid" },
- /* ATTR_PARTIALIGNORE */ { 0, 0, 0, 0, 1, 0, 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, 0, "pointer_default" },
- /* ATTR_POINTERTYPE */ { 1, 0, 0, 0, 1, 1, 0, 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, 0, 1, "progid" },
- /* ATTR_PROPGET */ { 0, 0, 0, 1, 0, 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, 0, "propput" },
- /* ATTR_PROPPUTREF */ { 0, 0, 0, 1, 0, 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, 0, "proxy" },
- /* ATTR_PUBLIC */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "public" },
- /* ATTR_RANGE */ { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, "range" },
- /* ATTR_READONLY */ { 0, 0, 0, 0, 1, 0, 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, 0, "represent_as" },
- /* ATTR_REQUESTEDIT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "requestedit" },
- /* ATTR_RESTRICTED */ { 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, "restricted" },
- /* ATTR_RETVAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "retval" },
- /* ATTR_SIZEIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "size_is" },
- /* ATTR_SOURCE */ { 0, 0, 1, 1, 0, 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, 0, "strict_context_handle" },
- /* ATTR_STRING */ { 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, "string" },
- /* ATTR_SWITCHIS */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "switch_is" },
- /* ATTR_SWITCHTYPE */ { 1, 0, 0, 0, 0, 1, 0, 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, 0, 1, "threading" },
- /* ATTR_TRANSMITAS */ { 1, 0, 0, 0, 0, 1, 0, 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, 0, "uidefault" },
- /* ATTR_USESGETLASTERROR */ { 0, 0, 0, 1, 0, 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, 0, "user_marshal" },
- /* ATTR_UUID */ { 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, "uuid" },
- /* ATTR_V1ENUM */ { 0, 0, 0, 0, 0, 1, 1, 0, 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, 0, "vararg" },
- /* ATTR_VERSION */ { 1, 0, 1, 0, 0, 1, 1, 0, 2, 0, 0, 1, 0, 0, 1, "version" },
- /* ATTR_VIPROGID */ { 0, 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, 0, "wire_marshal" },
+ /* attr { D ACF I Fn ARG T En Enm St Un Fi L DI M C AC <display name> } */
+ /* ATTR_AGGREGATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "aggregatable" },
+ /* ATTR_ANNOTATION */ { 0, 0, 0, 0, 1, 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, 1, 0, "appobject" },
+ /* ATTR_ASYNC */ { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "async" },
+ /* ATTR_ASYNCUUID */ { 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "async_uuid" },
+ /* ATTR_AUTO_HANDLE */ { 1, 1, 1, 0, 0, 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, 0, 0, "bindable" },
+ /* ATTR_BROADCAST */ { 1, 0, 0, 1, 0, 0, 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, 0, 0, "call_as" },
+ /* ATTR_CALLCONV */ { 0, 0, 0, 1, 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, 1, 0, 0, 0, 0, 0, "case" },
+ /* ATTR_CODE */ { 0, 1, 1, 1, 0, 0, 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, 0, 0, "comm_status" },
+ /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" },
+ /* ATTR_CONTRACTVERSION */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "contractversion" },
+ /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, "control" },
+ /* ATTR_DECODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "decode" },
+ /* ATTR_DEFAULT */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, "default" },
+ /* ATTR_DEFAULTBIND */ { 0, 0, 0, 1, 0, 0, 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, 0, 0, "defaultcollelem" },
+ /* ATTR_DEFAULTVALUE */ { 0, 0, 0, 0, 1, 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, 1, 0, "defaultvtable" },
+ /* ATTR_DISABLECONSISTENCYCHECK */{ 0, 0, 0, 0, 1, 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, 0, 0, 0, NULL },
+ /* ATTR_DISPLAYBIND */ { 0, 0, 0, 1, 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, 1, 0, 0, "dllname" },
+ /* ATTR_DUAL */ { 0, 0, 1, 0, 0, 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, 0, 0, "enable_allocate" },
+ /* ATTR_ENCODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 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, 0, 0, "endpoint" },
+ /* ATTR_ENTRY */ { 0, 0, 0, 1, 0, 0, 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, 0, 0, "explicit_handle" },
+ /* ATTR_FAULTSTATUS */ { 0, 0, 0, 1, 1, 0, 0, 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, 0, 0, "force_allocate" },
+ /* ATTR_HANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "handle" },
+ /* ATTR_HELPCONTEXT */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "helpcontext" },
+ /* ATTR_HELPFILE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "helpfile" },
+ /* ATTR_HELPSTRING */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "helpstring" },
+ /* ATTR_HELPSTRINGCONTEXT */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "helpstringcontext" },
+ /* ATTR_HELPSTRINGDLL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "helpstringdll" },
+ /* ATTR_HIDDEN */ { 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, "hidden" },
+ /* ATTR_ID */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, "id" },
+ /* ATTR_IDEMPOTENT */ { 1, 0, 0, 1, 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, 1, 0, 0, 0, 0, 0, "ignore" },
+ /* ATTR_IIDIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "iid_is" },
+ /* ATTR_IMMEDIATEBIND */ { 0, 0, 0, 1, 0, 0, 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, 0, 0, "implicit_handle" },
+ /* ATTR_IN */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" },
+ /* ATTR_INPUTSYNC */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" },
+ /* ATTR_LENGTHIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "length_is" },
+ /* ATTR_LIBLCID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "lcid" },
+ /* ATTR_LICENSED */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "licensed" },
+ /* ATTR_LOCAL */ { 1, 0, 1, 1, 0, 0, 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, 0, 0, "maybe" },
+ /* ATTR_MESSAGE */ { 0, 0, 0, 1, 0, 0, 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, 0, 0, "nocode" },
+ /* ATTR_NONBROWSABLE */ { 0, 0, 0, 1, 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, 1, 0, "noncreatable" },
+ /* ATTR_NONEXTENSIBLE */ { 0, 0, 1, 0, 0, 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, 0, 0, "notify" },
+ /* ATTR_NOTIFYFLAG */ { 0, 0, 0, 1, 0, 0, 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, 0, 0, "object" },
+ /* ATTR_ODL */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "odl" },
+ /* ATTR_OLEAUTOMATION */ { 0, 0, 1, 0, 0, 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, 0, 0, "optimize" },
+ /* ATTR_OPTIONAL */ { 0, 0, 0, 0, 1, 0, 0, 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, 0, 0, "out" },
+ /* ATTR_PARAMLCID */ { 0, 0, 0, 0, 1, 0, 0, 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, 0, 0, "partial_ignore" },
+ /* ATTR_POINTERDEFAULT */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "pointer_default" },
+ /* ATTR_POINTERTYPE */ { 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 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, 1, 0, "progid" },
+ /* ATTR_PROPGET */ { 0, 0, 0, 1, 0, 0, 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, 0, 0, "propput" },
+ /* ATTR_PROPPUTREF */ { 0, 0, 0, 1, 0, 0, 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, 0, 0, "proxy" },
+ /* ATTR_PUBLIC */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "public" },
+ /* ATTR_RANGE */ { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, "range" },
+ /* ATTR_READONLY */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "readonly" },
+ /* ATTR_REPRESENTAS */ { 1, 0, 0, 0, 0, 1, 0, 0, 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, 0, 0, "requestedit" },
+ /* ATTR_RESTRICTED */ { 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, "restricted" },
+ /* ATTR_RETVAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "retval" },
+ /* ATTR_SIZEIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "size_is" },
+ /* ATTR_SOURCE */ { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "source" },
+ /* ATTR_STRICTCONTEXTHANDLE */ { 0, 0, 1, 0, 0, 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, 0, 1, 0, 0, 0, 0, 0, "string" },
+ /* ATTR_SWITCHIS */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "switch_is" },
+ /* ATTR_SWITCHTYPE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "switch_type" },
+ /* ATTR_THREADING */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "threading" },
+ /* ATTR_TRANSMITAS */ { 1, 0, 0, 0, 0, 1, 0, 0, 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, 0, 0, "uidefault" },
+ /* ATTR_USESGETLASTERROR */ { 0, 0, 0, 1, 0, 0, 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, 0, 0, "user_marshal" },
+ /* ATTR_UUID */ { 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, "uuid" },
+ /* ATTR_V1ENUM */ { 0, 0, 0, 0, 0, 1, 1, 0, 0, 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, 0, 0, "vararg" },
+ /* ATTR_VERSION */ { 1, 0, 1, 0, 0, 1, 1, 0, 2, 0, 0, 1, 0, 0, 1, 0, "version" },
+ /* ATTR_VIPROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "vi_progid" },
+ /* ATTR_WIREMARSHAL */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "wire_marshal" },
};
const char *get_attr_display_name(enum attr_type type)
@@ -2420,6 +2436,17 @@ static attr_list_t *check_coclass_attrs(const char *name, attr_list_t *attrs)
return attrs;
}
+static attr_list_t *check_apicontract_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_apicontract)
+ error_loc("inapplicable attribute %s for apicontract %s\n",
+ allowed_attr[attr->type].display_name, name);
+ return attrs;
+}
+
static int is_allowed_conf_type(const type_t *type)
{
switch (type_get_type(type))
@@ -2459,6 +2486,10 @@ static int is_allowed_conf_type(const type_t *type)
case TYPE_INTERFACE:
case TYPE_BITFIELD:
return FALSE;
+ case TYPE_APICONTRACT:
+ /* not supposed to be here */
+ assert(0);
+ break;
}
return FALSE;
}
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index 04280cbb722..46aae9b69e9 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -374,6 +374,10 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att
case TYPE_ALIAS:
case TYPE_BITFIELD:
break;
+ case TYPE_APICONTRACT:
+ /* not supposed to be here */
+ assert(0);
+ break;
}
return TGT_INVALID;
}
@@ -1966,6 +1970,7 @@ 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:
/* 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
@@ -2067,6 +2072,7 @@ static unsigned int type_buffer_alignment(const type_t *t)
case TYPE_MODULE:
case TYPE_FUNCTION:
case TYPE_BITFIELD:
+ case TYPE_APICONTRACT:
/* 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
diff --git a/tools/widl/typelib.c b/tools/widl/typelib.c
index cf027558d0a..faf76440f93 100644
--- a/tools/widl/typelib.c
+++ b/tools/widl/typelib.c
@@ -224,7 +224,8 @@ unsigned short get_type_vt(type_t *t)
return VT_VOID;
case TYPE_ALIAS:
- /* aliases should be filtered out by the type_get_type call above */
+ case TYPE_APICONTRACT:
+ /* not supposed to be here */
assert(0);
break;
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h
index e288c574002..7abec41a8fd 100644
--- a/tools/widl/typetree.h
+++ b/tools/widl/typetree.h
@@ -223,6 +223,9 @@ static inline int type_is_complete(const type_t *type)
case TYPE_ARRAY:
case TYPE_BITFIELD:
return TRUE;
+ case TYPE_APICONTRACT:
+ assert(0);
+ break;
}
return FALSE;
}
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 1b00b8da002..add7cedfacc 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -432,6 +432,7 @@ enum type_type
TYPE_POINTER,
TYPE_ARRAY,
TYPE_BITFIELD,
+ TYPE_APICONTRACT,
};
struct _type_t {
--
2.28.0

View File

@ -0,0 +1,74 @@
From 9e4292bb0ed2953f71ebe6c835db790d3cd5f954 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 12 Oct 2020 19:11:44 +0200
Subject: [PATCH 06/28] widl: Prefer mangled name over typedef in WinRT mode.
MIDL generates prefixed mangled name for every use of enum, struct and
union types, in fields types as well as function arguments. When the
types are in the global namespace, the typedef name is used instead.
---
tools/widl/header.c | 13 ++++++++++---
tools/widl/typetree.c | 2 +-
2 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 607d156ccf4..d8dfcf4f4c3 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -250,7 +250,7 @@ static void write_fields(FILE *h, var_list_t *fields)
default:
;
}
- write_type_v(h, &v->declspec, TRUE, v->declonly, name, NAME_DEFAULT);
+ write_type_v(h, &v->declspec, TRUE, v->declonly, name, NAME_C);
fprintf(h, ";\n");
}
}
@@ -322,7 +322,7 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i
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 (!winrt_mode && type_is_alias(t)) fprintf(h, "%s", t->name);
else {
switch (type_get_type_detect_alias(t)) {
case TYPE_ENUM:
@@ -464,6 +464,13 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i
break;
}
case TYPE_ALIAS:
+ {
+ const decl_spec_t *ds = type_alias_get_aliasee(t);
+ int in_namespace = ds && ds->type && ds->type->namespace && !is_global_namespace(ds->type->namespace);
+ if (!in_namespace) fprintf(h, "%s", t->name);
+ else write_type_left(h, ds, name_type, declonly, write_callconv);
+ break;
+ }
case TYPE_APICONTRACT:
/* handled elsewhere */
assert(0);
@@ -807,7 +814,7 @@ static void write_generic_handle_routines(FILE *header)
static void write_typedef(FILE *header, type_t *type, int declonly)
{
fprintf(header, "typedef ");
- write_type_v(header, type_alias_get_aliasee(type), FALSE, declonly, type->name, NAME_DEFAULT);
+ write_type_v(header, type_alias_get_aliasee(type), FALSE, declonly, type->name, NAME_C);
fprintf(header, ";\n");
}
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index ebba2c4c6bb..d8dcd5d80b0 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -82,7 +82,7 @@ const char *type_get_name(const type_t *type, enum name_type 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);
--
2.28.0

View File

@ -0,0 +1,27 @@
From 98a3b25143161e249102eceef6face6833ba19ea Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 12 Oct 2020 19:11:44 +0200
Subject: [PATCH 07/28] widl: Don't output typedef statement in WinRT mode.
For types under a non-global namespace, since we reference them with
their prefixed mangled names.
---
tools/widl/header.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tools/widl/header.c b/tools/widl/header.c
index d8dfcf4f4c3..0a8272fdbb4 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -813,6 +813,8 @@ static void write_generic_handle_routines(FILE *header)
static void write_typedef(FILE *header, type_t *type, int declonly)
{
+ type_t *t = type_alias_get_aliasee_type(type);
+ if (winrt_mode && t->namespace && !is_global_namespace(t->namespace)) return;
fprintf(header, "typedef ");
write_type_v(header, type_alias_get_aliasee(type), FALSE, declonly, type->name, NAME_C);
fprintf(header, ";\n");
--
2.28.0

View File

@ -0,0 +1,341 @@
From 9b5039017bd7072164042bf7b739f373134978ea Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Wed, 23 Sep 2020 19:23:45 +0200
Subject: [PATCH 08/28] widl: Support WinRT contract attribute.
---
include/windows.foundation.idl | 14 ++---
include/windows.media.speechsynthesis.idl | 13 ++++
tools/widl/header.c | 72 ++++++++++++++++++++++-
tools/widl/parser.l | 1 +
tools/widl/parser.y | 10 ++++
tools/widl/widltypes.h | 1 +
6 files changed, 101 insertions(+), 10 deletions(-)
diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl
index 2a38e9f671b..5e17062f399 100644
--- a/include/windows.foundation.idl
+++ b/include/windows.foundation.idl
@@ -28,7 +28,7 @@ import "windowscontracts.idl";
namespace Windows {
namespace Foundation {
- [version(0x06020000)]
+ [contract(Windows.Foundation.FoundationContract, 1.0)]
enum PropertyType {
Empty = 0,
UInt8 = 1,
@@ -73,19 +73,19 @@ namespace Windows {
OtherTypeArray = 1044
};
- [version(0x06020000)]
+ [contract(Windows.Foundation.FoundationContract, 1.0)]
struct Point {
FLOAT X;
FLOAT Y;
};
- [version(0x06020000)]
+ [contract(Windows.Foundation.FoundationContract, 1.0)]
struct Size {
FLOAT Width;
FLOAT Height;
};
- [version(0x06020000)]
+ [contract(Windows.Foundation.FoundationContract, 1.0)]
struct Rect {
FLOAT X;
FLOAT Y;
@@ -93,18 +93,18 @@ namespace Windows {
FLOAT Height;
};
- [version(0x06020000)]
+ [contract(Windows.Foundation.FoundationContract, 1.0)]
struct DateTime {
INT64 UniversalTime;
};
- [version(0x06020000)]
+ [contract(Windows.Foundation.FoundationContract, 1.0)]
struct TimeSpan {
INT64 Duration;
};
[
- version(0x06030000),
+ contract(Windows.Foundation.FoundationContract, 1.0),
uuid(96369f54-8eb6-48f0-abce-c1b211e627c3)
]
interface IStringable : IInspectable
diff --git a/include/windows.media.speechsynthesis.idl b/include/windows.media.speechsynthesis.idl
index d3dedfe0709..7a1de5fcba6 100644
--- a/include/windows.media.speechsynthesis.idl
+++ b/include/windows.media.speechsynthesis.idl
@@ -32,3 +32,16 @@ namespace Windows {
}
}
}
+
+namespace Windows {
+ namespace Media {
+ namespace SpeechSynthesis {
+ [contract(Windows.Foundation.UniversalApiContract, 1.0)]
+ enum VoiceGender
+ {
+ Male = 0,
+ Female = 1
+ };
+ }
+ }
+}
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 0a8272fdbb4..0fd3eb917ea 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -45,6 +45,11 @@ generic_handle_list_t generic_handle_list = LIST_INIT(generic_handle_list);
static void write_type_v(FILE *f, const decl_spec_t *t, int is_field, int declonly, const char *name, enum name_type name_type);
+static void write_winrt_type_comments(FILE *header, const type_t *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 indent(FILE *h, int delta)
{
int c;
@@ -218,7 +223,9 @@ static void write_fields(FILE *h, var_list_t *fields)
}
LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) {
+ expr_t *contract = get_attrp(v->attrs, ATTR_CONTRACT);
if (!v || !v->declspec.type) continue;
+ if (contract) write_apicontract_guard_start(h, contract);
indent(h, 0);
name = v->name;
@@ -252,6 +259,7 @@ static void write_fields(FILE *h, var_list_t *fields)
}
write_type_v(h, &v->declspec, TRUE, v->declonly, name, NAME_C);
fprintf(h, ";\n");
+ if (contract) write_apicontract_guard_end(h, contract);
}
}
@@ -261,6 +269,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)
@@ -273,8 +283,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)
@@ -563,7 +574,9 @@ static void write_type_definition(FILE *f, type_t *t, int declonly)
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");
@@ -581,6 +594,7 @@ static void write_type_definition(FILE *f, type_t *t, int declonly)
fprintf(f, ";\n");
fprintf(f, "#endif\n\n");
}
+ if (contract) write_apicontract_guard_end(f, contract);
}
void write_type_decl(FILE *f, const decl_spec_t *t, const char *name)
@@ -1468,12 +1482,55 @@ static char *format_apicontract_macro(const type_t *type)
return name;
}
+static void write_winrt_type_comments(FILE *header, const type_t *type)
+{
+ expr_t *contract = get_attrp(type->attrs, ATTR_CONTRACT);
+ fprintf(header, " *\n");
+ if (contract)
+ {
+ const type_t *type = contract->u.tref.type;
+ char *name = format_namespace(type->namespace, "", ".", type->name, NULL);
+ int ver = contract->ref->u.lval;
+ fprintf(header, " * Introduced to %s in version %d.%d\n *\n", name, (ver >> 16) & 0xffff, ver & 0xffff);
+ free(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.lval;
+ 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.lval;
+ 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" : "");
+ if (winrt_mode) write_winrt_type_comments(header, iface);
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" : "");
}
@@ -1482,6 +1539,7 @@ 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);
+ expr_t *contract = get_attrp(iface->attrs, ATTR_CONTRACT);
type_t *type;
if (uuid)
@@ -1559,17 +1617,22 @@ 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));
+ if (winrt_mode) write_winrt_type_comments(header, iface);
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)
@@ -1594,7 +1657,10 @@ 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)
diff --git a/tools/widl/parser.l b/tools/widl/parser.l
index 11debca2ebd..c3d0e9e2746 100644
--- a/tools/widl/parser.l
+++ b/tools/widl/parser.l
@@ -338,6 +338,7 @@ static const struct keyword attr_keywords[] =
{"context_handle", tCONTEXTHANDLE, 0},
{"context_handle_noserialize", tCONTEXTHANDLENOSERIALIZE, 0},
{"context_handle_serialize", tCONTEXTHANDLENOSERIALIZE, 0},
+ {"contract", tCONTRACT, 1},
{"contractversion", tCONTRACTVERSION, 1},
{"control", tCONTROL, 0},
{"decode", tDECODE, 0},
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index bdd019a2880..28d7e16dad4 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -180,6 +180,7 @@ static typelib_t *current_typelib;
%token tCALLAS tCALLBACK tCASE tCDECL tCHAR tCOCLASS tCODE tCOMMSTATUS
%token tCONST tCONTEXTHANDLE tCONTEXTHANDLENOSERIALIZE
%token tCONTEXTHANDLESERIALIZE
+%token tCONTRACT
%token tCONTRACTVERSION
%token tCONTROL tCPPQUOTE
%token tDECODE tDEFAULT tDEFAULTBIND
@@ -269,6 +270,7 @@ static typelib_t *current_typelib;
%type <str_list> str_list
%type <expr> m_expr expr expr_const expr_int_const array m_bitfield
%type <expr_list> m_exprs /* exprs expr_list */ expr_list_int_const
+%type <expr> contract_req
%type <type> interfacehdr
%type <stgclass> storage_cls_spec
%type <type_qualifier> type_qualifier m_type_qual_list
@@ -505,6 +507,12 @@ contract_ver:
| aNUM '.' aNUM { $$ = MAKEVERSION($3, $1); }
;
+contract_req: decl_spec ',' contract_ver { if ($1->type->type_type != TYPE_APICONTRACT)
+ error_loc("type %s is not an apicontract\n", $1->type->name);
+ $$ = make_exprl(EXPR_NUM, $3);
+ $$ = make_exprt(EXPR_GTREQL, declare_var(NULL, $1, make_declarator(NULL), 0), $$);
+ }
+
attribute: { $$ = NULL; }
| tAGGREGATABLE { $$ = make_attr(ATTR_AGGREGATABLE); }
| tANNOTATION '(' aSTRING ')' { $$ = make_attrp(ATTR_ANNOTATION, $3); }
@@ -520,6 +528,7 @@ attribute: { $$ = NULL; }
| 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 */ }
+ | tCONTRACT '(' contract_req ')' { $$ = make_attrp(ATTR_CONTRACT, $3); }
| tCONTRACTVERSION '(' contract_ver ')' { $$ = make_attrv(ATTR_CONTRACTVERSION, $3); }
| tCONTROL { $$ = make_attr(ATTR_CONTROL); }
| tDECODE { $$ = make_attr(ATTR_DECODE); }
@@ -2160,6 +2169,7 @@ struct allowed_attr allowed_attr[] =
/* ATTR_CODE */ { 0, 1, 1, 1, 0, 0, 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, 0, 0, "comm_status" },
/* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" },
+ /* ATTR_CONTRACT */ { 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, "contract" },
/* ATTR_CONTRACTVERSION */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "contractversion" },
/* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, "control" },
/* ATTR_DECODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "decode" },
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index add7cedfacc..3f358efecd1 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -82,6 +82,7 @@ enum attr_type
ATTR_CODE,
ATTR_COMMSTATUS,
ATTR_CONTEXTHANDLE,
+ ATTR_CONTRACT,
ATTR_CONTRACTVERSION,
ATTR_CONTROL,
ATTR_DECODE,
--
2.28.0

View File

@ -0,0 +1,173 @@
From 1a75069e45df24a09e8f364c61ad5d77115d48cd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 12 Oct 2020 20:34:28 +0200
Subject: [PATCH 09/28] widl: Support WinRT marshaling_behavior attribute
parsing.
---
tools/widl/header.c | 7 +++++++
tools/widl/parser.l | 4 ++++
tools/widl/parser.y | 18 ++++++++++++++++--
tools/widl/widltypes.h | 9 +++++++++
4 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 0fd3eb917ea..6d5987bd4c1 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -1494,6 +1494,13 @@ static void write_winrt_type_comments(FILE *header, const type_t *type)
fprintf(header, " * Introduced to %s in version %d.%d\n *\n", name, (ver >> 16) & 0xffff, ver & 0xffff);
free(name);
}
+ switch (get_attrv(type->attrs, ATTR_MARSHALING_BEHAVIOR))
+ {
+ case MARSHALING_AGILE: fprintf(header, " * Class Marshaling Behavior: Agile - Class is agile\n *\n"); break;
+ case MARSHALING_STANDARD: fprintf(header, " * Class Marshaling Behavior: Standard - Class marshals using the standard marshaler\n *\n"); break;
+ case MARSHALING_NONE: fprintf(header, " * Class Marshaling Behavior: None - Class cannot be marshaled\n *\n"); break;
+ default: break;
+ }
}
static void write_apicontract_guard_start(FILE *header, const expr_t *expr)
diff --git a/tools/widl/parser.l b/tools/widl/parser.l
index c3d0e9e2746..39a19a3c1de 100644
--- a/tools/widl/parser.l
+++ b/tools/widl/parser.l
@@ -320,6 +320,7 @@ static const struct keyword keywords[] = {
static const struct keyword attr_keywords[] =
{
{"aggregatable", tAGGREGATABLE, 0},
+ {"agile", tAGILE, 1},
{"allocate", tALLOCATE, 0},
{"annotation", tANNOTATION, 0},
{"apartment", tAPARTMENT, 0},
@@ -378,12 +379,14 @@ static const struct keyword attr_keywords[] =
{"length_is", tLENGTHIS, 0},
{"licensed", tLICENSED, 0},
{"local", tLOCAL, 0},
+ {"marshaling_behavior", tMARSHALINGBEHAVIOR, 1},
{"maybe", tMAYBE, 0},
{"message", tMESSAGE, 0},
{"neutral", tNEUTRAL, 0},
{"nocode", tNOCODE, 0},
{"nonbrowsable", tNONBROWSABLE, 0},
{"noncreatable", tNONCREATABLE, 0},
+ {"none", tNONE, 1},
{"nonextensible", tNONEXTENSIBLE, 0},
{"notify", tNOTIFY, 0},
{"notify_flag", tNOTIFYFLAG, 0},
@@ -412,6 +415,7 @@ static const struct keyword attr_keywords[] =
{"single", tSINGLE, 0},
{"size_is", tSIZEIS, 0},
{"source", tSOURCE, 0},
+ {"standard", tSTANDARD, 1},
{"strict_context_handle", tSTRICTCONTEXTHANDLE, 0},
{"string", tSTRING, 0},
{"switch_is", tSWITCHIS, 0},
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 28d7e16dad4..ebaa0fc514b 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -173,7 +173,9 @@ static typelib_t *current_typelib;
%token GREATEREQUAL LESSEQUAL
%token LOGICALOR LOGICALAND
%token ELLIPSIS
-%token tAGGREGATABLE tALLOCATE tANNOTATION
+%token tAGGREGATABLE
+%token tAGILE
+%token tALLOCATE tANNOTATION
%token tAPICONTRACT
%token tAPPOBJECT tASYNC tASYNCUUID
%token tAUTOHANDLE tBINDABLE tBOOLEAN tBROADCAST tBYTE tBYTECOUNT
@@ -214,12 +216,14 @@ static typelib_t *current_typelib;
%token tLENGTHIS tLIBRARY
%token tLICENSED tLOCAL
%token tLONG
+%token tMARSHALINGBEHAVIOR
%token tMAYBE tMESSAGE
%token tMETHODS
%token tMODULE
%token tNAMESPACE
%token tNOCODE tNONBROWSABLE
%token tNONCREATABLE
+%token tNONE
%token tNONEXTENSIBLE
%token tNOTIFY tNOTIFYFLAG
%token tNULL
@@ -245,6 +249,7 @@ static typelib_t *current_typelib;
%token tSIZEIS tSIZEOF
%token tSMALL
%token tSOURCE
+%token tSTANDARD
%token tSTATIC
%token tSTDCALL
%token tSTRICTCONTEXTHANDLE
@@ -297,7 +302,7 @@ static typelib_t *current_typelib;
%type <type> coclass coclasshdr coclassdef
%type <type> apicontract
%type <num> contract_ver
-%type <num> pointer_type threading_type version
+%type <num> pointer_type threading_type marshaling_behavior version
%type <str> libraryhdr callconv cppquote importlib import t_ident
%type <uuid> uuid_string
%type <import> import_start
@@ -502,6 +507,12 @@ str_list: aSTRING { $$ = append_str( NULL, $1 ); }
| str_list ',' aSTRING { $$ = append_str( $1, $3 ); }
;
+marshaling_behavior:
+ tAGILE { $$ = MARSHALING_AGILE; }
+ | tNONE { $$ = MARSHALING_NONE; }
+ | tSTANDARD { $$ = MARSHALING_STANDARD; }
+ ;
+
contract_ver:
aNUM { $$ = MAKEVERSION(0, $1); }
| aNUM '.' aNUM { $$ = MAKEVERSION($3, $1); }
@@ -568,6 +579,8 @@ attribute: { $$ = NULL; }
| tLCID { $$ = make_attr(ATTR_PARAMLCID); }
| tLICENSED { $$ = make_attr(ATTR_LICENSED); }
| tLOCAL { $$ = make_attr(ATTR_LOCAL); }
+ | tMARSHALINGBEHAVIOR '(' marshaling_behavior ')'
+ { $$ = make_attrv(ATTR_MARSHALING_BEHAVIOR, $3); }
| tMAYBE { $$ = make_attr(ATTR_MAYBE); }
| tMESSAGE { $$ = make_attr(ATTR_MESSAGE); }
| tNOCODE { $$ = make_attr(ATTR_NOCODE); }
@@ -2209,6 +2222,7 @@ struct allowed_attr allowed_attr[] =
/* ATTR_LIBLCID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "lcid" },
/* ATTR_LICENSED */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "licensed" },
/* ATTR_LOCAL */ { 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "local" },
+ /* ATTR_MARSHALING_BEHAVIOR */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "marshaling_behavior" },
/* ATTR_MAYBE */ { 0, 0, 0, 1, 0, 0, 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, 0, 0, "message" },
/* ATTR_NOCODE */ { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "nocode" },
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 3f358efecd1..62a018ab5a5 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -122,6 +122,7 @@ enum attr_type
ATTR_LIBLCID,
ATTR_LICENSED,
ATTR_LOCAL,
+ ATTR_MARSHALING_BEHAVIOR,
ATTR_MAYBE,
ATTR_MESSAGE,
ATTR_NOCODE,
@@ -268,6 +269,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,
--
2.28.0

View File

@ -0,0 +1,79 @@
From d2013864b6a28fabca3678172ab95b95ab2bb9af Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 13 Oct 2020 11:35:49 +0200
Subject: [PATCH 10/28] widl: Support WinRT mta threading attribute parsing.
---
tools/widl/header.c | 7 +++++++
tools/widl/parser.l | 1 +
tools/widl/parser.y | 2 ++
tools/widl/widltypes.h | 3 ++-
4 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 6d5987bd4c1..843aba214a4 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -1494,6 +1494,13 @@ static void write_winrt_type_comments(FILE *header, const type_t *type)
fprintf(header, " * Introduced to %s in version %d.%d\n *\n", name, (ver >> 16) & 0xffff, ver & 0xffff);
free(name);
}
+ switch (get_attrv(type->attrs, ATTR_THREADING))
+ {
+ case THREADING_SINGLE: fprintf(header, " * Class Threading Model: Single Threaded Apartment\n *\n"); break;
+ case THREADING_BOTH: fprintf(header, " * Class Threading Model: Both Single and Multi Threaded Apartment\n *\n"); break;
+ case THREADING_MTA: fprintf(header, " * Class Threading Model: Multi Threaded Apartment\n *\n"); break;
+ default: break;
+ }
switch (get_attrv(type->attrs, ATTR_MARSHALING_BEHAVIOR))
{
case MARSHALING_AGILE: fprintf(header, " * Class Marshaling Behavior: Agile - Class is agile\n *\n"); break;
diff --git a/tools/widl/parser.l b/tools/widl/parser.l
index 39a19a3c1de..c99feffb5d6 100644
--- a/tools/widl/parser.l
+++ b/tools/widl/parser.l
@@ -382,6 +382,7 @@ static const struct keyword attr_keywords[] =
{"marshaling_behavior", tMARSHALINGBEHAVIOR, 1},
{"maybe", tMAYBE, 0},
{"message", tMESSAGE, 0},
+ {"mta" , tMTA, 1},
{"neutral", tNEUTRAL, 0},
{"nocode", tNOCODE, 0},
{"nonbrowsable", tNONBROWSABLE, 0},
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index ebaa0fc514b..a4ad03ef037 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -220,6 +220,7 @@ static typelib_t *current_typelib;
%token tMAYBE tMESSAGE
%token tMETHODS
%token tMODULE
+%token tMTA
%token tNAMESPACE
%token tNOCODE tNONBROWSABLE
%token tNONCREATABLE
@@ -1150,6 +1151,7 @@ threading_type:
| tSINGLE { $$ = THREADING_SINGLE; }
| tFREE { $$ = THREADING_FREE; }
| tBOTH { $$ = THREADING_BOTH; }
+ | tMTA { $$ = THREADING_MTA; }
;
pointer_type:
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 62a018ab5a5..26634fa7f7d 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -266,7 +266,8 @@ enum threading_type
THREADING_NEUTRAL,
THREADING_SINGLE,
THREADING_FREE,
- THREADING_BOTH
+ THREADING_BOTH,
+ THREADING_MTA,
};
enum marshaling_type
--
2.28.0

View File

@ -0,0 +1,92 @@
From 1d70d60ab7af24ba47e98c00d4673347883f065b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 13 Oct 2020 00:11:08 +0200
Subject: [PATCH 11/28] widl: Support WinRT exclusiveto attribute parsing.
---
tools/widl/header.c | 7 +++++++
tools/widl/parser.l | 1 +
tools/widl/parser.y | 3 +++
tools/widl/widltypes.h | 1 +
4 files changed, 12 insertions(+)
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 843aba214a4..8aed9be3f57 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -1485,6 +1485,7 @@ static char *format_apicontract_macro(const type_t *type)
static void write_winrt_type_comments(FILE *header, const type_t *type)
{
expr_t *contract = get_attrp(type->attrs, ATTR_CONTRACT);
+ type_t *exclusiveto = get_attrp(type->attrs, ATTR_EXCLUSIVETO);
fprintf(header, " *\n");
if (contract)
{
@@ -1494,6 +1495,12 @@ static void write_winrt_type_comments(FILE *header, const type_t *type)
fprintf(header, " * Introduced to %s in version %d.%d\n *\n", name, (ver >> 16) & 0xffff, ver & 0xffff);
free(name);
}
+ if (exclusiveto)
+ {
+ char *name = format_namespace(exclusiveto->namespace, "", ".", exclusiveto->name, NULL);
+ fprintf(header, " * Interface is a part of the implementation of type %s\n *\n", name);
+ free(name);
+ }
switch (get_attrv(type->attrs, ATTR_THREADING))
{
case THREADING_SINGLE: fprintf(header, " * Class Threading Model: Single Threaded Apartment\n *\n"); break;
diff --git a/tools/widl/parser.l b/tools/widl/parser.l
index c99feffb5d6..498071a1992 100644
--- a/tools/widl/parser.l
+++ b/tools/widl/parser.l
@@ -355,6 +355,7 @@ static const struct keyword attr_keywords[] =
{"encode", tENCODE, 0},
{"endpoint", tENDPOINT, 0},
{"entry", tENTRY, 0},
+ {"exclusiveto", tEXCLUSIVETO, 1},
{"explicit_handle", tEXPLICITHANDLE, 0},
{"fault_status", tFAULTSTATUS, 0},
{"force_allocate", tFORCEALLOCATE, 0},
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index a4ad03ef037..88cc029c3ae 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -194,6 +194,7 @@ static typelib_t *current_typelib;
%token tDLLNAME tDOUBLE tDUAL
%token tENABLEALLOCATE tENCODE tENDPOINT
%token tENTRY tENUM tERRORSTATUST
+%token tEXCLUSIVETO
%token tEXPLICITHANDLE tEXTERN
%token tFALSE
%token tFASTCALL tFAULTSTATUS
@@ -557,6 +558,7 @@ attribute: { $$ = NULL; }
| tENCODE { $$ = make_attr(ATTR_ENCODE); }
| tENDPOINT '(' str_list ')' { $$ = make_attrp(ATTR_ENDPOINT, $3); }
| tENTRY '(' expr_const ')' { $$ = make_attrp(ATTR_ENTRY, $3); }
+ | tEXCLUSIVETO '(' decl_spec ')' { $$ = make_attrp(ATTR_EXCLUSIVETO, $3->type); }
| tEXPLICITHANDLE { $$ = make_attr(ATTR_EXPLICIT_HANDLE); }
| tFAULTSTATUS { $$ = make_attr(ATTR_FAULTSTATUS); }
| tFORCEALLOCATE { $$ = make_attr(ATTR_FORCEALLOCATE); }
@@ -2202,6 +2204,7 @@ struct allowed_attr allowed_attr[] =
/* ATTR_ENCODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 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, 0, 0, "endpoint" },
/* ATTR_ENTRY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "entry" },
+ /* ATTR_EXCLUSIVETO */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "exclusive_to" },
/* ATTR_EXPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 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, 0, 0, "fault_status" },
/* ATTR_FORCEALLOCATE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "force_allocate" },
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 26634fa7f7d..e945cad33b2 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -100,6 +100,7 @@ enum attr_type
ATTR_ENCODE,
ATTR_ENDPOINT,
ATTR_ENTRY,
+ ATTR_EXCLUSIVETO,
ATTR_EXPLICIT_HANDLE,
ATTR_FAULTSTATUS,
ATTR_FORCEALLOCATE,
--
2.28.0

View File

@ -0,0 +1,742 @@
From ef00d7d2e0178d9f3ad3405613c6c4a1ddd3c2b1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 13 Oct 2020 15:57:04 +0200
Subject: [PATCH 12/28] widl: Support WinRT runtimeclass type.
MIDL doesn't generate anything special in the header files for these
types. They can however be used instead of interfaces as function
arguments or type parameters, but pointer to their default interface
type is instead used in the generated code.
---
include/windows.media.speechsynthesis.idl | 25 ++
tools/widl/expr.c | 1 +
tools/widl/header.c | 65 +++++-
tools/widl/parser.l | 1 +
tools/widl/parser.y | 265 +++++++++++++---------
tools/widl/typegen.c | 4 +
tools/widl/typelib.c | 1 +
tools/widl/typetree.c | 17 ++
tools/widl/typetree.h | 24 ++
tools/widl/widltypes.h | 7 +
10 files changed, 298 insertions(+), 112 deletions(-)
diff --git a/include/windows.media.speechsynthesis.idl b/include/windows.media.speechsynthesis.idl
index 7a1de5fcba6..90bc9f279c6 100644
--- a/include/windows.media.speechsynthesis.idl
+++ b/include/windows.media.speechsynthesis.idl
@@ -29,6 +29,8 @@ namespace Windows {
typedef enum VoiceGender VoiceGender;
interface IInstalledVoicesStatic;
interface IVoiceInformation;
+ runtimeclass VoiceInformation;
+ runtimeclass SpeechSynthesizer;
}
}
}
@@ -42,6 +44,29 @@ namespace Windows {
Male = 0,
Female = 1
};
+
+ [
+ contract(Windows.Foundation.UniversalApiContract, 1.0),
+ exclusiveto(Windows.Media.SpeechSynthesis.VoiceInformation),
+ uuid(b127d6a4-1291-4604-aa9c-83134083352c)
+ ]
+ interface IVoiceInformation : IInspectable
+ {
+ [propget] HRESULT DisplayName([out] [retval] HSTRING* value);
+ [propget] HRESULT Id([out] [retval] HSTRING* value);
+ [propget] HRESULT Language([out] [retval] HSTRING* value);
+ [propget] HRESULT Description([out] [retval] HSTRING* value);
+ [propget] HRESULT Gender([out] [retval] VoiceGender* value);
+ }
+
+ [
+ contract(Windows.Foundation.UniversalApiContract, 1.0),
+ marshaling_behavior(agile)
+ ]
+ runtimeclass VoiceInformation
+ {
+ [default] interface IVoiceInformation;
+ }
}
}
}
diff --git a/tools/widl/expr.c b/tools/widl/expr.c
index be8311cfb7f..13bd5a889aa 100644
--- a/tools/widl/expr.c
+++ b/tools/widl/expr.c
@@ -463,6 +463,7 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type,
case TYPE_ARRAY:
case TYPE_BITFIELD:
case TYPE_APICONTRACT:
+ case TYPE_RUNTIMECLASS:
/* nothing to do */
break;
case TYPE_ALIAS:
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 8aed9be3f57..065a82ea384 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -465,6 +465,9 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i
case TYPE_COCLASS:
fprintf(h, "%s", name);
break;
+ case TYPE_RUNTIMECLASS:
+ fprintf(h, "%s", type_get_name(type_runtimeclass_get_default_iface(t), name_type));
+ break;
case TYPE_VOID:
fprintf(h, "void");
break;
@@ -547,6 +550,7 @@ void write_type_right(FILE *h, type_t *t, int is_field)
case TYPE_MODULE:
case TYPE_COCLASS:
case TYPE_INTERFACE:
+ case TYPE_RUNTIMECLASS:
break;
case TYPE_APICONTRACT:
/* not supposed to be here */
@@ -1033,7 +1037,8 @@ static int is_aggregate_return(const var_t *func)
{
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)
@@ -1501,6 +1506,21 @@ static void write_winrt_type_comments(FILE *header, const type_t *type)
fprintf(header, " * Interface is a part of the implementation of type %s\n *\n", name);
free(name);
}
+ if (type_get_type(type) == TYPE_RUNTIMECLASS)
+ {
+ ifref_list_t *ifaces = type_runtimeclass_get_ifaces(type);
+ ifref_t *entry;
+ fprintf(header, " * Class implements the following interfaces:\n");
+ LIST_FOR_EACH_ENTRY(entry, ifaces, ifref_t, entry)
+ {
+ char *name = format_namespace(entry->iface->namespace, "", ".", entry->iface->name, NULL);
+ fprintf(header, " * %s", name);
+ if (is_attr(entry->attrs, ATTR_DEFAULT)) fprintf(header, " ** Default Interface **");
+ fprintf(header, "\n");
+ free(name);
+ }
+ fprintf(header, " *\n");
+ }
switch (get_attrv(type->attrs, ATTR_THREADING))
{
case THREADING_SINGLE: fprintf(header, " * Class Threading Model: Single Threaded Apartment\n *\n"); break;
@@ -1728,6 +1748,45 @@ static void write_apicontract(FILE *header, type_t *apicontract)
free(name);
}
+static void write_runtimeclass(FILE *header, type_t *runtimeclass)
+{
+ expr_t *contract = get_attrp(runtimeclass->attrs, ATTR_CONTRACT);
+ size_t i, len;
+ char *name, *c_name;
+ 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);
+ write_winrt_type_comments(header, runtimeclass);
+ 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);
+ /* MIDL generates extern const here */
+ fprintf(header, "static 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 /* 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;
@@ -1792,6 +1851,8 @@ static void write_forward_decls(FILE *header, const statement_list_t *stmts)
}
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);
break;
case STMT_TYPEREF:
case STMT_IMPORTLIB:
@@ -1848,6 +1909,8 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons
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
{
write_type_definition(header, stmt->u.type, stmt->declonly);
diff --git a/tools/widl/parser.l b/tools/widl/parser.l
index 498071a1992..31b97951b31 100644
--- a/tools/widl/parser.l
+++ b/tools/widl/parser.l
@@ -298,6 +298,7 @@ static const struct keyword keywords[] = {
{"pascal", tPASCAL, 0},
{"properties", tPROPERTIES, 0},
{"register", tREGISTER, 0},
+ {"runtimeclass", tRUNTIMECLASS, 1},
{"short", tSHORT, 0},
{"signed", tSIGNED, 0},
{"sizeof", tSIZEOF, 0},
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 88cc029c3ae..8b88e031fb5 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -99,6 +99,7 @@ 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);
+static attr_list_t *check_runtimeclass_attrs(const char *name, attr_list_t *attrs);
static attr_list_t *check_apicontract_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);
@@ -245,6 +246,7 @@ static typelib_t *current_typelib;
%token tREQUESTEDIT
%token tRESTRICTED
%token tRETVAL
+%token tRUNTIMECLASS
%token tSAFEARRAY
%token tSHORT
%token tSIGNED
@@ -290,8 +292,8 @@ static typelib_t *current_typelib;
%type <type> base_type int_std
%type <type> enumdef structdef uniondef typedecl
%type <type> type qualified_seq qualified_type
-%type <ifref> coclass_int
-%type <ifref_list> coclass_ints
+%type <ifref> class_interface
+%type <ifref_list> class_interfaces
%type <var> arg ne_union_field union_field s_field case enum enum_member declaration
%type <var> funcdef
%type <var_list> m_args arg_list args dispint_meths
@@ -302,6 +304,7 @@ static typelib_t *current_typelib;
%type <declarator> m_abstract_declarator abstract_declarator abstract_declarator_no_direct abstract_direct_declarator
%type <declarator_list> declarator_list struct_declarator_list
%type <type> coclass coclasshdr coclassdef
+%type <type> runtimeclass runtimeclass_hdr runtimeclass_def
%type <type> apicontract
%type <num> contract_ver
%type <num> pointer_type threading_type marshaling_behavior version
@@ -361,6 +364,9 @@ gbl_statements: { $$ = NULL; }
}
| gbl_statements apicontract ';' { $$ = 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); }
@@ -377,6 +383,9 @@ imp_statements: { $$ = NULL; }
}
| imp_statements apicontract ';' { $$ = 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)); }
@@ -558,7 +567,9 @@ attribute: { $$ = NULL; }
| tENCODE { $$ = make_attr(ATTR_ENCODE); }
| tENDPOINT '(' str_list ')' { $$ = make_attrp(ATTR_ENDPOINT, $3); }
| tENTRY '(' expr_const ')' { $$ = make_attrp(ATTR_ENTRY, $3); }
- | tEXCLUSIVETO '(' decl_spec ')' { $$ = make_attrp(ATTR_EXCLUSIVETO, $3->type); }
+ | tEXCLUSIVETO '(' decl_spec ')' { if ($3->type->type_type != TYPE_RUNTIMECLASS)
+ error_loc("type %s is not a runtimeclass\n", $3->type->name);
+ $$ = make_attrp(ATTR_EXCLUSIVETO, $3->type); }
| tEXPLICITHANDLE { $$ = make_attr(ATTR_EXPLICIT_HANDLE); }
| tFAULTSTATUS { $$ = make_attr(ATTR_FAULTSTATUS); }
| tFORCEALLOCATE { $$ = make_attr(ATTR_FORCEALLOCATE); }
@@ -893,10 +904,29 @@ coclasshdr: attributes coclass { $$ = $2;
}
;
-coclassdef: coclasshdr '{' coclass_ints '}' semicolon_opt
+coclassdef: coclasshdr '{' class_interfaces '}' semicolon_opt
{ $$ = type_coclass_define($1, $3); }
;
+runtimeclass:
+ tRUNTIMECLASS aIDENTIFIER { $$ = type_new_runtimeclass($2, current_namespace); }
+ | tRUNTIMECLASS aKNOWNTYPE { $$ = find_type($2, NULL, 0);
+ if (type_get_type_detect_alias($$) != TYPE_RUNTIMECLASS)
+ error_loc("%s was not declared a runtimeclass at %s:%d\n", $2,
+ $$->loc_info.input_name, $$->loc_info.line_number);
+ }
+ ;
+
+runtimeclass_hdr: attributes runtimeclass { $$ = $2;
+ check_def($$);
+ $$->attrs = check_runtimeclass_attrs($2->name, $1);
+ }
+ ;
+
+runtimeclass_def: runtimeclass_hdr '{' class_interfaces '}' semicolon_opt
+ { $$ = type_runtimeclass_define($1, $3); }
+ ;
+
apicontract: attributes tAPICONTRACT aIDENTIFIER '{' '}'
{ $$ = get_type(TYPE_APICONTRACT, $3, current_namespace, 0);
check_def($$);
@@ -908,11 +938,11 @@ namespacedef: tNAMESPACE aIDENTIFIER { $$ = $2; }
| tNAMESPACE aNAMESPACE { $$ = $2; }
;
-coclass_ints: { $$ = NULL; }
- | coclass_ints coclass_int { $$ = append_ifref( $1, $2 ); }
+class_interfaces: { $$ = NULL; }
+ | class_interfaces class_interface { $$ = append_ifref( $1, $2 ); }
;
-coclass_int:
+class_interface:
m_attributes interfacedec { $$ = make_ifref($2); $$->attrs = $1; }
;
@@ -2166,115 +2196,116 @@ struct allowed_attr
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 I Fn ARG T En Enm St Un Fi L DI M C AC <display name> } */
- /* ATTR_AGGREGATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "aggregatable" },
- /* ATTR_ANNOTATION */ { 0, 0, 0, 0, 1, 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, 1, 0, "appobject" },
- /* ATTR_ASYNC */ { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "async" },
- /* ATTR_ASYNCUUID */ { 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "async_uuid" },
- /* ATTR_AUTO_HANDLE */ { 1, 1, 1, 0, 0, 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, 0, 0, "bindable" },
- /* ATTR_BROADCAST */ { 1, 0, 0, 1, 0, 0, 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, 0, 0, "call_as" },
- /* ATTR_CALLCONV */ { 0, 0, 0, 1, 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, 1, 0, 0, 0, 0, 0, "case" },
- /* ATTR_CODE */ { 0, 1, 1, 1, 0, 0, 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, 0, 0, "comm_status" },
- /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" },
- /* ATTR_CONTRACT */ { 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, "contract" },
- /* ATTR_CONTRACTVERSION */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "contractversion" },
- /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, "control" },
- /* ATTR_DECODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "decode" },
- /* ATTR_DEFAULT */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, "default" },
- /* ATTR_DEFAULTBIND */ { 0, 0, 0, 1, 0, 0, 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, 0, 0, "defaultcollelem" },
- /* ATTR_DEFAULTVALUE */ { 0, 0, 0, 0, 1, 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, 1, 0, "defaultvtable" },
- /* ATTR_DISABLECONSISTENCYCHECK */{ 0, 0, 0, 0, 1, 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, 0, 0, 0, NULL },
- /* ATTR_DISPLAYBIND */ { 0, 0, 0, 1, 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, 1, 0, 0, "dllname" },
- /* ATTR_DUAL */ { 0, 0, 1, 0, 0, 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, 0, 0, "enable_allocate" },
- /* ATTR_ENCODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 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, 0, 0, "endpoint" },
- /* ATTR_ENTRY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "entry" },
- /* ATTR_EXCLUSIVETO */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "exclusive_to" },
- /* ATTR_EXPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 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, 0, 0, "fault_status" },
- /* ATTR_FORCEALLOCATE */ { 0, 0, 0, 0, 1, 0, 0, 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, 0, 0, "handle" },
- /* ATTR_HELPCONTEXT */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "helpcontext" },
- /* ATTR_HELPFILE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "helpfile" },
- /* ATTR_HELPSTRING */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "helpstring" },
- /* ATTR_HELPSTRINGCONTEXT */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, "helpstringcontext" },
- /* ATTR_HELPSTRINGDLL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "helpstringdll" },
- /* ATTR_HIDDEN */ { 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, "hidden" },
- /* ATTR_ID */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, "id" },
- /* ATTR_IDEMPOTENT */ { 1, 0, 0, 1, 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, 1, 0, 0, 0, 0, 0, "ignore" },
- /* ATTR_IIDIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "iid_is" },
- /* ATTR_IMMEDIATEBIND */ { 0, 0, 0, 1, 0, 0, 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, 0, 0, "implicit_handle" },
- /* ATTR_IN */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" },
- /* ATTR_INPUTSYNC */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" },
- /* ATTR_LENGTHIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "length_is" },
- /* ATTR_LIBLCID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "lcid" },
- /* ATTR_LICENSED */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "licensed" },
- /* ATTR_LOCAL */ { 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "local" },
- /* ATTR_MARSHALING_BEHAVIOR */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "marshaling_behavior" },
- /* ATTR_MAYBE */ { 0, 0, 0, 1, 0, 0, 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, 0, 0, "message" },
- /* ATTR_NOCODE */ { 0, 1, 1, 1, 0, 0, 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, 0, 0, "nonbrowsable" },
- /* ATTR_NONCREATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "noncreatable" },
- /* ATTR_NONEXTENSIBLE */ { 0, 0, 1, 0, 0, 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, 0, 0, "notify" },
- /* ATTR_NOTIFYFLAG */ { 0, 0, 0, 1, 0, 0, 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, 0, 0, "object" },
- /* ATTR_ODL */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "odl" },
- /* ATTR_OLEAUTOMATION */ { 0, 0, 1, 0, 0, 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, 0, 0, "optimize" },
- /* ATTR_OPTIONAL */ { 0, 0, 0, 0, 1, 0, 0, 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, 0, 0, "out" },
- /* ATTR_PARAMLCID */ { 0, 0, 0, 0, 1, 0, 0, 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, 0, 0, "partial_ignore" },
- /* ATTR_POINTERDEFAULT */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "pointer_default" },
- /* ATTR_POINTERTYPE */ { 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 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, 1, 0, "progid" },
- /* ATTR_PROPGET */ { 0, 0, 0, 1, 0, 0, 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, 0, 0, "propput" },
- /* ATTR_PROPPUTREF */ { 0, 0, 0, 1, 0, 0, 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, 0, 0, "proxy" },
- /* ATTR_PUBLIC */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "public" },
- /* ATTR_RANGE */ { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, "range" },
- /* ATTR_READONLY */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "readonly" },
- /* ATTR_REPRESENTAS */ { 1, 0, 0, 0, 0, 1, 0, 0, 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, 0, 0, "requestedit" },
- /* ATTR_RESTRICTED */ { 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, "restricted" },
- /* ATTR_RETVAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "retval" },
- /* ATTR_SIZEIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "size_is" },
- /* ATTR_SOURCE */ { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "source" },
- /* ATTR_STRICTCONTEXTHANDLE */ { 0, 0, 1, 0, 0, 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, 0, 1, 0, 0, 0, 0, 0, "string" },
- /* ATTR_SWITCHIS */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "switch_is" },
- /* ATTR_SWITCHTYPE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "switch_type" },
- /* ATTR_THREADING */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "threading" },
- /* ATTR_TRANSMITAS */ { 1, 0, 0, 0, 0, 1, 0, 0, 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, 0, 0, "uidefault" },
- /* ATTR_USESGETLASTERROR */ { 0, 0, 0, 1, 0, 0, 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, 0, 0, "user_marshal" },
- /* ATTR_UUID */ { 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, "uuid" },
- /* ATTR_V1ENUM */ { 0, 0, 0, 0, 0, 1, 1, 0, 0, 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, 0, 0, "vararg" },
- /* ATTR_VERSION */ { 1, 0, 1, 0, 0, 1, 1, 0, 2, 0, 0, 1, 0, 0, 1, 0, "version" },
- /* ATTR_VIPROGID */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, "vi_progid" },
- /* ATTR_WIREMARSHAL */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "wire_marshal" },
+ /* attr { D ACF I Fn ARG T En Enm St Un Fi L DI M C AC R <display name> } */
+ /* ATTR_AGGREGATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "aggregatable" },
+ /* ATTR_ANNOTATION */ { 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, 1, 0, 0, "appobject" },
+ /* ATTR_ASYNC */ { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "async" },
+ /* ATTR_ASYNCUUID */ { 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "async_uuid" },
+ /* ATTR_AUTO_HANDLE */ { 1, 1, 1, 0, 0, 0, 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, 0, 0, 0, "bindable" },
+ /* ATTR_BROADCAST */ { 1, 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "call_as" },
+ /* ATTR_CALLCONV */ { 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, 1, 0, 0, 0, 0, 0, 0, "case" },
+ /* ATTR_CODE */ { 0, 1, 1, 1, 0, 0, 0, 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, 0, 0, 0, "comm_status" },
+ /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" },
+ /* ATTR_CONTRACT */ { 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, 1, 0, "contractversion" },
+ /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, "control" },
+ /* ATTR_DECODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "decode" },
+ /* ATTR_DEFAULT */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, "default" },
+ /* ATTR_DEFAULTBIND */ { 0, 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "defaultcollelem" },
+ /* ATTR_DEFAULTVALUE */ { 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, 1, 0, 0, "defaultvtable" },
+ /* ATTR_DISABLECONSISTENCYCHECK */{ 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, 0, 0, 0, 0, NULL },
+ /* ATTR_DISPLAYBIND */ { 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, 1, 0, 0, 0, "dllname" },
+ /* ATTR_DUAL */ { 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "enable_allocate" },
+ /* ATTR_ENCODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 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, 0, 0, 0, "endpoint" },
+ /* ATTR_ENTRY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "entry" },
+ /* ATTR_EXCLUSIVETO */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "exclusive_to" },
+ /* ATTR_EXPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 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, 0, 0, 0, "fault_status" },
+ /* ATTR_FORCEALLOCATE */ { 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "handle" },
+ /* ATTR_HELPCONTEXT */ { 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, 1, 0, 0, 0, 0, 0, "helpfile" },
+ /* ATTR_HELPSTRING */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "helpstring" },
+ /* ATTR_HELPSTRINGCONTEXT */ { 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, 1, 0, 0, 0, 0, 0, "helpstringdll" },
+ /* ATTR_HIDDEN */ { 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, "hidden" },
+ /* ATTR_ID */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, "id" },
+ /* ATTR_IDEMPOTENT */ { 1, 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, 1, 0, 0, 0, 0, 0, 0, "ignore" },
+ /* ATTR_IIDIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "iid_is" },
+ /* ATTR_IMMEDIATEBIND */ { 0, 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "implicit_handle" },
+ /* ATTR_IN */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" },
+ /* ATTR_INPUTSYNC */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" },
+ /* ATTR_LENGTHIS */ { 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, 1, 0, 0, 0, 0, 0, "lcid" },
+ /* ATTR_LICENSED */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "licensed" },
+ /* ATTR_LOCAL */ { 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "local" },
+ /* ATTR_MARSHALING_BEHAVIOR */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "marshaling_behavior" },
+ /* ATTR_MAYBE */ { 0, 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "message" },
+ /* ATTR_NOCODE */ { 0, 1, 1, 1, 0, 0, 0, 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, 0, 0, 0, "nonbrowsable" },
+ /* ATTR_NONCREATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "noncreatable" },
+ /* ATTR_NONEXTENSIBLE */ { 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "notify" },
+ /* ATTR_NOTIFYFLAG */ { 0, 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "object" },
+ /* ATTR_ODL */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "odl" },
+ /* ATTR_OLEAUTOMATION */ { 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "optimize" },
+ /* ATTR_OPTIONAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "out" },
+ /* ATTR_PARAMLCID */ { 0, 0, 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "partial_ignore" },
+ /* ATTR_POINTERDEFAULT */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "pointer_default" },
+ /* ATTR_POINTERTYPE */ { 1, 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, 1, 0, 0, "progid" },
+ /* ATTR_PROPGET */ { 0, 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "propput" },
+ /* ATTR_PROPPUTREF */ { 0, 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "proxy" },
+ /* ATTR_PUBLIC */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "public" },
+ /* ATTR_RANGE */ { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "range" },
+ /* ATTR_READONLY */ { 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, 1, 0, 0, 0, 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, 0, 0, 0, "requestedit" },
+ /* ATTR_RESTRICTED */ { 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, "restricted" },
+ /* ATTR_RETVAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "retval" },
+ /* ATTR_SIZEIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "size_is" },
+ /* ATTR_SOURCE */ { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "source" },
+ /* ATTR_STRICTCONTEXTHANDLE */ { 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, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "string" },
+ /* ATTR_SWITCHIS */ { 1, 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, 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, 1, 0, 1, "threading" },
+ /* ATTR_TRANSMITAS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "uidefault" },
+ /* ATTR_USESGETLASTERROR */ { 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "user_marshal" },
+ /* ATTR_UUID */ { 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, "uuid" },
+ /* ATTR_V1ENUM */ { 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 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, 0, 0, 0, "vararg" },
+ /* ATTR_VERSION */ { 1, 0, 1, 0, 0, 1, 1, 0, 2, 0, 0, 1, 0, 0, 1, 0, 1, "version" },
+ /* ATTR_VIPROGID */ { 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "wire_marshal" },
};
const char *get_attr_display_name(enum attr_type type)
@@ -2465,6 +2496,17 @@ static attr_list_t *check_coclass_attrs(const char *name, attr_list_t *attrs)
return attrs;
}
+static attr_list_t *check_runtimeclass_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_runtimeclass)
+ error_loc("inapplicable attribute %s for runtimeclass %s\n",
+ allowed_attr[attr->type].display_name, name);
+ return attrs;
+}
+
static attr_list_t *check_apicontract_attrs(const char *name, attr_list_t *attrs)
{
const attr_t *attr;
@@ -2514,6 +2556,7 @@ static int is_allowed_conf_type(const type_t *type)
case TYPE_FUNCTION:
case TYPE_INTERFACE:
case TYPE_BITFIELD:
+ case TYPE_RUNTIMECLASS:
return FALSE;
case TYPE_APICONTRACT:
/* not supposed to be here */
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index 46aae9b69e9..86c010aa6ae 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -353,6 +353,7 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att
return TGT_ENUM;
case TYPE_POINTER:
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_VOID && is_attr(attrs, ATTR_IIDIS)))
return TGT_IFACE_POINTER;
else if (is_aliaschain_attr(type_pointer_get_ref_type(type), ATTR_CONTEXTHANDLE))
@@ -373,6 +374,7 @@ 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:
break;
case TYPE_APICONTRACT:
/* not supposed to be here */
@@ -1971,6 +1973,7 @@ unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align)
case TYPE_FUNCTION:
case TYPE_BITFIELD:
case TYPE_APICONTRACT:
+ case TYPE_RUNTIMECLASS:
/* 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
@@ -2073,6 +2076,7 @@ static unsigned int type_buffer_alignment(const type_t *t)
case TYPE_FUNCTION:
case TYPE_BITFIELD:
case TYPE_APICONTRACT:
+ case TYPE_RUNTIMECLASS:
/* 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
diff --git a/tools/widl/typelib.c b/tools/widl/typelib.c
index faf76440f93..ace6424e3a0 100644
--- a/tools/widl/typelib.c
+++ b/tools/widl/typelib.c
@@ -218,6 +218,7 @@ unsigned short get_type_vt(type_t *t)
case TYPE_MODULE:
case TYPE_UNION:
case TYPE_ENCAPSULATED_UNION:
+ case TYPE_RUNTIMECLASS:
return VT_USERDEFINED;
case TYPE_VOID:
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index d8dcd5d80b0..d075619448d 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -211,6 +211,16 @@ type_t *type_new_coclass(char *name)
return type;
}
+type_t *type_new_runtimeclass(char *name, struct namespace *namespace)
+{
+ type_t *type = get_type(TYPE_RUNTIMECLASS, name, NULL, 0);
+ if (type->type_type != TYPE_RUNTIMECLASS || 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;
+ type->namespace = namespace;
+ return type;
+}
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)
@@ -505,6 +515,13 @@ type_t *type_coclass_define(type_t *coclass, ifref_list_t *ifaces)
return coclass;
}
+type_t *type_runtimeclass_define(type_t *runtimeclass, ifref_list_t *ifaces)
+{
+ runtimeclass->details.runtimeclass.ifaces = ifaces;
+ runtimeclass->defined = TRUE;
+ return runtimeclass;
+}
+
int type_is_equal(const type_t *type1, const type_t *type2)
{
if (type_get_type_detect_alias(type1) != type_get_type_detect_alias(type2))
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h
index 7abec41a8fd..951084cf875 100644
--- a/tools/widl/typetree.h
+++ b/tools/widl/typetree.h
@@ -44,11 +44,13 @@ type_t *type_new_struct(char *name, struct namespace *namespace, int defined, va
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_new_bitfield(type_t *field_type, const expr_t *bits);
+type_t *type_new_runtimeclass(char *name, struct namespace *namespace);
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_define(type_t *runtimeclass, ifref_list_t *ifaces);
int type_is_equal(const type_t *type1, const type_t *type2);
const char *type_get_name(const type_t *type, enum name_type name_type);
char *gen_name(void);
@@ -222,6 +224,7 @@ static inline int type_is_complete(const type_t *type)
case TYPE_POINTER:
case TYPE_ARRAY:
case TYPE_BITFIELD:
+ case TYPE_RUNTIMECLASS:
return TRUE;
case TYPE_APICONTRACT:
assert(0);
@@ -322,6 +325,27 @@ static inline ifref_list_t *type_coclass_get_ifaces(const type_t *type)
return type->details.coclass.ifaces;
}
+static inline ifref_list_t *type_runtimeclass_get_ifaces(const type_t *type)
+{
+ type = type_get_real_type(type);
+ assert(type_get_type(type) == TYPE_RUNTIMECLASS);
+ return type->details.runtimeclass.ifaces;
+}
+
+static inline type_t *type_runtimeclass_get_default_iface(const type_t *type)
+{
+ ifref_list_t *ifaces = type_runtimeclass_get_ifaces(type);
+ ifref_t *entry;
+ attr_t *attr;
+
+ LIST_FOR_EACH_ENTRY(entry, ifaces, ifref_t, entry)
+ LIST_FOR_EACH_ENTRY(attr, entry->attrs, attr_t, entry)
+ if (attr->type == ATTR_DEFAULT) return entry->iface;
+
+ assert(0);
+ return NULL;
+}
+
static inline const decl_spec_t *type_pointer_get_ref(const type_t *type)
{
type = type_get_real_type(type);
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index e945cad33b2..0a2088574d3 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -418,6 +418,11 @@ struct alias_details
struct _decl_spec_t aliasee;
};
+struct runtimeclass_details
+{
+ ifref_list_t *ifaces;
+};
+
#define HASHMAX 64
struct namespace {
@@ -445,6 +450,7 @@ enum type_type
TYPE_ARRAY,
TYPE_BITFIELD,
TYPE_APICONTRACT,
+ TYPE_RUNTIMECLASS,
};
struct _type_t {
@@ -465,6 +471,7 @@ struct _type_t {
struct pointer_details pointer;
struct bitfield_details bitfield;
struct alias_details alias;
+ struct runtimeclass_details runtimeclass;
} details;
const char *c_name;
unsigned int typestring_offset;
--
2.28.0

View File

@ -0,0 +1,95 @@
From 4f9ad72a4381348591151271107caea8a83cef84 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 1 Oct 2020 20:10:02 +0200
Subject: [PATCH 13/28] widl: Support WinRT eventadd/eventremove attributes.
---
tools/widl/header.c | 4 ++++
tools/widl/parser.l | 2 ++
tools/widl/parser.y | 7 +++++++
tools/widl/widltypes.h | 2 ++
4 files changed, 15 insertions(+)
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 065a82ea384..812becad63b 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -187,6 +187,10 @@ const char *get_name(const var_t *v)
{
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 ))
return buffer = strmake( "get_%s", v->name );
if (is_attr( v->attrs, ATTR_PROPPUT ))
diff --git a/tools/widl/parser.l b/tools/widl/parser.l
index 31b97951b31..02a6b47e225 100644
--- a/tools/widl/parser.l
+++ b/tools/widl/parser.l
@@ -356,6 +356,8 @@ static const struct keyword attr_keywords[] =
{"encode", tENCODE, 0},
{"endpoint", tENDPOINT, 0},
{"entry", tENTRY, 0},
+ {"eventadd", tEVENTADD, 1},
+ {"eventremove", tEVENTREMOVE, 1},
{"exclusiveto", tEXCLUSIVETO, 1},
{"explicit_handle", tEXPLICITHANDLE, 0},
{"fault_status", tFAULTSTATUS, 0},
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 8b88e031fb5..b1b3201042f 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -195,6 +195,7 @@ static typelib_t *current_typelib;
%token tDLLNAME tDOUBLE tDUAL
%token tENABLEALLOCATE tENCODE tENDPOINT
%token tENTRY tENUM tERRORSTATUST
+%token tEVENTADD tEVENTREMOVE
%token tEXCLUSIVETO
%token tEXPLICITHANDLE tEXTERN
%token tFALSE
@@ -567,6 +568,8 @@ attribute: { $$ = NULL; }
| tENCODE { $$ = make_attr(ATTR_ENCODE); }
| tENDPOINT '(' str_list ')' { $$ = make_attrp(ATTR_ENDPOINT, $3); }
| tENTRY '(' expr_const ')' { $$ = make_attrp(ATTR_ENTRY, $3); }
+ | tEVENTADD { $$ = make_attr(ATTR_EVENTADD); }
+ | tEVENTREMOVE { $$ = make_attr(ATTR_EVENTREMOVE); }
| tEXCLUSIVETO '(' decl_spec ')' { if ($3->type->type_type != TYPE_RUNTIMECLASS)
error_loc("type %s is not a runtimeclass\n", $3->type->name);
$$ = make_attrp(ATTR_EXCLUSIVETO, $3->type); }
@@ -2235,6 +2238,8 @@ struct allowed_attr allowed_attr[] =
/* ATTR_ENCODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 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, 0, 0, 0, "endpoint" },
/* ATTR_ENTRY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "entry" },
+ /* ATTR_EVENTADD */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "eventadd" },
+ /* ATTR_EVENTREMOVE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "eventremove" },
/* ATTR_EXCLUSIVETO */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "exclusive_to" },
/* ATTR_EXPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 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, 0, 0, 0, "fault_status" },
@@ -2884,6 +2889,8 @@ static void check_functions(const type_t *iface, int is_inside_library)
{
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;
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 0a2088574d3..da70a8f97d5 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -100,6 +100,8 @@ enum attr_type
ATTR_ENCODE,
ATTR_ENDPOINT,
ATTR_ENTRY,
+ ATTR_EVENTADD,
+ ATTR_EVENTREMOVE,
ATTR_EXCLUSIVETO,
ATTR_EXPLICIT_HANDLE,
ATTR_FAULTSTATUS,
--
2.28.0

View File

@ -0,0 +1,66 @@
From c64bd2a13a6ec07122d08bc81d4933b38eec5edf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 12 Oct 2020 18:02:59 +0200
Subject: [PATCH 14/28] widl: Support WinRT flags attribute parsing.
---
tools/widl/parser.l | 1 +
tools/widl/parser.y | 3 +++
tools/widl/widltypes.h | 1 +
3 files changed, 5 insertions(+)
diff --git a/tools/widl/parser.l b/tools/widl/parser.l
index 02a6b47e225..f5a57db4797 100644
--- a/tools/widl/parser.l
+++ b/tools/widl/parser.l
@@ -361,6 +361,7 @@ static const struct keyword attr_keywords[] =
{"exclusiveto", tEXCLUSIVETO, 1},
{"explicit_handle", tEXPLICITHANDLE, 0},
{"fault_status", tFAULTSTATUS, 0},
+ {"flags", tFLAGS, 1},
{"force_allocate", tFORCEALLOCATE, 0},
{"free", tFREE, 0},
{"handle", tHANDLE, 0},
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index b1b3201042f..131226ba7be 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -200,6 +200,7 @@ static typelib_t *current_typelib;
%token tEXPLICITHANDLE tEXTERN
%token tFALSE
%token tFASTCALL tFAULTSTATUS
+%token tFLAGS
%token tFLOAT tFORCEALLOCATE
%token tHANDLE
%token tHANDLET
@@ -575,6 +576,7 @@ attribute: { $$ = NULL; }
$$ = make_attrp(ATTR_EXCLUSIVETO, $3->type); }
| tEXPLICITHANDLE { $$ = make_attr(ATTR_EXPLICIT_HANDLE); }
| tFAULTSTATUS { $$ = make_attr(ATTR_FAULTSTATUS); }
+ | tFLAGS { $$ = make_attr(ATTR_FLAGS); }
| tFORCEALLOCATE { $$ = make_attr(ATTR_FORCEALLOCATE); }
| tHANDLE { $$ = make_attr(ATTR_HANDLE); }
| tHELPCONTEXT '(' expr_int_const ')' { $$ = make_attrp(ATTR_HELPCONTEXT, $3); }
@@ -2243,6 +2245,7 @@ struct allowed_attr allowed_attr[] =
/* ATTR_EXCLUSIVETO */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "exclusive_to" },
/* ATTR_EXPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 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, 0, 0, 0, "fault_status" },
+ /* ATTR_FLAGS */ { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "flags" },
/* ATTR_FORCEALLOCATE */ { 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "handle" },
/* ATTR_HELPCONTEXT */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "helpcontext" },
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index da70a8f97d5..0bf7b644fff 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -105,6 +105,7 @@ enum attr_type
ATTR_EXCLUSIVETO,
ATTR_EXPLICIT_HANDLE,
ATTR_FAULTSTATUS,
+ ATTR_FLAGS,
ATTR_FORCEALLOCATE,
ATTR_HANDLE,
ATTR_HELPCONTEXT,
--
2.28.0

View File

@ -0,0 +1,156 @@
From 65fefdad1ecb8bc45a89bee1393acf2cfcbb63b8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Fri, 25 Sep 2020 17:13:47 +0200
Subject: [PATCH 15/28] widl: Support using qualified names for interfaces.
And make qualified name lookup more robust, only looking for types in
the lookup namespace if it's active.
---
include/windows.media.speechsynthesis.idl | 2 +-
tools/widl/parser.y | 58 +++++++++++++++--------
2 files changed, 38 insertions(+), 22 deletions(-)
diff --git a/include/windows.media.speechsynthesis.idl b/include/windows.media.speechsynthesis.idl
index 90bc9f279c6..89fe616b9b3 100644
--- a/include/windows.media.speechsynthesis.idl
+++ b/include/windows.media.speechsynthesis.idl
@@ -65,7 +65,7 @@ namespace Windows {
]
runtimeclass VoiceInformation
{
- [default] interface IVoiceInformation;
+ [default] interface Windows.Media.SpeechSynthesis.IVoiceInformation;
}
}
}
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 131226ba7be..8e79ce3660f 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -74,6 +74,8 @@ static void append_chain_callconv(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 *get_qualified_type(enum type_type type, char *name, int t);
+static type_t *find_qualified_type_or_error(const char *name, int t);
static type_t *find_type_or_error(const char *name, int t);
static type_t *find_type_or_error2(char *name, int t);
@@ -81,7 +83,6 @@ static var_t *reg_const(var_t *var);
static void push_namespace(const char *name);
static void pop_namespace(const char *name);
-static void init_lookup_namespace(const char *name);
static void push_lookup_namespace(const char *name);
static void check_arg_attrs(const var_t *arg);
@@ -293,7 +294,7 @@ static typelib_t *current_typelib;
%type <str> namespacedef
%type <type> base_type int_std
%type <type> enumdef structdef uniondef typedecl
-%type <type> type qualified_seq qualified_type
+%type <type> type qualified_type
%type <ifref> class_interface
%type <ifref_list> class_interfaces
%type <var> arg ne_union_field union_field s_field case enum enum_member declaration
@@ -884,15 +885,15 @@ int_std: tINT { $$ = type_new_int(TYPE_BASIC_INT, 0); }
| tINT3264 { $$ = type_new_int(TYPE_BASIC_INT3264, 0); }
;
-qualified_seq:
- aKNOWNTYPE { $$ = find_type_or_error($1, 0); }
- | aIDENTIFIER '.' { push_lookup_namespace($1); } qualified_seq { $$ = $4; }
- ;
+namespace_pfx:
+ aNAMESPACE '.' { push_lookup_namespace($1); }
+ | namespace_pfx aNAMESPACE '.' { push_lookup_namespace($2); }
+ ;
qualified_type:
- aKNOWNTYPE { $$ = find_type_or_error($1, 0); }
- | aNAMESPACE '.' { init_lookup_namespace($1); } qualified_seq { $$ = $4; }
- ;
+ aKNOWNTYPE { $$ = find_type_or_error($1, 0); }
+ | namespace_pfx aKNOWNTYPE { $$ = find_qualified_type_or_error($2, 0); }
+ ;
coclass: tCOCLASS aIDENTIFIER { $$ = type_new_coclass($2); }
| tCOCLASS aKNOWNTYPE { $$ = find_type($2, NULL, 0);
@@ -990,6 +991,8 @@ inherit: { $$ = NULL; }
interface: tINTERFACE aIDENTIFIER { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); }
| tINTERFACE aKNOWNTYPE { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); }
+ | tINTERFACE namespace_pfx aIDENTIFIER { $$ = get_qualified_type(TYPE_INTERFACE, $3, 0); }
+ | tINTERFACE namespace_pfx aKNOWNTYPE { $$ = get_qualified_type(TYPE_INTERFACE, $3, 0); }
;
interfacehdr: attributes interface { $$ = $2;
@@ -1953,12 +1956,6 @@ static void pop_namespace(const char *name)
current_namespace = current_namespace->parent;
}
-static void init_lookup_namespace(const char *name)
-{
- if (!(lookup_namespace = find_sub_namespace(&global_namespace, name)))
- error_loc("namespace '%s' not found\n", name);
-}
-
static void push_lookup_namespace(const char *name)
{
struct namespace *namespace;
@@ -2076,11 +2073,29 @@ type_t *find_type(const char *name, struct namespace *namespace, int t)
return NULL;
}
+static type_t *get_qualified_type(enum type_type type_type, char *name, int t)
+{
+ type_t *type = get_type(type_type, name, lookup_namespace, t);
+ lookup_namespace = &global_namespace;
+ return type;
+}
+
+static type_t *find_qualified_type_or_error(const char *name, int t)
+{
+ type_t *type;
+ if (!(type = find_type(name, lookup_namespace, t)))
+ {
+ error_loc("type '%s' not found\n", name);
+ return NULL;
+ }
+ lookup_namespace = &global_namespace;
+ return type;
+}
+
static type_t *find_type_or_error(const char *name, int t)
{
type_t *type;
- if (!(type = find_type(name, current_namespace, t)) &&
- !(type = find_type(name, lookup_namespace, t)))
+ if (!(type = find_type(name, current_namespace, t)))
{
error_loc("type '%s' not found\n", name);
return NULL;
@@ -2097,15 +2112,16 @@ static type_t *find_type_or_error2(char *name, int t)
int is_type(const char *name)
{
- return find_type(name, current_namespace, 0) != NULL ||
- find_type(name, lookup_namespace, 0) != NULL;
+ if (lookup_namespace != &global_namespace)
+ return find_type(name, lookup_namespace, 0) != NULL;
+ else
+ return find_type(name, current_namespace, 0) != NULL;
}
int is_namespace(const char *name)
{
if (!winrt_mode) return 0;
- return find_sub_namespace(current_namespace, name) != NULL ||
- find_sub_namespace(&global_namespace, name) != NULL;
+ return find_sub_namespace(lookup_namespace, name) != NULL;
}
type_t *get_type(enum type_type type, char *name, struct namespace *namespace, int t)
--
2.28.0

View File

@ -0,0 +1,297 @@
From 734f1257696ef221883e92d23f653dc7188b1fcd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 13 Oct 2020 13:52:34 +0200
Subject: [PATCH 16/28] widl: Support repeated attributes for WinRT static.
---
tools/widl/parser.y | 258 ++++++++++++++++++++++----------------------
1 file changed, 130 insertions(+), 128 deletions(-)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 8e79ce3660f..1727b5bb396 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -1310,27 +1310,6 @@ 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;
@@ -2203,6 +2182,8 @@ 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;
@@ -2223,115 +2204,136 @@ struct allowed_attr
struct allowed_attr allowed_attr[] =
{
- /* attr { D ACF I Fn ARG T En Enm St Un Fi L DI M C AC R <display name> } */
- /* ATTR_AGGREGATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "aggregatable" },
- /* ATTR_ANNOTATION */ { 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, 1, 0, 0, "appobject" },
- /* ATTR_ASYNC */ { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "async" },
- /* ATTR_ASYNCUUID */ { 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "async_uuid" },
- /* ATTR_AUTO_HANDLE */ { 1, 1, 1, 0, 0, 0, 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, 0, 0, 0, "bindable" },
- /* ATTR_BROADCAST */ { 1, 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "call_as" },
- /* ATTR_CALLCONV */ { 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, 1, 0, 0, 0, 0, 0, 0, "case" },
- /* ATTR_CODE */ { 0, 1, 1, 1, 0, 0, 0, 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, 0, 0, 0, "comm_status" },
- /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" },
- /* ATTR_CONTRACT */ { 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, 1, 0, "contractversion" },
- /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, "control" },
- /* ATTR_DECODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "decode" },
- /* ATTR_DEFAULT */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, "default" },
- /* ATTR_DEFAULTBIND */ { 0, 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "defaultcollelem" },
- /* ATTR_DEFAULTVALUE */ { 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, 1, 0, 0, "defaultvtable" },
- /* ATTR_DISABLECONSISTENCYCHECK */{ 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, 0, 0, 0, 0, NULL },
- /* ATTR_DISPLAYBIND */ { 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, 1, 0, 0, 0, "dllname" },
- /* ATTR_DUAL */ { 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "enable_allocate" },
- /* ATTR_ENCODE */ { 0, 0, 1, 1, 0, 1, 0, 0, 0, 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, 0, 0, 0, "endpoint" },
- /* ATTR_ENTRY */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "entry" },
- /* ATTR_EVENTADD */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "eventadd" },
- /* ATTR_EVENTREMOVE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "eventremove" },
- /* ATTR_EXCLUSIVETO */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "exclusive_to" },
- /* ATTR_EXPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 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, 0, 0, 0, "fault_status" },
- /* ATTR_FLAGS */ { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "flags" },
- /* ATTR_FORCEALLOCATE */ { 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "handle" },
- /* ATTR_HELPCONTEXT */ { 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, 1, 0, 0, 0, 0, 0, "helpfile" },
- /* ATTR_HELPSTRING */ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, "helpstring" },
- /* ATTR_HELPSTRINGCONTEXT */ { 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, 1, 0, 0, 0, 0, 0, "helpstringdll" },
- /* ATTR_HIDDEN */ { 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, "hidden" },
- /* ATTR_ID */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, "id" },
- /* ATTR_IDEMPOTENT */ { 1, 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, 1, 0, 0, 0, 0, 0, 0, "ignore" },
- /* ATTR_IIDIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "iid_is" },
- /* ATTR_IMMEDIATEBIND */ { 0, 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "implicit_handle" },
- /* ATTR_IN */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" },
- /* ATTR_INPUTSYNC */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" },
- /* ATTR_LENGTHIS */ { 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, 1, 0, 0, 0, 0, 0, "lcid" },
- /* ATTR_LICENSED */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "licensed" },
- /* ATTR_LOCAL */ { 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "local" },
- /* ATTR_MARSHALING_BEHAVIOR */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "marshaling_behavior" },
- /* ATTR_MAYBE */ { 0, 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "message" },
- /* ATTR_NOCODE */ { 0, 1, 1, 1, 0, 0, 0, 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, 0, 0, 0, "nonbrowsable" },
- /* ATTR_NONCREATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "noncreatable" },
- /* ATTR_NONEXTENSIBLE */ { 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "notify" },
- /* ATTR_NOTIFYFLAG */ { 0, 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "object" },
- /* ATTR_ODL */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "odl" },
- /* ATTR_OLEAUTOMATION */ { 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "optimize" },
- /* ATTR_OPTIONAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "out" },
- /* ATTR_PARAMLCID */ { 0, 0, 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "partial_ignore" },
- /* ATTR_POINTERDEFAULT */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "pointer_default" },
- /* ATTR_POINTERTYPE */ { 1, 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, 1, 0, 0, "progid" },
- /* ATTR_PROPGET */ { 0, 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "propput" },
- /* ATTR_PROPPUTREF */ { 0, 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "proxy" },
- /* ATTR_PUBLIC */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "public" },
- /* ATTR_RANGE */ { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "range" },
- /* ATTR_READONLY */ { 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, 1, 0, 0, 0, 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, 0, 0, 0, "requestedit" },
- /* ATTR_RESTRICTED */ { 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, "restricted" },
- /* ATTR_RETVAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "retval" },
- /* ATTR_SIZEIS */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "size_is" },
- /* ATTR_SOURCE */ { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "source" },
- /* ATTR_STRICTCONTEXTHANDLE */ { 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, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "string" },
- /* ATTR_SWITCHIS */ { 1, 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, 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, 1, 0, 1, "threading" },
- /* ATTR_TRANSMITAS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 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, 0, 0, 0, "uidefault" },
- /* ATTR_USESGETLASTERROR */ { 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "user_marshal" },
- /* ATTR_UUID */ { 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, "uuid" },
- /* ATTR_V1ENUM */ { 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 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, 0, 0, 0, "vararg" },
- /* ATTR_VERSION */ { 1, 0, 1, 0, 0, 1, 1, 0, 2, 0, 0, 1, 0, 0, 1, 0, 1, "version" },
- /* ATTR_VIPROGID */ { 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "wire_marshal" },
+ /* attr { D ACF M I Fn ARG T En Enm St Un Fi L DI M C AC R <display name> } */
+ /* ATTR_AGGREGATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "aggregatable" },
+ /* 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_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_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_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_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, 0, 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, 0, 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_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_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_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, 0, 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 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 && !allowed_attr[attr->type].multiple)
+ {
+ 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;
+}
+
const char *get_attr_display_name(enum attr_type type)
{
return allowed_attr[type].display_name;
--
2.28.0

View File

@ -0,0 +1,134 @@
From ca0364f1bd90bb35821c6ffb620e502f2b4afb7a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 13 Oct 2020 14:30:32 +0200
Subject: [PATCH 17/28] widl: Support WinRT static attribute parsing.
---
tools/widl/header.c | 30 ++++++++++++++++++++++++++++++
tools/widl/parser.l | 1 +
tools/widl/parser.y | 8 ++++++++
tools/widl/widltypes.h | 1 +
4 files changed, 40 insertions(+)
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 812becad63b..3bc6b452177 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -109,6 +109,17 @@ int is_attr(const attr_list_t *list, enum attr_type t)
return 0;
}
+static void get_attr_statics(const attr_list_t *attrs, expr_list_t *list)
+{
+ const attr_t *attr;
+ if (!attrs) return;
+ LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry )
+ {
+ if (attr->type != ATTR_STATIC) continue;
+ list_add_tail(list, &((expr_t *)attr->u.pval)->entry);
+ }
+}
+
void *get_attrp(const attr_list_t *list, enum attr_type t)
{
const attr_t *attr;
@@ -1495,6 +1506,8 @@ static void write_winrt_type_comments(FILE *header, const type_t *type)
{
expr_t *contract = get_attrp(type->attrs, ATTR_CONTRACT);
type_t *exclusiveto = get_attrp(type->attrs, ATTR_EXCLUSIVETO);
+ expr_list_t statics = LIST_INIT(statics);
+ get_attr_statics(type->attrs, &statics);
fprintf(header, " *\n");
if (contract)
{
@@ -1510,6 +1523,23 @@ static void write_winrt_type_comments(FILE *header, const type_t *type)
fprintf(header, " * Interface is a part of the implementation of type %s\n *\n", name);
free(name);
}
+ if (!list_empty(&statics))
+ {
+ expr_t *expr;
+ fprintf(header, " * RuntimeClass contains static methods.\n");
+ LIST_FOR_EACH_ENTRY(expr, &statics, expr_t, entry)
+ {
+ const type_t *iface = expr->u.tref.type, *apicontract = expr->ref->u.tref.type;
+ int version_req = expr->ref->ref->u.lval;
+ char *iface_name = format_namespace(iface->namespace, "", ".", iface->name, NULL);
+ char *name = format_namespace(apicontract->namespace, "", ".", apicontract->name, NULL);
+ fprintf(header, " * Static Methods exist on the %s interface starting with version %d.%d of the %s API contract\n",
+ iface_name, (version_req >> 16) & 0xffff, version_req & 0xffff, name);
+ free(iface_name);
+ free(name);
+ }
+ fprintf(header, " *\n");
+ }
if (type_get_type(type) == TYPE_RUNTIMECLASS)
{
ifref_list_t *ifaces = type_runtimeclass_get_ifaces(type);
diff --git a/tools/widl/parser.l b/tools/widl/parser.l
index f5a57db4797..90791543db2 100644
--- a/tools/widl/parser.l
+++ b/tools/widl/parser.l
@@ -422,6 +422,7 @@ static const struct keyword attr_keywords[] =
{"size_is", tSIZEIS, 0},
{"source", tSOURCE, 0},
{"standard", tSTANDARD, 1},
+ {"static", tSTATIC, 1},
{"strict_context_handle", tSTRICTCONTEXTHANDLE, 0},
{"string", tSTRING, 0},
{"switch_is", tSWITCHIS, 0},
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 1727b5bb396..e6e67826a8f 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -283,6 +283,7 @@ static typelib_t *current_typelib;
%type <expr> m_expr expr expr_const expr_int_const array m_bitfield
%type <expr_list> m_exprs /* exprs expr_list */ expr_list_int_const
%type <expr> contract_req
+%type <expr> static_attr
%type <type> interfacehdr
%type <stgclass> storage_cls_spec
%type <type_qualifier> type_qualifier m_type_qual_list
@@ -538,6 +539,11 @@ contract_req: decl_spec ',' contract_ver { if ($1->type->type_type != TYPE_APICO
$$ = make_exprt(EXPR_GTREQL, declare_var(NULL, $1, make_declarator(NULL), 0), $$);
}
+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);
+ }
+
attribute: { $$ = NULL; }
| tAGGREGATABLE { $$ = make_attr(ATTR_AGGREGATABLE); }
| tANNOTATION '(' aSTRING ')' { $$ = make_attrp(ATTR_ANNOTATION, $3); }
@@ -634,6 +640,7 @@ attribute: { $$ = NULL; }
| tRETVAL { $$ = make_attr(ATTR_RETVAL); }
| tSIZEIS '(' m_exprs ')' { $$ = make_attrp(ATTR_SIZEIS, $3); }
| tSOURCE { $$ = make_attr(ATTR_SOURCE); }
+ | tSTATIC '(' static_attr ')' { $$ = make_attrp(ATTR_STATIC, $3); }
| tSTRICTCONTEXTHANDLE { $$ = make_attr(ATTR_STRICTCONTEXTHANDLE); }
| tSTRING { $$ = make_attr(ATTR_STRING); }
| tSWITCHIS '(' expr ')' { $$ = make_attrp(ATTR_SWITCHIS, $3); }
@@ -2296,6 +2303,7 @@ struct allowed_attr allowed_attr[] =
/* 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" },
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 0bf7b644fff..aa3e6e75898 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -159,6 +159,7 @@ enum attr_type
ATTR_RETVAL,
ATTR_SIZEIS,
ATTR_SOURCE,
+ ATTR_STATIC,
ATTR_STRICTCONTEXTHANDLE,
ATTR_STRING,
ATTR_SWITCHIS,
--
2.28.0

View File

@ -0,0 +1,254 @@
From 0d3503123e3f0cb458ada24b052e1d39f1c4dddb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 13 Oct 2020 00:31:57 +0200
Subject: [PATCH 18/28] widl: Support WinRT requires keyword.
---
tools/widl/header.c | 13 +++++++++++
tools/widl/parser.l | 1 +
tools/widl/parser.y | 49 ++++++++++++++++++++++++++++++++----------
tools/widl/typetree.c | 5 ++++-
tools/widl/typetree.h | 9 +++++++-
tools/widl/widltypes.h | 1 +
6 files changed, 65 insertions(+), 13 deletions(-)
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 3bc6b452177..5dfc5e2ff8c 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -1506,6 +1506,7 @@ static void write_winrt_type_comments(FILE *header, const type_t *type)
{
expr_t *contract = get_attrp(type->attrs, ATTR_CONTRACT);
type_t *exclusiveto = get_attrp(type->attrs, ATTR_EXCLUSIVETO);
+ type_list_t *requires = type->type_type == TYPE_INTERFACE ? type_iface_get_requires(type) : NULL;
expr_list_t statics = LIST_INIT(statics);
get_attr_statics(type->attrs, &statics);
fprintf(header, " *\n");
@@ -1523,6 +1524,18 @@ static void write_winrt_type_comments(FILE *header, const type_t *type)
fprintf(header, " * Interface is a part of the implementation of type %s\n *\n", name);
free(name);
}
+ if (requires)
+ {
+ type_list_t *req;
+ fprintf(header, " * Any object which implements this interface must also implement the following interfaces:\n");
+ for (req = requires; req; req = req->next)
+ {
+ char *name = format_namespace(req->type->namespace, "", ".", req->type->name, NULL);
+ fprintf(header, " * %s\n", name);
+ free(name);
+ }
+ fprintf(header, " *\n");
+ }
if (!list_empty(&statics))
{
expr_t *expr;
diff --git a/tools/widl/parser.l b/tools/widl/parser.l
index 90791543db2..2b41bea1bc9 100644
--- a/tools/widl/parser.l
+++ b/tools/widl/parser.l
@@ -298,6 +298,7 @@ static const struct keyword keywords[] = {
{"pascal", tPASCAL, 0},
{"properties", tPROPERTIES, 0},
{"register", tREGISTER, 0},
+ {"requires", tREQUIRES, 1},
{"runtimeclass", tRUNTIMECLASS, 1},
{"short", tSHORT, 0},
{"signed", tSIGNED, 0},
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index e6e67826a8f..1da667e0ced 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -38,12 +38,6 @@
#include "expr.h"
#include "typetree.h"
-typedef struct list typelist_t;
-struct typenode {
- type_t *type;
- struct list entry;
-};
-
struct _import_t
{
char *name;
@@ -51,6 +45,8 @@ struct _import_t
};
static str_list_t *append_str(str_list_t *list, char *str);
+static type_list_t *append_type(type_list_t *list, type_t *type);
+static type_list_t *append_types(type_list_t *list, type_list_t *types);
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,
@@ -140,6 +136,7 @@ static typelib_t *current_typelib;
expr_t *expr;
expr_list_t *expr_list;
type_t *type;
+ type_list_t *typelist;
var_t *var;
var_list_t *var_list;
declarator_t *declarator;
@@ -247,6 +244,7 @@ static typelib_t *current_typelib;
%token tREADONLY tREF
%token tREGISTER tREPRESENTAS
%token tREQUESTEDIT
+%token tREQUIRES
%token tRESTRICTED
%token tRETVAL
%token tRUNTIMECLASS
@@ -296,6 +294,7 @@ static typelib_t *current_typelib;
%type <type> base_type int_std
%type <type> enumdef structdef uniondef typedecl
%type <type> type qualified_type
+%type <typelist> requires required_types
%type <ifref> class_interface
%type <ifref_list> class_interfaces
%type <var> arg ne_union_field union_field s_field case enum enum_member declaration
@@ -1009,19 +1008,27 @@ interfacehdr: attributes interface { $$ = $2;
}
;
-interfacedef: interfacehdr inherit
+required_types:
+ qualified_type { $$ = append_type(NULL, $1); }
+ | required_types ',' required_types { $$ = append_types($1, $3); }
+
+requires: { $$ = NULL; }
+ | tREQUIRES required_types { $$ = $2; }
+ ;
+
+interfacedef: interfacehdr inherit requires
'{' int_statements '}' semicolon_opt { $$ = $1;
if($$ == $2)
error_loc("Interface can't inherit from itself\n");
- type_interface_define($$, $2, $4);
+ type_interface_define($$, $2, $5, $3);
check_async_uuid($$);
}
/* 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
+ | interfacehdr ':' aIDENTIFIER requires
'{' import int_statements '}'
semicolon_opt { $$ = $1;
- type_interface_define($$, find_type_or_error2($3, 0), $6);
+ type_interface_define($$, find_type_or_error2($3, 0), $7, $4);
}
| dispinterfacedef semicolon_opt { $$ = $1; }
;
@@ -1317,6 +1324,26 @@ static str_list_t *append_str(str_list_t *list, char *str)
return list;
}
+static type_list_t *append_type(type_list_t *list, type_t *type)
+{
+ type_list_t *entry;
+ if (!type) return list;
+ entry = xmalloc( sizeof(*entry) );
+ entry->type = type;
+ entry->next = list;
+ return entry;
+}
+
+static type_list_t *append_types(type_list_t *list, type_list_t *types)
+{
+ type_list_t *entry;
+ if (!list) return types;
+ if (!types) return list;
+ for (entry = list; entry->next; entry = entry->next) {}
+ entry->next = types;
+ return list;
+}
+
static attr_list_t *move_attr(attr_list_t *dst, attr_list_t *src, enum attr_type type)
{
attr_t *attr;
@@ -3015,7 +3042,7 @@ static void check_async_uuid(type_t *iface)
stmts = append_statement(stmts, make_statement_declaration(finish_func));
}
- type_interface_define(async_iface, inherit, stmts);
+ type_interface_define(async_iface, inherit, stmts, NULL);
iface->details.iface->async_iface = async_iface->details.iface->async_iface = async_iface;
}
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index d075619448d..3d26fd23b26 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -459,7 +459,7 @@ static unsigned int compute_method_indexes(type_t *iface)
return idx;
}
-void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts)
+void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts, type_list_t *requires)
{
iface->details.iface = xmalloc(sizeof(*iface->details.iface));
iface->details.iface->disp_props = NULL;
@@ -468,6 +468,7 @@ 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->details.iface->requires = requires;
iface->defined = TRUE;
compute_method_indexes(iface);
}
@@ -482,6 +483,7 @@ 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->details.iface->requires = NULL;
iface->defined = TRUE;
compute_method_indexes(iface);
}
@@ -496,6 +498,7 @@ 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->details.iface->requires = NULL;
dispiface->defined = TRUE;
compute_method_indexes(dispiface);
}
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h
index 951084cf875..8c555b91656 100644
--- a/tools/widl/typetree.h
+++ b/tools/widl/typetree.h
@@ -45,7 +45,7 @@ type_t *type_new_nonencapsulated_union(const char *name, int defined, var_list_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_bitfield(type_t *field_type, const expr_t *bits);
type_t *type_new_runtimeclass(char *name, struct namespace *namespace);
-void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts);
+void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts, type_list_t *requires);
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);
@@ -169,6 +169,13 @@ static inline type_t *type_iface_get_inherit(const type_t *type)
return type->details.iface->inherit;
}
+static inline type_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);
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index aa3e6e75898..be71886260b 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -378,6 +378,7 @@ struct iface_details
struct _type_t *inherit;
struct _type_t *disp_inherit;
struct _type_t *async_iface;
+ type_list_t *requires;
};
struct module_details
--
2.28.0

View File

@ -0,0 +1,96 @@
From c0c0bfcf80077cd2b5db3f7c1fb3fa597ae57321 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 13 Oct 2020 11:35:29 +0200
Subject: [PATCH 19/28] widl: Support WinRT activatable attribute.
---
tools/widl/header.c | 11 +++++++++++
tools/widl/parser.l | 1 +
tools/widl/parser.y | 3 +++
tools/widl/widltypes.h | 1 +
4 files changed, 16 insertions(+)
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 5dfc5e2ff8c..5c87a997349 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -1505,6 +1505,7 @@ static char *format_apicontract_macro(const type_t *type)
static void write_winrt_type_comments(FILE *header, const type_t *type)
{
expr_t *contract = get_attrp(type->attrs, ATTR_CONTRACT);
+ expr_t *activatable = get_attrp(type->attrs, ATTR_ACTIVATABLE);
type_t *exclusiveto = get_attrp(type->attrs, ATTR_EXCLUSIVETO);
type_list_t *requires = type->type_type == TYPE_INTERFACE ? type_iface_get_requires(type) : NULL;
expr_list_t statics = LIST_INIT(statics);
@@ -1518,6 +1519,16 @@ static void write_winrt_type_comments(FILE *header, const type_t *type)
fprintf(header, " * Introduced to %s in version %d.%d\n *\n", name, (ver >> 16) & 0xffff, ver & 0xffff);
free(name);
}
+ if (activatable)
+ {
+ const type_t *apicontract = activatable->u.tref.type;
+ int version_req = activatable->ref->u.lval;
+ char *name = format_namespace(apicontract->namespace, "", ".", apicontract->name, NULL);
+ fprintf(header, " * RuntimeClass can be activated.\n");
+ fprintf(header, " * Type can be activated via RoActivateInstance starting with version %d.%d of the %s API contract\n *\n",
+ (version_req >> 16) & 0xffff, version_req & 0xffff, name);
+ free(name);
+ }
if (exclusiveto)
{
char *name = format_namespace(exclusiveto->namespace, "", ".", exclusiveto->name, NULL);
diff --git a/tools/widl/parser.l b/tools/widl/parser.l
index 2b41bea1bc9..a47c490ec4c 100644
--- a/tools/widl/parser.l
+++ b/tools/widl/parser.l
@@ -321,6 +321,7 @@ static const struct keyword keywords[] = {
*/
static const struct keyword attr_keywords[] =
{
+ {"activatable", tACTIVATABLE, 1},
{"aggregatable", tAGGREGATABLE, 0},
{"agile", tAGILE, 1},
{"allocate", tALLOCATE, 0},
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 1da667e0ced..d24f8881147 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -172,6 +172,7 @@ static typelib_t *current_typelib;
%token GREATEREQUAL LESSEQUAL
%token LOGICALOR LOGICALAND
%token ELLIPSIS
+%token tACTIVATABLE
%token tAGGREGATABLE
%token tAGILE
%token tALLOCATE tANNOTATION
@@ -544,6 +545,7 @@ static_attr: decl_spec ',' contract_req { if ($1->type->type_type != TYPE_INTER
}
attribute: { $$ = NULL; }
+ | tACTIVATABLE '(' contract_req ')' { $$ = make_attrp(ATTR_ACTIVATABLE, $3); }
| tAGGREGATABLE { $$ = make_attr(ATTR_AGGREGATABLE); }
| tANNOTATION '(' aSTRING ')' { $$ = make_attrp(ATTR_ANNOTATION, $3); }
| tAPPOBJECT { $$ = make_attr(ATTR_APPOBJECT); }
@@ -2239,6 +2241,7 @@ struct allowed_attr
struct allowed_attr allowed_attr[] =
{
/* attr { D ACF M I Fn ARG T En Enm St Un Fi L DI M C AC R <display name> } */
+ /* ATTR_ACTIVATABLE */ { 0, 0, 0, 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_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" },
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index be71886260b..7ca770b67ea 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -68,6 +68,7 @@ typedef struct list warning_list_t;
enum attr_type
{
+ ATTR_ACTIVATABLE,
ATTR_AGGREGATABLE,
ATTR_ANNOTATION,
ATTR_APPOBJECT,
--
2.28.0

View File

@ -0,0 +1,391 @@
From 46f497692aa6da875d56764538eefaadb9a8ec38 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 13 Oct 2020 16:31:16 +0200
Subject: [PATCH 20/28] widl: Support WinRT parameterized type parsing.
And add IVectorView<T> and IIterator<T> parameterized interfaces to
windows.foundation.idl for illustration and future use. They won't
generate any additional code until they are fully specialized.
This is a WIDL-specific feature, but MIDL has some magic knowledge of
these Windows.Foundation.Collections interface templates, and we need a
way to instruct WIDL about them too.
Having these interfaces declared in the IDL, guarded with __WIDL__ ifdef
is easier and more flexible than re-creating the types by hand in WIDL
source.
---
include/windows.foundation.idl | 29 +++++++++++++++++
tools/widl/expr.c | 2 ++
tools/widl/header.c | 10 +++---
tools/widl/parser.y | 57 ++++++++++++++++++++++++++++++++--
tools/widl/typegen.c | 6 ++++
tools/widl/typelib.c | 2 ++
tools/widl/typetree.c | 30 ++++++++++++++++++
tools/widl/typetree.h | 4 +++
tools/widl/widltypes.h | 9 ++++++
9 files changed, 143 insertions(+), 6 deletions(-)
diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl
index 5e17062f399..ab7c4753c3b 100644
--- a/include/windows.foundation.idl
+++ b/include/windows.foundation.idl
@@ -111,5 +111,34 @@ namespace Windows {
{
HRESULT ToString([out, retval] HSTRING *value);
}
+
+#ifdef __WIDL__
+ namespace Collections
+ {
+ [
+ contract(Windows.Foundation.FoundationContract, 1.0),
+ uuid(6a79e863-4300-459a-9966-cbb660963ee1)
+ ]
+ interface IIterator<T> : IInspectable
+ {
+ [propget] HRESULT Current([out, retval] T *value);
+ [propget] HRESULT HasCurrent([out, retval] BOOL *value);
+ HRESULT MoveNext([out, retval] BOOL *value);
+ HRESULT GetMany([in] UINT32 count, [out] T *items, [out, retval] UINT32 *value);
+ }
+
+ [
+ contract(Windows.Foundation.FoundationContract, 1.0),
+ uuid(bbe1fa4c-b0e3-4583-baef-1f1b2e483e56)
+ ]
+ interface IVectorView<T> : IInspectable
+ {
+ HRESULT GetAt([in] ULONG index, [out, retval] T *value);
+ [propget] HRESULT Size([out, retval] ULONG *value);
+ HRESULT IndexOf([in, optional] T element, [out] ULONG *index, [out, retval] BOOLEAN *value);
+ HRESULT GetMany([in] ULONG start_index, [out] T *items, [out, retval] ULONG *value);
+ }
+ }
+#endif
}
}
diff --git a/tools/widl/expr.c b/tools/widl/expr.c
index 13bd5a889aa..c83e9aa5ec0 100644
--- a/tools/widl/expr.c
+++ b/tools/widl/expr.c
@@ -464,6 +464,8 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type,
case TYPE_BITFIELD:
case TYPE_APICONTRACT:
case TYPE_RUNTIMECLASS:
+ case TYPE_PARAMETERIZED_TYPE:
+ case TYPE_PARAMETER:
/* nothing to do */
break;
case TYPE_ALIAS:
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 5c87a997349..283f2372fee 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -501,7 +501,9 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i
break;
}
case TYPE_APICONTRACT:
- /* handled elsewhere */
+ case TYPE_PARAMETERIZED_TYPE:
+ case TYPE_PARAMETER:
+ /* handled elsewhere / shouldn't be here */
assert(0);
break;
}
@@ -568,6 +570,8 @@ void write_type_right(FILE *h, type_t *t, int is_field)
case TYPE_RUNTIMECLASS:
break;
case TYPE_APICONTRACT:
+ case TYPE_PARAMETERIZED_TYPE:
+ case TYPE_PARAMETER:
/* not supposed to be here */
assert(0);
break;
@@ -1969,10 +1973,8 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons
write_apicontract(header, stmt->u.type);
else if (type_get_type(stmt->u.type) == TYPE_RUNTIMECLASS)
write_runtimeclass(header, stmt->u.type);
- else
- {
+ else if (type_get_type(stmt->u.type) != TYPE_PARAMETERIZED_TYPE)
write_type_definition(header, stmt->u.type, stmt->declonly);
- }
break;
case STMT_TYPEREF:
/* FIXME: shouldn't write out forward declarations for undefined
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index d24f8881147..aa6ded5ba89 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -80,6 +80,8 @@ 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_lookup_namespace(const char *name);
+static void push_parameters_namespace(const char *name);
+static void pop_parameters_namespace(const char *name);
static void check_arg_attrs(const var_t *arg);
static void check_statements(const statement_list_t *stmts, int is_inside_library);
@@ -125,6 +127,7 @@ static struct namespace global_namespace = {
static struct namespace *current_namespace = &global_namespace;
static struct namespace *lookup_namespace = &global_namespace;
+static struct namespace *parameters_namespace = NULL;
static typelib_t *current_typelib;
@@ -295,6 +298,8 @@ static typelib_t *current_typelib;
%type <type> base_type int_std
%type <type> enumdef structdef uniondef typedecl
%type <type> type qualified_type
+%type <type> type_parameter
+%type <typelist> type_parameters
%type <typelist> requires required_types
%type <ifref> class_interface
%type <ifref_list> class_interfaces
@@ -1010,6 +1015,15 @@ interfacehdr: attributes interface { $$ = $2;
}
;
+type_parameter: aIDENTIFIER { $$ = get_type(TYPE_PARAMETER, $1, parameters_namespace, 0); }
+ | aKNOWNTYPE { $$ = get_type(TYPE_PARAMETER, $1, parameters_namespace, 0); }
+ ;
+
+type_parameters:
+ type_parameter { $$ = append_type(NULL, $1); }
+ | type_parameters ',' type_parameter { $$ = append_type($1, $3); }
+ ;
+
required_types:
qualified_type { $$ = append_type(NULL, $1); }
| required_types ',' required_types { $$ = append_types($1, $3); }
@@ -1025,6 +1039,13 @@ interfacedef: interfacehdr inherit requires
type_interface_define($$, $2, $5, $3);
check_async_uuid($$);
}
+ | interfacehdr '<' { push_parameters_namespace($1->name); } type_parameters '>' inherit
+ '{' int_statements '}' semicolon_opt { $$ = $1;
+ if($$ == $6) error_loc("Interface can't inherit from itself\n");
+ type_parameterized_interface_define($$, $4, $6, $8);
+ check_async_uuid($$);
+ pop_parameters_namespace($1->name);
+ }
/* 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 requires
@@ -1037,6 +1058,11 @@ interfacedef: interfacehdr inherit requires
interfacedec:
interface ';' { $$ = $1; }
+ | interface '<' { push_parameters_namespace($1->name); } type_parameters '>' ';'
+ { $$ = $1;
+ type_parameterized_interface_declare($$, $4);
+ pop_parameters_namespace($1->name);
+ }
| dispinterface ';' { $$ = $1; }
;
@@ -1979,6 +2005,29 @@ static void push_lookup_namespace(const char *name)
lookup_namespace = namespace;
}
+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(&current_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;
@@ -2110,7 +2159,8 @@ static type_t *find_qualified_type_or_error(const char *name, int t)
static type_t *find_type_or_error(const char *name, int t)
{
type_t *type;
- if (!(type = find_type(name, current_namespace, t)))
+ if (!(type = find_type(name, current_namespace, t)) &&
+ !(type = find_type(name, parameters_namespace, t)))
{
error_loc("type '%s' not found\n", name);
return NULL;
@@ -2130,7 +2180,8 @@ int is_type(const char *name)
if (lookup_namespace != &global_namespace)
return find_type(name, lookup_namespace, 0) != NULL;
else
- return find_type(name, current_namespace, 0) != NULL;
+ return find_type(name, current_namespace, 0) != NULL ||
+ find_type(name, parameters_namespace, 0) != NULL;
}
int is_namespace(const char *name)
@@ -2623,6 +2674,8 @@ static int is_allowed_conf_type(const type_t *type)
case TYPE_RUNTIMECLASS:
return FALSE;
case TYPE_APICONTRACT:
+ case TYPE_PARAMETERIZED_TYPE:
+ case TYPE_PARAMETER:
/* not supposed to be here */
assert(0);
break;
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index 86c010aa6ae..f37b54eb65d 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -377,6 +377,8 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att
case TYPE_RUNTIMECLASS:
break;
case TYPE_APICONTRACT:
+ case TYPE_PARAMETERIZED_TYPE:
+ case TYPE_PARAMETER:
/* not supposed to be here */
assert(0);
break;
@@ -1974,6 +1976,8 @@ unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align)
case TYPE_BITFIELD:
case TYPE_APICONTRACT:
case TYPE_RUNTIMECLASS:
+ case TYPE_PARAMETERIZED_TYPE:
+ case TYPE_PARAMETER:
/* 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
@@ -2077,6 +2081,8 @@ static unsigned int type_buffer_alignment(const type_t *t)
case TYPE_BITFIELD:
case TYPE_APICONTRACT:
case TYPE_RUNTIMECLASS:
+ case TYPE_PARAMETERIZED_TYPE:
+ case TYPE_PARAMETER:
/* 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
diff --git a/tools/widl/typelib.c b/tools/widl/typelib.c
index ace6424e3a0..6f6c5f3ccc8 100644
--- a/tools/widl/typelib.c
+++ b/tools/widl/typelib.c
@@ -226,6 +226,8 @@ unsigned short get_type_vt(type_t *t)
case TYPE_ALIAS:
case TYPE_APICONTRACT:
+ case TYPE_PARAMETERIZED_TYPE:
+ case TYPE_PARAMETER:
/* not supposed to be here */
assert(0);
break;
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index 3d26fd23b26..bbd519d98ab 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -459,6 +459,36 @@ static unsigned int compute_method_indexes(type_t *iface)
return idx;
}
+void type_parameterized_interface_declare(type_t *type, type_list_t *params)
+{
+ type_t *iface = make_type(TYPE_INTERFACE);
+ type->type_type = TYPE_PARAMETERIZED_TYPE;
+ type->details.parameterized.type = iface;
+ type->details.parameterized.params = params;
+}
+
+void type_parameterized_interface_define(type_t *type, type_list_t *params, type_t *inherit, statement_list_t *stmts)
+{
+ type_t *iface;
+
+ if (type->type_type != TYPE_PARAMETERIZED_TYPE) type_parameterized_interface_declare(type, params);
+ iface = type->details.parameterized.type;
+
+ /* 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
+ * FIXME: store type signatures for generated interfaces, and generate their GUIDs
+ */
+ 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 = NULL;
+}
+
void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts, type_list_t *requires)
{
iface->details.iface = xmalloc(sizeof(*iface->details.iface));
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h
index 8c555b91656..b04a67f6b47 100644
--- a/tools/widl/typetree.h
+++ b/tools/widl/typetree.h
@@ -45,6 +45,8 @@ type_t *type_new_nonencapsulated_union(const char *name, int defined, var_list_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_bitfield(type_t *field_type, const expr_t *bits);
type_t *type_new_runtimeclass(char *name, struct namespace *namespace);
+void type_parameterized_interface_declare(type_t *type, type_list_t *params);
+void type_parameterized_interface_define(type_t *type, type_list_t *params, type_t *inherit, statement_list_t *stmts);
void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts, type_list_t *requires);
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);
@@ -234,6 +236,8 @@ static inline int type_is_complete(const type_t *type)
case TYPE_RUNTIMECLASS:
return TRUE;
case TYPE_APICONTRACT:
+ case TYPE_PARAMETERIZED_TYPE:
+ case TYPE_PARAMETER:
assert(0);
break;
}
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 7ca770b67ea..e2ffec6da8a 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -429,6 +429,12 @@ struct runtimeclass_details
ifref_list_t *ifaces;
};
+struct parameterized_details
+{
+ type_t *type;
+ type_list_t *params;
+};
+
#define HASHMAX 64
struct namespace {
@@ -457,6 +463,8 @@ enum type_type
TYPE_BITFIELD,
TYPE_APICONTRACT,
TYPE_RUNTIMECLASS,
+ TYPE_PARAMETERIZED_TYPE,
+ TYPE_PARAMETER,
};
struct _type_t {
@@ -478,6 +486,7 @@ struct _type_t {
struct bitfield_details bitfield;
struct alias_details alias;
struct runtimeclass_details runtimeclass;
+ struct parameterized_details parameterized;
} details;
const char *c_name;
unsigned int typestring_offset;
--
2.28.0

View File

@ -0,0 +1,203 @@
From dfec9f64f5f1058ce394c8a39ae759ea027106a8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 12 Oct 2020 23:23:18 +0200
Subject: [PATCH 21/28] widl: Support partially specialized parameterized type.
This allows parameterized types to reference each other with a different
set of parameters. This is required for instance for IIterable<T>, that
needs to reference IIterator<T>.
The partial specialization is recorded by adding a new parameterized
type, referencing the original one as its template. The parameterized
type chain will be resolved all at once when the type is declared.
---
include/windows.foundation.idl | 9 +++++++++
tools/widl/parser.y | 35 ++++++++++++++++++++++++++++++++++
tools/widl/typetree.c | 32 +++++++++++++++++++++++++++++++
tools/widl/typetree.h | 2 ++
tools/widl/widltypes.h | 1 +
5 files changed, 79 insertions(+)
diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl
index ab7c4753c3b..5f7a49c38e4 100644
--- a/include/windows.foundation.idl
+++ b/include/windows.foundation.idl
@@ -127,6 +127,15 @@ namespace Windows {
HRESULT GetMany([in] UINT32 count, [out] T *items, [out, retval] UINT32 *value);
}
+ [
+ contract(Windows.Foundation.FoundationContract, 1.0),
+ uuid(faa585ea-6214-4217-afda-7f46de5869b3)
+ ]
+ interface IIterable<T> : IInspectable
+ {
+ HRESULT First([out, retval] Windows.Foundation.Collections.IIterator<T> **value);
+ }
+
[
contract(Windows.Foundation.FoundationContract, 1.0),
uuid(bbe1fa4c-b0e3-4583-baef-1f1b2e483e56)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index aa6ded5ba89..c9806ced633 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -300,6 +300,8 @@ static typelib_t *current_typelib;
%type <type> type qualified_type
%type <type> type_parameter
%type <typelist> type_parameters
+%type <type> parameterized_type
+%type <typelist> parameterized_types
%type <typelist> requires required_types
%type <ifref> class_interface
%type <ifref_list> class_interfaces
@@ -908,6 +910,20 @@ qualified_type:
| namespace_pfx aKNOWNTYPE { $$ = find_qualified_type_or_error($2, 0); }
;
+parameterized_type: qualified_type '<' parameterized_types '>'
+ { $$ = find_parameterized_type($1, $3, 0); }
+ ;
+
+parameterized_types:
+ base_type { $$ = append_type(NULL, $1); }
+ | qualified_type { $$ = append_type(NULL, $1); }
+ | qualified_type '*' { $$ = append_type(NULL, type_new_pointer($1)); }
+ | parameterized_type { $$ = append_type(NULL, $1); }
+ | parameterized_type '*' { $$ = append_type(NULL, type_new_pointer($1)); }
+ | parameterized_types ',' parameterized_types
+ { $$ = append_types($1, $3); }
+ ;
+
coclass: tCOCLASS aIDENTIFIER { $$ = type_new_coclass($2); }
| tCOCLASS aKNOWNTYPE { $$ = find_type($2, NULL, 0);
if (type_get_type_detect_alias($$) != TYPE_COCLASS)
@@ -1000,6 +1016,7 @@ dispinterfacedef: dispinterfacehdr '{'
inherit: { $$ = NULL; }
| ':' qualified_type { $$ = $2; }
+ | ':' parameterized_type { $$ = $2; }
;
interface: tINTERFACE aIDENTIFIER { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); }
@@ -1026,6 +1043,7 @@ type_parameters:
required_types:
qualified_type { $$ = append_type(NULL, $1); }
+ | parameterized_type { $$ = append_type(NULL, $1); }
| required_types ',' required_types { $$ = append_types($1, $3); }
requires: { $$ = NULL; }
@@ -1247,6 +1265,7 @@ structdef: tSTRUCT t_ident '{' fields '}' { $$ = type_new_struct($2, current_nam
type: tVOID { $$ = type_new_void(); }
| qualified_type { $$ = $1; }
+ | parameterized_type { $$ = $1; }
| base_type { $$ = $1; }
| enumdef { $$ = $1; }
| tENUM aIDENTIFIER { $$ = type_new_enum($2, current_namespace, FALSE, NULL); }
@@ -3324,3 +3343,19 @@ static void check_def(const type_t *t)
error_loc("%s: redefinition error; original definition was at %s:%d\n",
t->name, t->loc_info.input_name, t->loc_info.line_number);
}
+
+type_t *find_parameterized_type(type_t *type, type_list_t *params, int t)
+{
+ char *name = format_parameterized_type_name(type, params);
+
+ if (parameters_namespace)
+ {
+ assert(type->type_type == TYPE_PARAMETERIZED_TYPE);
+ type = type_parameterized_type_specialize_partial(type, params);
+ }
+ /* FIXME: If not in another parameterized type, we'll have to look for the declared specialization. */
+ else error_loc("parameterized type '%s' not declared\n", name);
+
+ free(name);
+ return type;
+}
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index bbd519d98ab..9d50cabf172 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -112,6 +112,22 @@ static int format_namespace_buffer(char *buf, size_t len, struct namespace *name
return ret;
}
+static int format_parameterized_type_name_buffer(char *buf, size_t len, type_t *type, type_list_t *params)
+{
+ type_list_t *entry;
+ int ret = 0;
+ append_buf(snprintf, "%s<", type->name);
+ for (entry = params; entry; entry = entry->next)
+ {
+ for (type = entry->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) {}
+ append_buf(format_namespace_buffer, type->namespace, "", "::", type->name, use_abi_namespace ? "ABI" : NULL);
+ for (type = entry->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) append_buf(snprintf, "*");
+ if (entry->next) append_buf(snprintf, ",");
+ }
+ append_buf(snprintf, ">");
+ return ret;
+}
+
#undef append_buf
char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, const char *abi_prefix)
@@ -122,6 +138,14 @@ char *format_namespace(struct namespace *namespace, const char *prefix, const ch
return buf;
}
+char *format_parameterized_type_name(type_t *type, type_list_t *params)
+{
+ int len = format_parameterized_type_name_buffer(NULL, 0, type, params);
+ char *buf = xmalloc(len + 1);
+ format_parameterized_type_name_buffer(buf, len + 1, type, params);
+ return buf;
+}
+
type_t *type_new_function(var_list_t *args)
{
var_t *arg;
@@ -459,6 +483,14 @@ static unsigned int compute_method_indexes(type_t *iface)
return idx;
}
+type_t *type_parameterized_type_specialize_partial(type_t *type, type_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;
+}
+
void type_parameterized_interface_declare(type_t *type, type_list_t *params)
{
type_t *iface = make_type(TYPE_INTERFACE);
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h
index b04a67f6b47..472fdf2d5fc 100644
--- a/tools/widl/typetree.h
+++ b/tools/widl/typetree.h
@@ -45,6 +45,8 @@ type_t *type_new_nonencapsulated_union(const char *name, int defined, var_list_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_bitfield(type_t *field_type, const expr_t *bits);
type_t *type_new_runtimeclass(char *name, struct namespace *namespace);
+type_t *type_parameterized_type_specialize_partial(type_t *type, type_list_t *params);
+type_t *find_parameterized_type(type_t *type, type_list_t *params, int t);
void type_parameterized_interface_declare(type_t *type, type_list_t *params);
void type_parameterized_interface_define(type_t *type, type_list_t *params, type_t *inherit, statement_list_t *stmts);
void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts, type_list_t *requires);
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index e2ffec6da8a..9863c4f72ff 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -643,6 +643,7 @@ void init_loc_info(loc_info_t *);
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, type_list_t *params);
static inline enum type_type type_get_type_detect_alias(const type_t *type)
{
--
2.28.0

View File

@ -0,0 +1,542 @@
From dfbafe5f504cc35003199e63716c9ce5c6a5729e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 12 Oct 2020 17:38:53 +0200
Subject: [PATCH 22/28] widl: Support WinRT parameterized interface type.
This allows parameterized interfaces to be instanciated in declare
blocks, in the same way MIDL does, generating a new interface to the
header from the parameterized type template, replacing its parameters
with the given types.
---
include/windows.media.speechsynthesis.idl | 23 ++
tools/widl/header.c | 7 +-
tools/widl/parser.l | 1 +
tools/widl/parser.y | 63 +++++-
tools/widl/typetree.c | 243 ++++++++++++++++++++++
tools/widl/typetree.h | 2 +
6 files changed, 334 insertions(+), 5 deletions(-)
diff --git a/include/windows.media.speechsynthesis.idl b/include/windows.media.speechsynthesis.idl
index 89fe616b9b3..40c45c82051 100644
--- a/include/windows.media.speechsynthesis.idl
+++ b/include/windows.media.speechsynthesis.idl
@@ -35,6 +35,18 @@ namespace Windows {
}
}
+namespace Windows {
+ namespace Media {
+ namespace SpeechSynthesis {
+ declare {
+ interface Windows.Foundation.Collections.IIterator<Windows.Media.SpeechSynthesis.VoiceInformation*>;
+ interface Windows.Foundation.Collections.IIterable<Windows.Media.SpeechSynthesis.VoiceInformation*>;
+ interface Windows.Foundation.Collections.IVectorView<Windows.Media.SpeechSynthesis.VoiceInformation*>;
+ }
+ }
+ }
+}
+
namespace Windows {
namespace Media {
namespace SpeechSynthesis {
@@ -59,6 +71,17 @@ namespace Windows {
[propget] HRESULT Gender([out] [retval] VoiceGender* value);
}
+ [
+ contract(Windows.Foundation.UniversalApiContract, 1.0),
+ exclusiveto(Windows.Media.SpeechSynthesis.SpeechSynthesizer),
+ uuid(7d526ecc-7533-4c3f-85be-888c2baeebdc)
+ ]
+ interface IInstalledVoicesStatic : IInspectable
+ {
+ [propget] HRESULT AllVoices([out, retval] Windows.Foundation.Collections.IVectorView<VoiceInformation*>** value);
+ [propget] HRESULT DefaultVoice([out, retval] VoiceInformation** value);
+ }
+
[
contract(Windows.Foundation.UniversalApiContract, 1.0),
marshaling_behavior(agile)
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 283f2372fee..db83f3aac13 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -1492,7 +1492,8 @@ static void write_forward(FILE *header, type_t *iface)
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);
+ if (strchr(iface->name, '<')) write_line(header, 0, "template<> struct %s;", iface->name);
+ else write_line(header, 0, "interface %s;", iface->name);
write_namespace_end(header, iface->namespace);
fprintf(header, "#endif /* __cplusplus */\n");
fprintf(header, "#endif\n\n" );
@@ -1655,11 +1656,13 @@ 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))
{
diff --git a/tools/widl/parser.l b/tools/widl/parser.l
index a47c490ec4c..b7f8844c7a9 100644
--- a/tools/widl/parser.l
+++ b/tools/widl/parser.l
@@ -276,6 +276,7 @@ static const struct keyword keywords[] = {
{"coclass", tCOCLASS, 0},
{"const", tCONST, 0},
{"cpp_quote", tCPPQUOTE, 0},
+ {"declare", tDECLARE, 1},
{"default", tDEFAULT, 0},
{"dispinterface", tDISPINTERFACE, 0},
{"double", tDOUBLE, 0},
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index c9806ced633..2fb73a46dc1 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -83,6 +83,7 @@ static void push_lookup_namespace(const char *name);
static void push_parameters_namespace(const char *name);
static void pop_parameters_namespace(const char *name);
+static statement_list_t *append_parameterized_type_stmts(statement_list_t *stmts);
static void check_arg_attrs(const var_t *arg);
static void check_statements(const statement_list_t *stmts, int is_inside_library);
static void check_all_user_types(const statement_list_t *stmts);
@@ -117,6 +118,7 @@ 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, int declonly);
static statement_t *make_statement_import(const char *str);
+static statement_t *make_statement_parameterized_type(type_t *type, type_list_t *params);
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 *);
@@ -128,6 +130,7 @@ static struct namespace global_namespace = {
static struct namespace *current_namespace = &global_namespace;
static struct namespace *lookup_namespace = &global_namespace;
static struct namespace *parameters_namespace = NULL;
+static statement_list_t *parameterized_type_stmts = NULL;
static typelib_t *current_typelib;
@@ -188,6 +191,7 @@ static typelib_t *current_typelib;
%token tCONTRACT
%token tCONTRACTVERSION
%token tCONTROL tCPPQUOTE
+%token tDECLARE
%token tDECODE tDEFAULT tDEFAULTBIND
%token tDEFAULTCOLLELEM
%token tDEFAULTVALUE
@@ -325,6 +329,8 @@ static typelib_t *current_typelib;
%type <typelib> library_start librarydef
%type <statement> statement typedef pragma_warning
%type <stmt_list> gbl_statements imp_statements int_statements
+%type <stmt_list> decl_block decl_statements
+%type <stmt_list> imp_decl_block imp_decl_statements
%type <warning_list> warnings
%left ','
@@ -346,7 +352,8 @@ static typelib_t *current_typelib;
%%
-input: gbl_statements m_acf { check_statements($1, FALSE);
+input: gbl_statements m_acf { $1 = append_parameterized_type_stmts($1);
+ check_statements($1, FALSE);
check_all_user_types($1);
write_header($1);
write_id_data($1);
@@ -362,6 +369,22 @@ input: gbl_statements m_acf { check_statements($1, FALSE);
m_acf: /* empty */ | aACF acf_statements
+decl_statements: { $$ = NULL; }
+ | decl_statements tINTERFACE qualified_type '<' parameterized_types '>' ';'
+ { 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: { $$ = NULL; }
+ | imp_decl_statements tINTERFACE qualified_type '<' parameterized_types '>' ';'
+ { $$ = append_statement($1, make_statement_reference(type_parameterized_type_specialize_declare($3, $5))); }
+ ;
+
+imp_decl_block: tDECLARE '{' imp_decl_statements '}' { $$ = $3; }
+
gbl_statements: { $$ = NULL; }
| gbl_statements namespacedef '{' { push_namespace($2); } gbl_statements '}'
{ pop_namespace($2); $$ = append_statements($1, $5); }
@@ -381,6 +404,7 @@ gbl_statements: { $$ = NULL; }
| 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; }
@@ -401,6 +425,7 @@ imp_statements: { $$ = NULL; }
| 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; }
@@ -3121,6 +3146,27 @@ static void check_async_uuid(type_t *iface)
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_list->type, stmt->u.type_list->next);
+ stmt->declonly = FALSE;
+ 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;
@@ -3302,6 +3348,15 @@ static statement_t *make_statement_typedef(declarator_list_t *decls, int declonl
return stmt;
}
+static statement_t *make_statement_parameterized_type(type_t *type, type_list_t *params)
+{
+ statement_t *stmt = make_statement(STMT_TYPE);
+ stmt->u.type_list = xmalloc(sizeof(type_list_t));
+ stmt->u.type_list->type = type;
+ stmt->u.type_list->next = params;
+ return stmt;
+}
+
static statement_list_t *append_statements(statement_list_t *l1, statement_list_t *l2)
{
if (!l2) return l1;
@@ -3353,8 +3408,10 @@ type_t *find_parameterized_type(type_t *type, type_list_t *params, int t)
assert(type->type_type == TYPE_PARAMETERIZED_TYPE);
type = type_parameterized_type_specialize_partial(type, params);
}
- /* FIXME: If not in another parameterized type, we'll have to look for the declared specialization. */
- else error_loc("parameterized type '%s' not declared\n", name);
+ else if ((type = find_type(name, type->namespace, t)))
+ assert(type->type_type != TYPE_PARAMETERIZED_TYPE);
+ else
+ error_loc("parameterized type '%s' not declared\n", name);
free(name);
return type;
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index 9d50cabf172..8f1e2d71aff 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -128,6 +128,21 @@ static int format_parameterized_type_name_buffer(char *buf, size_t len, type_t *
return ret;
}
+static int format_parameterized_type_c_name_buffer(char *buf, size_t len, type_t *type, type_list_t *params)
+{
+ type_list_t *entry;
+ int ret = 0, count = 0;
+ append_buf(format_namespace_buffer, type->namespace, "__x_", "_C", type->name, use_abi_namespace ? "ABI" : NULL);
+ for (entry = params; entry; entry = entry->next) count++;
+ append_buf(snprintf, "_%d", count);
+ for (entry = params; entry; entry = entry->next)
+ {
+ for (type = entry->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) {}
+ append_buf(format_namespace_buffer, type->namespace, "_", "__C", type->name, NULL);
+ }
+ return ret;
+}
+
#undef append_buf
char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, const char *abi_prefix)
@@ -146,6 +161,31 @@ char *format_parameterized_type_name(type_t *type, type_list_t *params)
return buf;
}
+static char const *parameterized_type_shorthands[][2] = {
+ {"Windows_CFoundation_CCollections_C", "__F"},
+ {"Windows_CFoundation_C", "__F"},
+};
+
+static char *format_parameterized_type_c_name(type_t *type, type_list_t *params)
+{
+ int i, len = format_parameterized_type_c_name_buffer(NULL, 0, type, params);
+ char *buf = xmalloc(len + 1), *tmp;
+ format_parameterized_type_c_name_buffer(buf, len + 1, type, params);
+
+ for (i = 0; i < ARRAY_SIZE(parameterized_type_shorthands); ++i)
+ {
+ if ((tmp = strstr(buf, parameterized_type_shorthands[i][0])) &&
+ (tmp - buf) == strlen(use_abi_namespace ? "__x_ABI_C" : "__x_C"))
+ {
+ tmp += strlen(parameterized_type_shorthands[i][0]);
+ strcpy(buf, parameterized_type_shorthands[i][1]);
+ memmove(buf + 3, tmp, len - (tmp - buf) + 1);
+ }
+ }
+
+ return buf;
+}
+
type_t *type_new_function(var_list_t *args)
{
var_t *arg;
@@ -483,6 +523,177 @@ static unsigned int compute_method_indexes(type_t *iface)
return idx;
}
+static type_t *replace_type_parameters_in_type(type_t *type, type_list_t *orig, type_list_t *repl);
+
+static type_list_t *replace_type_parameters_in_type_list(type_list_t *type_list, type_list_t *orig, type_list_t *repl)
+{
+ type_list_t *entry, *new_entry, **next, *first = NULL;
+
+ if (!type_list) return type_list;
+
+ next = &first;
+ for (entry = type_list; entry; entry = entry->next)
+ {
+ new_entry = xmalloc(sizeof(*new_entry));
+ new_entry->type = replace_type_parameters_in_type(entry->type, orig, repl);
+ new_entry->next = NULL;
+ *next = new_entry;
+ next = &new_entry->next;
+ }
+
+ return first;
+}
+
+static var_t *replace_type_parameters_in_var(var_t *var, type_list_t *orig, type_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, type_list_t *orig, type_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, type_list_t *orig, type_list_t *repl)
+{
+ 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_LIBRARY:
+ case STMT_TYPE:
+ case STMT_TYPEREF:
+ case STMT_MODULE:
+ case STMT_TYPEDEF:
+ new_stmt->u.type_list = replace_type_parameters_in_type_list(stmt->u.type_list, orig, repl);
+ break;
+ case STMT_IMPORT:
+ case STMT_IMPORTLIB:
+ case STMT_PRAGMA:
+ case STMT_CPPQUOTE:
+ fprintf(stderr, "%d\n", stmt->type);
+ assert(0);
+ break;
+ }
+
+ return new_stmt;
+}
+
+static statement_list_t *replace_type_parameters_in_statement_list(statement_list_t *stmt_list, type_list_t *orig, type_list_t *repl)
+{
+ 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);
+ list_add_tail(new_stmt_list, &new_stmt->entry);
+ }
+
+ return new_stmt_list;
+}
+
+static type_t *replace_type_parameters_in_type(type_t *type, type_list_t *orig, type_list_t *repl)
+{
+ type_list_t *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:
+ return type;
+ case TYPE_PARAMETER:
+ for (o = orig, r = repl; o && r; o = o->next, r = r->next)
+ if (type == o->type) return r->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, 0);
+ 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_STRUCT:
+ case TYPE_ENCAPSULATED_UNION:
+ case TYPE_UNION:
+ case TYPE_MODULE:
+ case TYPE_COCLASS:
+ case TYPE_APICONTRACT:
+ assert(0); /* FIXME: implement when needed */
+ break;
+ }
+
+ return type;
+}
+
+static void type_parameterized_interface_specialize(type_t *tmpl, type_t *iface, type_list_t *orig, type_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);
+ 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;
+}
+
type_t *type_parameterized_type_specialize_partial(type_t *type, type_list_t *params)
{
type_t *new_type = duptype(type, 0);
@@ -491,6 +702,38 @@ type_t *type_parameterized_type_specialize_partial(type_t *type, type_list_t *pa
return new_type;
}
+type_t *type_parameterized_type_specialize_declare(type_t *type, type_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);
+
+ return new_type;
+}
+
+type_t *type_parameterized_type_specialize_define(type_t *type, type_list_t *params)
+{
+ type_list_t *orig = type->details.parameterized.params;
+ type_t *tmpl = type->details.parameterized.type;
+ type_t *iface = find_parameterized_type(type, params, 0);
+
+ if (tmpl->type_type == TYPE_INTERFACE)
+ type_parameterized_interface_specialize(tmpl, iface, orig, params);
+ else
+ {
+ error_loc("Unsupported parameterized type template %d\n", tmpl->type_type);
+ return NULL;
+ }
+
+ iface->defined = TRUE;
+ compute_method_indexes(iface);
+ return iface;
+}
+
void type_parameterized_interface_declare(type_t *type, type_list_t *params)
{
type_t *iface = make_type(TYPE_INTERFACE);
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h
index 472fdf2d5fc..e1a52d21d09 100644
--- a/tools/widl/typetree.h
+++ b/tools/widl/typetree.h
@@ -46,6 +46,8 @@ type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *unio
type_t *type_new_bitfield(type_t *field_type, const expr_t *bits);
type_t *type_new_runtimeclass(char *name, struct namespace *namespace);
type_t *type_parameterized_type_specialize_partial(type_t *type, type_list_t *params);
+type_t *type_parameterized_type_specialize_declare(type_t *type, type_list_t *params);
+type_t *type_parameterized_type_specialize_define(type_t *type, type_list_t *params);
type_t *find_parameterized_type(type_t *type, type_list_t *params, int t);
void type_parameterized_interface_declare(type_t *type, type_list_t *params);
void type_parameterized_interface_define(type_t *type, type_list_t *params, type_t *inherit, statement_list_t *stmts);
--
2.28.0

View File

@ -0,0 +1,346 @@
From 82c354b2275a33863181fc7660f8e63db51c131a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 24 Sep 2020 00:00:54 +0200
Subject: [PATCH 23/28] widl: Support WinRT delegate type.
---
tools/widl/expr.c | 1 +
tools/widl/header.c | 14 ++++++++++----
tools/widl/parser.l | 1 +
tools/widl/parser.y | 25 +++++++++++++++++++++++++
tools/widl/typegen.c | 4 ++++
tools/widl/typelib.c | 1 +
tools/widl/typetree.c | 29 +++++++++++++++++++++++++++++
tools/widl/typetree.h | 9 +++++++++
tools/widl/widltypes.h | 7 +++++++
9 files changed, 87 insertions(+), 4 deletions(-)
diff --git a/tools/widl/expr.c b/tools/widl/expr.c
index c83e9aa5ec0..88d59290d6b 100644
--- a/tools/widl/expr.c
+++ b/tools/widl/expr.c
@@ -466,6 +466,7 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type,
case TYPE_RUNTIMECLASS:
case TYPE_PARAMETERIZED_TYPE:
case TYPE_PARAMETER:
+ case TYPE_DELEGATE:
/* nothing to do */
break;
case TYPE_ALIAS:
diff --git a/tools/widl/header.c b/tools/widl/header.c
index db83f3aac13..64faf89c36a 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -483,6 +483,9 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i
case TYPE_RUNTIMECLASS:
fprintf(h, "%s", type_get_name(type_runtimeclass_get_default_iface(t), 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;
@@ -568,6 +571,7 @@ void write_type_right(FILE *h, type_t *t, int is_field)
case TYPE_COCLASS:
case TYPE_INTERFACE:
case TYPE_RUNTIMECLASS:
+ case TYPE_DELEGATE:
break;
case TYPE_APICONTRACT:
case TYPE_PARAMETERIZED_TYPE:
@@ -1904,9 +1908,10 @@ 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);
@@ -1946,10 +1951,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 = type_iface_get_async_iface(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))
{
diff --git a/tools/widl/parser.l b/tools/widl/parser.l
index b7f8844c7a9..5de85e43a94 100644
--- a/tools/widl/parser.l
+++ b/tools/widl/parser.l
@@ -278,6 +278,7 @@ static const struct keyword keywords[] = {
{"cpp_quote", tCPPQUOTE, 0},
{"declare", tDECLARE, 1},
{"default", tDEFAULT, 0},
+ {"delegate", tDELEGATE, 1},
{"dispinterface", tDISPINTERFACE, 0},
{"double", tDOUBLE, 0},
{"enum", tENUM, 0},
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 2fb73a46dc1..d0166eb3af2 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -119,6 +119,7 @@ static statement_t *make_statement_module(type_t *type);
static statement_t *make_statement_typedef(var_list_t *names, int declonly);
static statement_t *make_statement_import(const char *str);
static statement_t *make_statement_parameterized_type(type_t *type, type_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 *);
@@ -193,6 +194,7 @@ static typelib_t *current_typelib;
%token tCONTROL tCPPQUOTE
%token tDECLARE
%token tDECODE tDEFAULT tDEFAULTBIND
+%token tDELEGATE
%token tDEFAULTCOLLELEM
%token tDEFAULTVALUE
%token tDEFAULTVTABLE
@@ -291,6 +293,7 @@ static typelib_t *current_typelib;
%type <expr> contract_req
%type <expr> static_attr
%type <type> interfacehdr
+%type <type> delegatedef
%type <stgclass> storage_cls_spec
%type <type_qualifier> type_qualifier m_type_qual_list
%type <function_specifier> function_specifier
@@ -390,6 +393,7 @@ gbl_statements: { $$ = NULL; }
{ pop_namespace($2); $$ = append_statements($1, $5); }
| gbl_statements interfacedec { $$ = 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);
}
@@ -412,6 +416,7 @@ imp_statements: { $$ = NULL; }
| imp_statements namespacedef '{' { push_namespace($2); } imp_statements '}'
{ pop_namespace($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);
@@ -1066,6 +1071,17 @@ type_parameters:
| type_parameters ',' type_parameter { $$ = append_type($1, $3); }
;
+delegatedef:
+ m_attributes tDELEGATE type ident '(' m_args ')'
+ semicolon_opt { $$ = get_type(TYPE_DELEGATE, $4->name, current_namespace, 0);
+ check_def($$);
+ $$->attrs = check_iface_attrs($$->name, $1);
+ $$->defined = TRUE;
+ type_delegate_define($$, append_statement(NULL, make_statement_delegate($3, $6)));
+ check_async_uuid($$);
+ }
+ ;
+
required_types:
qualified_type { $$ = append_type(NULL, $1); }
| parameterized_type { $$ = append_type(NULL, $1); }
@@ -2716,6 +2732,7 @@ static int is_allowed_conf_type(const type_t *type)
case TYPE_INTERFACE:
case TYPE_BITFIELD:
case TYPE_RUNTIMECLASS:
+ case TYPE_DELEGATE:
return FALSE;
case TYPE_APICONTRACT:
case TYPE_PARAMETERIZED_TYPE:
@@ -3357,6 +3374,14 @@ static statement_t *make_statement_parameterized_type(type_t *type, type_list_t
return stmt;
}
+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;
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index f37b54eb65d..4557d24b3ff 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -354,6 +354,7 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att
case TYPE_POINTER:
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(type), ATTR_CONTEXTHANDLE))
@@ -375,6 +376,7 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att
case TYPE_ALIAS:
case TYPE_BITFIELD:
case TYPE_RUNTIMECLASS:
+ case TYPE_DELEGATE:
break;
case TYPE_APICONTRACT:
case TYPE_PARAMETERIZED_TYPE:
@@ -1978,6 +1980,7 @@ unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align)
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
@@ -2083,6 +2086,7 @@ static unsigned int type_buffer_alignment(const type_t *t)
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
diff --git a/tools/widl/typelib.c b/tools/widl/typelib.c
index 6f6c5f3ccc8..8b2a2401367 100644
--- a/tools/widl/typelib.c
+++ b/tools/widl/typelib.c
@@ -219,6 +219,7 @@ unsigned short get_type_vt(type_t *t)
case TYPE_UNION:
case TYPE_ENCAPSULATED_UNION:
case TYPE_RUNTIMECLASS:
+ case TYPE_DELEGATE:
return VT_USERDEFINED;
case TYPE_VOID:
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index 8f1e2d71aff..15629113cec 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -523,6 +523,13 @@ static unsigned int compute_method_indexes(type_t *iface)
return idx;
}
+static void compute_delegate_iface_name(type_t *delegate)
+{
+ char *name = xmalloc(strlen(delegate->name) + 2);
+ sprintf(name, "I%s", delegate->name);
+ delegate->details.delegate.iface->name = name;
+}
+
static type_t *replace_type_parameters_in_type(type_t *type, type_list_t *orig, type_list_t *repl);
static type_list_t *replace_type_parameters_in_type_list(type_list_t *type_list, type_list_t *orig, type_list_t *repl)
@@ -635,6 +642,7 @@ static type_t *replace_type_parameters_in_type(type_t *type, type_list_t *orig,
case TYPE_BITFIELD:
case TYPE_INTERFACE:
case TYPE_RUNTIMECLASS:
+ case TYPE_DELEGATE:
return type;
case TYPE_PARAMETER:
for (o = orig, r = repl; o && r; o = o->next, r = r->next)
@@ -778,6 +786,27 @@ void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stm
compute_method_indexes(iface);
}
+void type_delegate_define(type_t *delegate, statement_list_t *stmts)
+{
+ type_t *iface = make_type(TYPE_INTERFACE);
+
+ iface->namespace = delegate->namespace;
+ 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;
+ iface->defined = TRUE;
+ compute_method_indexes(iface);
+
+ delegate->details.delegate.iface = iface;
+ compute_delegate_iface_name(delegate);
+}
+
void type_dispinterface_define(type_t *iface, var_list_t *props, var_list_t *methods)
{
iface->details.iface = xmalloc(sizeof(*iface->details.iface));
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h
index e1a52d21d09..de3db4e7c7e 100644
--- a/tools/widl/typetree.h
+++ b/tools/widl/typetree.h
@@ -52,6 +52,7 @@ type_t *find_parameterized_type(type_t *type, type_list_t *params, int t);
void type_parameterized_interface_declare(type_t *type, type_list_t *params);
void type_parameterized_interface_define(type_t *type, type_list_t *params, type_t *inherit, statement_list_t *stmts);
void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts, type_list_t *requires);
+void type_delegate_define(type_t *iface, 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);
@@ -238,6 +239,7 @@ static inline int type_is_complete(const type_t *type)
case TYPE_ARRAY:
case TYPE_BITFIELD:
case TYPE_RUNTIMECLASS:
+ case TYPE_DELEGATE:
return TRUE;
case TYPE_APICONTRACT:
case TYPE_PARAMETERIZED_TYPE:
@@ -361,6 +363,13 @@ static inline type_t *type_runtimeclass_get_default_iface(const type_t *type)
return NULL;
}
+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);
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 9863c4f72ff..3938d0d5294 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -435,6 +435,11 @@ struct parameterized_details
type_list_t *params;
};
+struct delegate_details
+{
+ type_t *iface;
+};
+
#define HASHMAX 64
struct namespace {
@@ -465,6 +470,7 @@ enum type_type
TYPE_RUNTIMECLASS,
TYPE_PARAMETERIZED_TYPE,
TYPE_PARAMETER,
+ TYPE_DELEGATE,
};
struct _type_t {
@@ -487,6 +493,7 @@ struct _type_t {
struct alias_details alias;
struct runtimeclass_details runtimeclass;
struct parameterized_details parameterized;
+ struct delegate_details delegate;
} details;
const char *c_name;
unsigned int typestring_offset;
--
2.28.0

View File

@ -0,0 +1,181 @@
From f8fa58f5bdfac8adc9fba4af5ff294a11f48b556 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 28 Sep 2020 16:46:34 +0200
Subject: [PATCH 24/28] widl: Support WinRT parameterized delegate type.
---
include/windows.foundation.idl | 6 ++++
tools/widl/parser.y | 11 +++++++
tools/widl/typetree.c | 56 +++++++++++++++++++++++++++++-----
tools/widl/typetree.h | 1 +
4 files changed, 67 insertions(+), 7 deletions(-)
diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl
index 5f7a49c38e4..9583fa5bcc8 100644
--- a/include/windows.foundation.idl
+++ b/include/windows.foundation.idl
@@ -113,6 +113,12 @@ namespace Windows {
}
#ifdef __WIDL__
+ [
+ contract(Windows.Foundation.FoundationContract, 1.0),
+ uuid(9de1c535-6ae1-11e0-84e1-18a905bcc53f)
+ ]
+ delegate void EventHandler<T>([in] IInspectable *sender, [in] T args);
+
namespace Collections
{
[
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index d0166eb3af2..f7fb7a303a8 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -1080,6 +1080,17 @@ delegatedef:
type_delegate_define($$, append_statement(NULL, make_statement_delegate($3, $6)));
check_async_uuid($$);
}
+ | m_attributes tDELEGATE type ident
+ '<' { push_parameters_namespace($4->name); } type_parameters '>'
+ '(' m_args ')'
+ semicolon_opt { $$ = get_type(TYPE_DELEGATE, $4->name, current_namespace, 0);
+ check_def($$);
+ $$->attrs = check_iface_attrs($$->name, $1);
+ $$->defined = TRUE;
+ type_parameterized_delegate_define($$, $7, append_statement(NULL, make_statement_delegate($3, $10)));
+ check_async_uuid($$);
+ pop_parameters_namespace($4->name);
+ }
;
required_types:
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index 15629113cec..03778aa75c3 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -128,13 +128,13 @@ static int format_parameterized_type_name_buffer(char *buf, size_t len, type_t *
return ret;
}
-static int format_parameterized_type_c_name_buffer(char *buf, size_t len, type_t *type, type_list_t *params)
+static int format_parameterized_type_c_name_buffer(char *buf, size_t len, type_t *type, type_list_t *params, const char *prefix)
{
type_list_t *entry;
int ret = 0, count = 0;
- append_buf(format_namespace_buffer, type->namespace, "__x_", "_C", type->name, use_abi_namespace ? "ABI" : NULL);
+ append_buf(format_namespace_buffer, type->namespace, "__x_", "_C", "", use_abi_namespace ? "ABI" : NULL);
for (entry = params; entry; entry = entry->next) count++;
- append_buf(snprintf, "_%d", count);
+ append_buf(snprintf, "%s%s_%d", prefix, type->name, count);
for (entry = params; entry; entry = entry->next)
{
for (type = entry->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) {}
@@ -166,11 +166,11 @@ static char const *parameterized_type_shorthands[][2] = {
{"Windows_CFoundation_C", "__F"},
};
-static char *format_parameterized_type_c_name(type_t *type, type_list_t *params)
+static char *format_parameterized_type_c_name(type_t *type, type_list_t *params, const char *prefix)
{
- int i, len = format_parameterized_type_c_name_buffer(NULL, 0, type, params);
+ int i, len = format_parameterized_type_c_name_buffer(NULL, 0, type, params, prefix);
char *buf = xmalloc(len + 1), *tmp;
- format_parameterized_type_c_name_buffer(buf, len + 1, type, params);
+ format_parameterized_type_c_name_buffer(buf, len + 1, type, params, prefix);
for (i = 0; i < ARRAY_SIZE(parameterized_type_shorthands); ++i)
{
@@ -702,6 +702,11 @@ static void type_parameterized_interface_specialize(type_t *tmpl, type_t *iface,
iface->details.iface->requires = NULL;
}
+static void type_parameterized_delegate_specialize(type_t *tmpl, type_t *delegate, type_list_t *orig, type_list_t *repl)
+{
+ type_parameterized_interface_specialize(tmpl->details.delegate.iface, delegate->details.delegate.iface, orig, repl);
+}
+
type_t *type_parameterized_type_specialize_partial(type_t *type, type_list_t *params)
{
type_t *new_type = duptype(type, 0);
@@ -718,7 +723,15 @@ type_t *type_parameterized_type_specialize_declare(type_t *type, type_list_t *pa
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);
+ new_type->c_name = format_parameterized_type_c_name(type, params, "");
+
+ if (new_type->type_type == TYPE_DELEGATE)
+ {
+ new_type->details.delegate.iface = duptype(tmpl->details.delegate.iface, 0);
+ compute_delegate_iface_name(new_type);
+ new_type->details.delegate.iface->namespace = new_type->namespace;
+ new_type->details.delegate.iface->c_name = format_parameterized_type_c_name(type, params, "I");
+ }
return new_type;
}
@@ -731,6 +744,8 @@ type_t *type_parameterized_type_specialize_define(type_t *type, type_list_t *par
if (tmpl->type_type == TYPE_INTERFACE)
type_parameterized_interface_specialize(tmpl, iface, orig, params);
+ else if (tmpl->type_type == TYPE_DELEGATE)
+ type_parameterized_delegate_specialize(tmpl, iface, orig, params);
else
{
error_loc("Unsupported parameterized type template %d\n", tmpl->type_type);
@@ -738,6 +753,11 @@ type_t *type_parameterized_type_specialize_define(type_t *type, type_list_t *par
}
iface->defined = TRUE;
+ if (iface->type_type == TYPE_DELEGATE)
+ {
+ iface = iface->details.delegate.iface;
+ iface->defined = TRUE;
+ }
compute_method_indexes(iface);
return iface;
}
@@ -807,6 +827,28 @@ void type_delegate_define(type_t *delegate, statement_list_t *stmts)
compute_delegate_iface_name(delegate);
}
+void type_parameterized_delegate_define(type_t *type, type_list_t *params, statement_list_t *stmts)
+{
+ type_t *delegate = make_type(TYPE_DELEGATE);
+ type_t *iface = make_type(TYPE_INTERFACE);
+
+ type->type_type = TYPE_PARAMETERIZED_TYPE;
+ type->details.parameterized.type = delegate;
+ type->details.parameterized.params = params;
+
+ delegate->details.delegate.iface = 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;
+}
+
void type_dispinterface_define(type_t *iface, var_list_t *props, var_list_t *methods)
{
iface->details.iface = xmalloc(sizeof(*iface->details.iface));
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h
index de3db4e7c7e..939bc5b412e 100644
--- a/tools/widl/typetree.h
+++ b/tools/widl/typetree.h
@@ -53,6 +53,7 @@ void type_parameterized_interface_declare(type_t *type, type_list_t *params);
void type_parameterized_interface_define(type_t *type, type_list_t *params, type_t *inherit, statement_list_t *stmts);
void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts, type_list_t *requires);
void type_delegate_define(type_t *iface, statement_list_t *stmts);
+void type_parameterized_delegate_define(type_t *type, type_list_t *params, 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);
--
2.28.0

View File

@ -0,0 +1,253 @@
From c98f225368cdeac02b7c67b14d1e448f80c645e4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Fri, 25 Sep 2020 13:39:08 +0200
Subject: [PATCH 25/28] widl: Compute signatures for parameterized types.
---
tools/widl/typetree.c | 155 +++++++++++++++++++++++++++++++++++++++++
tools/widl/typetree.h | 10 +++
tools/widl/widltypes.h | 2 +
3 files changed, 167 insertions(+)
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index 03778aa75c3..b3718b5dc6d 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -49,6 +49,7 @@ type_t *make_type(enum type_type type)
t->type_type = type;
t->attrs = NULL;
t->c_name = NULL;
+ t->signature = NULL;
memset(&t->details, 0, sizeof(t->details));
t->typestring_offset = 0;
t->ptrdesc = 0;
@@ -143,6 +144,142 @@ static int format_parameterized_type_c_name_buffer(char *buf, size_t len, type_t
return ret;
}
+static int format_type_signature_buffer(char *buf, size_t len, type_t *type);
+
+static int format_var_list_signature_buffer(char *buf, size_t len, var_list_t *var_list)
+{
+ var_t *var;
+ int ret = 0;
+ if (!var_list) append_buf(snprintf, ";");
+ else LIST_FOR_EACH_ENTRY(var, var_list, var_t, entry)
+ {
+ append_buf(snprintf, ";");
+ append_buf(format_type_signature_buffer, var->declspec.type);
+ }
+ return ret;
+}
+
+static int format_type_signature_buffer(char *buf, size_t len, type_t *type)
+{
+ const GUID *uuid;
+ int ret = 0;
+ if (!type) return 0;
+ switch (type->type_type)
+ {
+ case TYPE_INTERFACE:
+ if (type->signature) append_buf(snprintf, "%s", type->signature);
+ else
+ {
+ uuid = type_get_uuid(type);
+ append_buf(snprintf, "{%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 ret;
+ case TYPE_DELEGATE:
+ append_buf(snprintf, "delegate(");
+ append_buf(format_type_signature_buffer, type_delegate_get_iface(type));
+ append_buf(snprintf, ")");
+ return ret;
+ case TYPE_RUNTIMECLASS:
+ append_buf(snprintf, "rc(");
+ append_buf(format_namespace_buffer, type->namespace, "", ".", type->name, NULL);
+ append_buf(snprintf, ";");
+ append_buf(format_type_signature_buffer, type_runtimeclass_get_default_iface(type));
+ append_buf(snprintf, ")");
+ return ret;
+ case TYPE_POINTER:
+ return format_type_signature_buffer(buf, len, type->details.pointer.ref.type);
+ case TYPE_ALIAS:
+ if (!strcmp(type->name, "boolean")) append_buf(snprintf, "b1");
+ else ret = format_type_signature_buffer(buf, len, type->details.alias.aliasee.type);
+ return ret;
+ case TYPE_STRUCT:
+ append_buf(snprintf, "struct(");
+ append_buf(format_namespace_buffer, type->namespace, "", ".", type->name, NULL);
+ append_buf(format_var_list_signature_buffer, type->details.structure->fields);
+ append_buf(snprintf, ")");
+ return ret;
+ case TYPE_BASIC:
+ switch (type_basic_get_type(type))
+ {
+ case TYPE_BASIC_INT:
+ case TYPE_BASIC_INT32:
+ append_buf(snprintf, type_basic_get_sign(type) < 0 ? "i4" : "u4");
+ return ret;
+ case TYPE_BASIC_INT64:
+ append_buf(snprintf, type_basic_get_sign(type) < 0 ? "i8" : "u8");
+ return ret;
+ case TYPE_BASIC_INT8:
+ assert(type_basic_get_sign(type) >= 0); /* signature string for signed char isn't specified */
+ append_buf(snprintf, "u1");
+ return ret;
+ case TYPE_BASIC_FLOAT:
+ append_buf(snprintf, "f4");
+ return ret;
+ case TYPE_BASIC_DOUBLE:
+ append_buf(snprintf, "f8");
+ return ret;
+ case TYPE_BASIC_INT16:
+ case TYPE_BASIC_INT3264:
+ case TYPE_BASIC_LONG:
+ case TYPE_BASIC_CHAR:
+ case TYPE_BASIC_HYPER:
+ case TYPE_BASIC_BYTE:
+ case TYPE_BASIC_WCHAR:
+ case TYPE_BASIC_ERROR_STATUS_T:
+ case TYPE_BASIC_HANDLE:
+ error("basic type '%d' signature not implemented\n", type_basic_get_type(type));
+ assert(0); /* FIXME: implement when needed */
+ break;
+ }
+ case TYPE_ENUM:
+ append_buf(snprintf, "enum(");
+ append_buf(format_namespace_buffer, type->namespace, "", ".", type->name, NULL);
+ if (is_attr(type->attrs, ATTR_FLAGS)) append_buf(snprintf, ";u4");
+ else append_buf(snprintf, ";i4");
+ append_buf(snprintf, ")");
+ return ret;
+ case TYPE_ARRAY:
+ case TYPE_ENCAPSULATED_UNION:
+ case TYPE_UNION:
+ case TYPE_COCLASS:
+ error("type '%d' signature for '%s' not implemented\n", type->type_type, type->name);
+ assert(0); /* FIXME: implement when needed */
+ break;
+ case TYPE_VOID:
+ case TYPE_FUNCTION:
+ case TYPE_BITFIELD:
+ case TYPE_MODULE:
+ case TYPE_PARAMETERIZED_TYPE:
+ case TYPE_PARAMETER:
+ case TYPE_APICONTRACT:
+ assert(0); /* should not be there */
+ break;
+ }
+
+ return ret;
+}
+
+static int format_parameterized_type_signature_buffer(char *buf, size_t len, type_t *type, type_list_t *params)
+{
+ type_list_t *entry;
+ const GUID *uuid = type_get_uuid(type);
+ int ret = 0;
+ append_buf(snprintf, "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]);
+ for (entry = params; entry; entry = entry->next)
+ {
+ append_buf(snprintf, ";");
+ append_buf(format_type_signature_buffer, entry->type);
+ }
+ append_buf(snprintf, ")");
+ return ret;
+}
+
#undef append_buf
char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, const char *abi_prefix)
@@ -161,6 +298,14 @@ char *format_parameterized_type_name(type_t *type, type_list_t *params)
return buf;
}
+char *format_type_signature(type_t *type)
+{
+ int len = format_type_signature_buffer(NULL, 0, type);
+ char *buf = xmalloc(len + 1);
+ format_type_signature_buffer(buf, len + 1, type);
+ return buf;
+}
+
static char const *parameterized_type_shorthands[][2] = {
{"Windows_CFoundation_CCollections_C", "__F"},
{"Windows_CFoundation_C", "__F"},
@@ -186,6 +331,14 @@ static char *format_parameterized_type_c_name(type_t *type, type_list_t *params,
return buf;
}
+static char *format_parameterized_type_signature(type_t *type, type_list_t *params)
+{
+ int len = format_parameterized_type_signature_buffer(NULL, 0, type, params);
+ char *buf = xmalloc(len + 1);
+ format_parameterized_type_signature_buffer(buf, len + 1, type, params);
+ return buf;
+}
+
type_t *type_new_function(var_list_t *args)
{
var_t *arg;
@@ -752,10 +905,12 @@ type_t *type_parameterized_type_specialize_define(type_t *type, type_list_t *par
return NULL;
}
+ iface->signature = format_parameterized_type_signature(type, params);
iface->defined = TRUE;
if (iface->type_type == TYPE_DELEGATE)
{
iface = iface->details.delegate.iface;
+ iface->signature = format_parameterized_type_signature(type, params);
iface->defined = TRUE;
}
compute_method_indexes(iface);
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h
index 939bc5b412e..b4257fe615f 100644
--- a/tools/widl/typetree.h
+++ b/tools/widl/typetree.h
@@ -80,6 +80,16 @@ static inline enum type_type type_get_type(const type_t *type)
return type_get_type_detect_alias(type_get_real_type(type));
}
+static inline const GUID *type_get_uuid(const type_t *type)
+{
+ static const GUID empty;
+ attr_t *attr;
+ LIST_FOR_EACH_ENTRY(attr, type->attrs, attr_t, entry)
+ if (attr->type == ATTR_UUID) return attr->u.pval;
+ error("type '%s' uuid not found\n", type->name);
+ return &empty;
+}
+
static inline enum type_basic_type type_basic_get_type(const type_t *type)
{
type = type_get_real_type(type);
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 3938d0d5294..58828a4f8e2 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -496,6 +496,7 @@ struct _type_t {
struct delegate_details delegate;
} details;
const char *c_name;
+ const char *signature;
unsigned int typestring_offset;
unsigned int ptrdesc; /* used for complex structs */
int typelib_idx;
@@ -651,6 +652,7 @@ void init_loc_info(loc_info_t *);
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, type_list_t *params);
+char *format_type_signature(type_t *type);
static inline enum type_type type_get_type_detect_alias(const type_t *type)
{
--
2.28.0

View File

@ -0,0 +1,317 @@
From a8e1b96947308faf90d1686bf14743c5da7b90bd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 28 Sep 2020 17:00:41 +0200
Subject: [PATCH 26/28] widl: Compute uuids for parameterized types.
---
tools/widl/hash.c | 178 ++++++++++++++++++++++++++++++++++++++++++
tools/widl/hash.h | 14 ++++
tools/widl/typetree.c | 53 +++++++++++++
tools/widl/typetree.h | 2 +-
4 files changed, 246 insertions(+), 1 deletion(-)
diff --git a/tools/widl/hash.c b/tools/widl/hash.c
index 15ec88001d6..df6133866e0 100644
--- a/tools/widl/hash.c
+++ b/tools/widl/hash.c
@@ -639,3 +639,181 @@ 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 <steve@edmweb.com>
+ */
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+/* FIXME: This definition of DWORD2BE is little endian specific! */
+#define DWORD2BE(x) (((x) >> 24) & 0xff) | (((x) >> 8) & 0xff00) | (((x) << 8) & 0xff0000) | (((x) << 24) & 0xff000000);
+/* FIXME: This definition of blk0 is little endian specific! */
+#define blk0(i) (Block[i] = (rol(Block[i],24)&0xFF00FF00)|(rol(Block[i],8)&0x00FF00FF))
+#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 SHA1Transform(ULONG State[5], UCHAR Buffer[64])
+{
+ ULONG a, b, c, d, e;
+ ULONG *Block;
+
+ Block = (ULONG*)Buffer;
+
+ /* Copy Context->State[] to working variables */
+ a = State[0];
+ b = State[1];
+ c = State[2];
+ d = State[3];
+ e = 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 Context->State[] */
+ State[0] += a;
+ State[1] += b;
+ State[2] += c;
+ State[3] += d;
+ State[4] += e;
+
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+}
+
+
+/******************************************************************************
+ * A_SHAInit (ntdll.@)
+ *
+ * Initialize a SHA context structure.
+ *
+ * PARAMS
+ * Context [O] SHA context
+ *
+ * RETURNS
+ * Nothing
+ */
+void A_SHAInit(SHA_CTX *Context)
+{
+ /* SHA1 initialization constants */
+ Context->State[0] = 0x67452301;
+ Context->State[1] = 0xEFCDAB89;
+ Context->State[2] = 0x98BADCFE;
+ Context->State[3] = 0x10325476;
+ Context->State[4] = 0xC3D2E1F0;
+ Context->Count[0] =
+ Context->Count[1] = 0;
+}
+
+/******************************************************************************
+ * A_SHAUpdate (ntdll.@)
+ *
+ * Update a SHA context with a hashed data from supplied buffer.
+ *
+ * PARAMS
+ * Context [O] SHA context
+ * Buffer [I] hashed data
+ * BufferSize [I] hashed data size
+ *
+ * RETURNS
+ * Nothing
+ */
+void A_SHAUpdate(SHA_CTX *Context, const unsigned char *Buffer, UINT BufferSize)
+{
+ ULONG BufferContentSize;
+
+ BufferContentSize = Context->Count[1] & 63;
+ Context->Count[1] += BufferSize;
+ if (Context->Count[1] < BufferSize)
+ Context->Count[0]++;
+ Context->Count[0] += (BufferSize >> 29);
+
+ if (BufferContentSize + BufferSize < 64)
+ {
+ RtlCopyMemory(&Context->Buffer[BufferContentSize], Buffer,
+ BufferSize);
+ }
+ else
+ {
+ while (BufferContentSize + BufferSize >= 64)
+ {
+ RtlCopyMemory(Context->Buffer + BufferContentSize, Buffer,
+ 64 - BufferContentSize);
+ Buffer += 64 - BufferContentSize;
+ BufferSize -= 64 - BufferContentSize;
+ SHA1Transform(Context->State, Context->Buffer);
+ BufferContentSize = 0;
+ }
+ RtlCopyMemory(Context->Buffer + BufferContentSize, Buffer, BufferSize);
+ }
+}
+
+/******************************************************************************
+ * A_SHAFinal (ntdll.@)
+ *
+ * Finalize SHA context and return the resulting hash.
+ *
+ * PARAMS
+ * Context [I/O] SHA context
+ * Result [O] resulting hash
+ *
+ * RETURNS
+ * Nothing
+ */
+void A_SHAFinal(SHA_CTX *Context, PULONG Result)
+{
+ INT Pad, Index;
+ UCHAR Buffer[72];
+ ULONG *Count;
+ ULONG BufferContentSize, LengthHi, LengthLo;
+
+ BufferContentSize = Context->Count[1] & 63;
+ if (BufferContentSize >= 56)
+ Pad = 56 + 64 - BufferContentSize;
+ else
+ Pad = 56 - BufferContentSize;
+
+ LengthHi = (Context->Count[0] << 3) | (Context->Count[1] >> (32 - 3));
+ LengthLo = (Context->Count[1] << 3);
+
+ RtlZeroMemory(Buffer + 1, Pad - 1);
+ Buffer[0] = 0x80;
+ Count = (ULONG*)(Buffer + Pad);
+ Count[0] = DWORD2BE(LengthHi);
+ Count[1] = DWORD2BE(LengthLo);
+ A_SHAUpdate(Context, Buffer, Pad + 8);
+
+ for (Index = 0; Index < 5; Index++)
+ Result[Index] = DWORD2BE(Context->State[Index]);
+
+ A_SHAInit(Context);
+}
diff --git a/tools/widl/hash.h b/tools/widl/hash.h
index 3c2fd2914bf..208b193ac87 100644
--- a/tools/widl/hash.h
+++ b/tools/widl/hash.h
@@ -22,6 +22,20 @@
#ifndef __WIDL_HASH_H
#define __WIDL_HASH_H
+#include "windef.h"
+
extern unsigned int lhash_val_of_name_sys( syskind_t skind, LCID lcid, LPCSTR lpStr);
+typedef struct
+{
+ ULONG Unknown[6];
+ ULONG State[5];
+ ULONG Count[2];
+ UCHAR Buffer[64];
+} SHA_CTX;
+
+VOID A_SHAInit(SHA_CTX *ctx);
+VOID A_SHAUpdate(SHA_CTX *ctx, const UCHAR *buffer, UINT size);
+VOID A_SHAFinal(SHA_CTX *ctx, PULONG result);
+
#endif
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index b3718b5dc6d..2d060363d8e 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -29,6 +29,7 @@
#include "parser.h"
#include "typetree.h"
#include "header.h"
+#include "hash.h"
type_t *duptype(type_t *t, int dupname)
{
@@ -683,6 +684,57 @@ static void compute_delegate_iface_name(type_t *delegate)
delegate->details.delegate.iface->name = name;
}
+static void compute_interface_signature_uuid(type_t *iface)
+{
+ static unsigned char const wrt_pinterface_namespace[] = {0x11,0xf4,0x7a,0xd5,0x7b,0x73,0x42,0xc0,0xab,0xae,0x87,0x8b,0x1e,0x16,0xad,0xee};
+ static const int version = 5;
+ unsigned char hash[20];
+ SHA_CTX sha_ctx;
+ attr_t *attr;
+ GUID *uuid;
+
+ if (!iface->attrs)
+ {
+ iface->attrs = xmalloc( sizeof(*iface->attrs) );
+ list_init( iface->attrs );
+ }
+
+ LIST_FOR_EACH_ENTRY(attr, iface->attrs, attr_t, entry)
+ if (attr->type == ATTR_UUID) break;
+
+ if (&attr->entry == iface->attrs)
+ {
+ attr = xmalloc( sizeof(*attr) );
+ attr->type = ATTR_UUID;
+ attr->u.pval = xmalloc( sizeof(GUID) );
+ list_add_tail( iface->attrs, &attr->entry );
+ }
+
+ A_SHAInit(&sha_ctx);
+ A_SHAUpdate(&sha_ctx, wrt_pinterface_namespace, sizeof(wrt_pinterface_namespace));
+ A_SHAUpdate(&sha_ctx, (const UCHAR *)iface->signature, strlen(iface->signature));
+ A_SHAFinal(&sha_ctx, (ULONG *)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 = attr->u.pval;
+ uuid->Data1 = ((DWORD)hash[0] << 24)|((DWORD)hash[1] << 16)|((DWORD)hash[2] << 8)|(DWORD)hash[3];
+ uuid->Data2 = ((WORD)hash[4] << 8)|(WORD)hash[5];
+ uuid->Data3 = ((WORD)hash[6] << 8)|(WORD)hash[7];
+ memcpy(&uuid->Data4, hash + 8, sizeof(*uuid) - offsetof(GUID, Data4));
+}
+
static type_t *replace_type_parameters_in_type(type_t *type, type_list_t *orig, type_list_t *repl);
static type_list_t *replace_type_parameters_in_type_list(type_list_t *type_list, type_list_t *orig, type_list_t *repl)
@@ -913,6 +965,7 @@ type_t *type_parameterized_type_specialize_define(type_t *type, type_list_t *par
iface->signature = format_parameterized_type_signature(type, params);
iface->defined = TRUE;
}
+ compute_interface_signature_uuid(iface);
compute_method_indexes(iface);
return iface;
}
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h
index b4257fe615f..46a223d50e3 100644
--- a/tools/widl/typetree.h
+++ b/tools/widl/typetree.h
@@ -84,7 +84,7 @@ static inline const GUID *type_get_uuid(const type_t *type)
{
static const GUID empty;
attr_t *attr;
- LIST_FOR_EACH_ENTRY(attr, type->attrs, attr_t, entry)
+ if (type->attrs) LIST_FOR_EACH_ENTRY(attr, type->attrs, attr_t, entry)
if (attr->type == ATTR_UUID) return attr->u.pval;
error("type '%s' uuid not found\n", type->name);
return &empty;
--
2.28.0

View File

@ -0,0 +1,206 @@
From d517b9b5856840f19b3a805b812153d5c0f6d0d9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Wed, 26 Aug 2020 22:46:02 +0200
Subject: [PATCH 27/28] widl: Generate helper macros for WinRT implementation.
This generates additional macros to help keeping implementation simple,
guarded with WIDL_USING ifdefs, like this:
#ifdef WIDL_USING_WINDOWS_FOO_IFOO
#define IFooVtbl __x_ABI_CWindows_CFoo_CIFooVtbl
#define IFoo __x_ABI_CWindows_CFoo_CIFoo
#define IFoo_DoFoo __x_ABI_CWindows_CFoo_CIFoo_DoFoo
#endif /* WIDL_USING_WINDOWS_FOO_IFOO */
Implementation files can define the desired WIDL_USING preprocessor
macros before including the header, and then implement or use the
interface methods with the simple non-prefixed names instead.
---
tools/widl/header.c | 71 ++++++++++++++++++++++++++++++++++++++++--
tools/widl/typetree.c | 24 ++++++++++++++
tools/widl/widltypes.h | 1 +
3 files changed, 94 insertions(+), 2 deletions(-)
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 64faf89c36a..4aa6844ee99 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -50,6 +50,8 @@ static void write_winrt_type_comments(FILE *header, const type_t *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)
{
int c;
@@ -616,10 +618,11 @@ static void write_type_definition(FILE *f, type_t *t, int declonly)
t->written = save_written;
write_namespace_end(f, t->namespace);
fprintf(f, "extern \"C\" {\n");
- fprintf(f, "#else\n");
+ fprintf(f, "#else /* __cplusplus */\n");
write_type_left(f, &ds, NAME_C, declonly, TRUE);
fprintf(f, ";\n");
- fprintf(f, "#endif\n\n");
+ if (winrt_mode) write_widl_using_macros(f, t);
+ fprintf(f, "#endif /* __cplusplus */\n\n");
}
if (contract) write_apicontract_guard_end(f, contract);
}
@@ -1643,6 +1646,69 @@ static void write_com_interface_start(FILE *header, const type_t *iface)
fprintf(header,"#define __%s_%sINTERFACE_DEFINED__\n\n", iface->c_name, dispinterface ? "DISP" : "");
}
+static char *get_winrt_guard_macro(type_t *iface)
+{
+ unsigned int len;
+ char *macro, *tmp = (char *)iface->c_name;
+ int i;
+
+ if (!strncmp(tmp, "__x", 3)) tmp += 3;
+ if (!strncmp(tmp, "_ABI", 4)) tmp += 4;
+ macro = xstrdup(tmp);
+
+ len = strlen(macro) + 1;
+ for (tmp = strstr(macro, "__F"); tmp; tmp = strstr(tmp, "__F"))
+ memmove(tmp + 1, tmp + 3, len - (tmp - macro) - 3);
+ for (tmp = strstr(macro, "__C"); tmp; tmp = strstr(tmp, "__C"))
+ memmove(tmp + 1, tmp + 3, len - (tmp - macro) - 3);
+ for (tmp = strstr(macro, "_C"); tmp; tmp = strstr(tmp, "_C"))
+ memmove(tmp + 1, tmp + 2, len - (tmp - macro) - 2);
+
+ for (i = strlen(macro); i > 0; --i) macro[i - 1] = toupper(macro[i - 1]);
+
+ return macro;
+}
+
+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 = get_name(func);
+
+ if (is_override_method(iface, top_iface, func)) continue;
+
+ if (!is_callas(func->attrs))
+ 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 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 = get_winrt_guard_macro(iface);
+ fprintf(header, "#ifdef WIDL_USING%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 /* WIDL_USING_%s */\n", macro);
+ free(macro);
+}
+
static void write_com_interface_end(FILE *header, type_t *iface)
{
int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE);
@@ -1715,6 +1781,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");
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index 2d060363d8e..f62d0eb51dc 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -51,6 +51,7 @@ type_t *make_type(enum type_type type)
t->attrs = NULL;
t->c_name = NULL;
t->signature = NULL;
+ t->short_name = NULL;
memset(&t->details, 0, sizeof(t->details));
t->typestring_offset = 0;
t->ptrdesc = 0;
@@ -281,6 +282,19 @@ static int format_parameterized_type_signature_buffer(char *buf, size_t len, typ
return ret;
}
+static int format_parameterized_type_short_name_buffer(char *buf, size_t len, type_t *type, type_list_t *params, const char *prefix)
+{
+ type_list_t *entry;
+ int ret = 0;
+ append_buf(snprintf, "%s%s", prefix, type->name);
+ for (entry = params; entry; entry = entry->next)
+ {
+ for (type = entry->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) {}
+ append_buf(snprintf, "_%s", type->name);
+ }
+ return ret;
+}
+
#undef append_buf
char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, const char *abi_prefix)
@@ -340,6 +354,14 @@ static char *format_parameterized_type_signature(type_t *type, type_list_t *para
return buf;
}
+static char *format_parameterized_type_short_name(type_t *type, type_list_t *params, const char *prefix)
+{
+ int len = format_parameterized_type_short_name_buffer(NULL, 0, type, params, prefix);
+ char *buf = xmalloc(len + 1);
+ format_parameterized_type_short_name_buffer(buf, len + 1, type, params, prefix);
+ return buf;
+}
+
type_t *type_new_function(var_list_t *args)
{
var_t *arg;
@@ -929,6 +951,7 @@ type_t *type_parameterized_type_specialize_declare(type_t *type, type_list_t *pa
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, "");
+ new_type->short_name = format_parameterized_type_short_name(type, params, "");
if (new_type->type_type == TYPE_DELEGATE)
{
@@ -936,6 +959,7 @@ type_t *type_parameterized_type_specialize_declare(type_t *type, type_list_t *pa
compute_delegate_iface_name(new_type);
new_type->details.delegate.iface->namespace = new_type->namespace;
new_type->details.delegate.iface->c_name = format_parameterized_type_c_name(type, params, "I");
+ new_type->details.delegate.iface->short_name = format_parameterized_type_short_name(type, params, "I");
}
return new_type;
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 58828a4f8e2..d80e9c04d51 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -497,6 +497,7 @@ struct _type_t {
} details;
const char *c_name;
const char *signature;
+ const char *short_name;
unsigned int typestring_offset;
unsigned int ptrdesc; /* used for complex structs */
int typelib_idx;
--
2.28.0

View File

@ -0,0 +1,29 @@
From 5609ada48132040965e84cdbdd95cea9492a471d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Fri, 25 Sep 2020 17:05:17 +0200
Subject: [PATCH 28/28] include: Add IVectorView<HSTRING> declaration to
windows.foundation.idl.
---
include/windows.foundation.idl | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl
index 9583fa5bcc8..9b9b40897be 100644
--- a/include/windows.foundation.idl
+++ b/include/windows.foundation.idl
@@ -157,3 +157,11 @@ namespace Windows {
#endif
}
}
+
+namespace Windows {
+ namespace Foundation {
+ declare {
+ interface Windows.Foundation.Collections.IVectorView<HSTRING>;
+ }
+ }
+}
--
2.28.0

View File

@ -0,0 +1 @@
Fixes: [68403] widl - Support WinRT idls

View File

@ -1,2 +1,3 @@
Fixes: [49740] windows.globalization: New DLL
Depends: windows.media.speech.dll
Disabled: True

View File

@ -1,2 +1,3 @@
Fixes: [46534] windows.networking.connectivity: New DLL
Depends: windows.globalization-dll
Disabled: True