[PATCH 5/5] widl: Generate helper macros for WinRT implementation.

Rémi Bernon rbernon at codeweavers.com
Fri Feb 19 05:04:01 CST 2021


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.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 tools/widl/header.c    | 68 ++++++++++++++++++++++++++++++++++++++++++
 tools/widl/typetree.c  | 19 ++++++++++++
 tools/widl/widltypes.h |  1 +
 3 files changed, 88 insertions(+)

diff --git a/tools/widl/header.c b/tools/widl/header.c
index 82aad0f11ca..8ca74d5a6f4 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -48,6 +48,8 @@ static void write_type_v(FILE *f, const decl_spec_t *t, int is_field, int declon
 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;
@@ -604,6 +606,7 @@ static void write_type_definition(FILE *f, type_t *t, int declonly)
         fprintf(f, "#else\n");
         write_type_left(f, &ds, NAME_C, declonly, TRUE);
         fprintf(f, ";\n");
+        if (winrt_mode) write_widl_using_macros(f, t);
         fprintf(f, "#endif\n\n");
     }
     if (contract) write_apicontract_guard_end(f, contract);
@@ -1536,6 +1539,70 @@ 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;
+
+        if (is_override_method(iface, top_iface, func)) continue;
+        if (is_callas(func->attrs)) continue;
+
+        func_name = get_name(func);
+        fprintf(header, "#define %s_%s %s_%s\n", name, func_name, top_iface->c_name, func_name);
+    }
+}
+
+static void write_widl_using_macros(FILE *header, type_t *iface)
+{
+    const 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);
@@ -1608,6 +1675,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 319dd4ae65a..8bce314018a 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -52,6 +52,7 @@ type_t *make_type(enum type_type type)
     t->c_name = NULL;
     t->signature = NULL;
     t->qualified_name = NULL;
+    t->short_name = NULL;
     memset(&t->details, 0, sizeof(t->details));
     t->typestring_offset = 0;
     t->ptrdesc = 0;
@@ -334,6 +335,22 @@ static char *format_parameterized_type_signature(type_t *type, typeref_list_t *p
     return buf;
 }
 
+static char *format_parameterized_type_short_name(type_t *type, typeref_list_t *params, const char *prefix)
+{
+    size_t len = 0, pos = 0;
+    char *buf = NULL;
+    typeref_t *ref;
+
+    pos += strappend(&buf, &len, pos, "%s%s", prefix, type->name);
+    if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry)
+    {
+        for (type = ref->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) {}
+        pos += strappend(&buf, &len, pos, "_%s", type->name);
+    }
+
+    return buf;
+}
+
 type_t *type_new_function(var_list_t *args)
 {
     var_t *arg;
@@ -1151,11 +1168,13 @@ type_t *type_parameterized_type_specialize_declare(type_t *type, typeref_list_t
     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)
     {
         new_type->details.delegate.iface = duptype(tmpl->details.delegate.iface, 0);
         compute_delegate_iface_names(new_type, type, params);
+        new_type->details.delegate.iface->short_name = format_parameterized_type_short_name(type, params, "I");
     }
 
     return new_type;
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 81646cae1d1..bedba40d903 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -504,6 +504,7 @@ struct _type_t {
   const char *c_name;
   const char *signature;
   const char *qualified_name;
+  const char *short_name;
   unsigned int typestring_offset;
   unsigned int ptrdesc;           /* used for complex structs */
   int typelib_idx;
-- 
2.30.0




More information about the wine-devel mailing list