From 88987c0a9500f2a3f86080baad2d8764a26defcd Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Fri, 7 Aug 2015 15:41:55 +0200 Subject: [PATCH] widl: Added support for namespaced enums. --- tools/widl/header.c | 58 ++++++++++++++++++++++++++++++++----------- tools/widl/header.h | 2 +- tools/widl/parser.y | 14 +++++------ tools/widl/typegen.c | 6 ++--- tools/widl/typetree.c | 20 ++++++++++++--- tools/widl/typetree.h | 8 +++++- 6 files changed, 79 insertions(+), 29 deletions(-) diff --git a/tools/widl/header.c b/tools/widl/header.c index 866e3c1ac03..29b622e9c9b 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -256,7 +256,7 @@ static void write_fields(FILE *h, var_list_t *fields) } } -static void write_enums(FILE *h, var_list_t *enums) +static void write_enums(FILE *h, var_list_t *enums, const char *enum_name) { var_t *v; if (!enums) return; @@ -264,7 +264,10 @@ static void write_enums(FILE *h, var_list_t *enums) { if (v->name) { indent(h, 0); - fprintf(h, "%s", get_name(v)); + if(!enum_name) + fprintf(h, "%s", get_name(v)); + else + fprintf(h, "%s_%s", enum_name, get_name(v)); if (v->eval) { fprintf(h, " = "); write_expr(h, v->eval, 0, 1, NULL, NULL, ""); @@ -281,10 +284,14 @@ int needs_space_after(type_t *t) (!is_ptr(t) && (!is_array(t) || !type_array_is_decl_as_ptr(t) || t->name))); } -void write_type_left(FILE *h, type_t *t, int declonly) +void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly) { + const char *name; + if (!h) return; + name = type_get_name(t, name_type); + if (is_attr(t->attrs, ATTR_CONST) && (type_is_alias(t) || !is_ptr(t))) fprintf(h, "const "); @@ -294,15 +301,15 @@ void write_type_left(FILE *h, type_t *t, int declonly) switch (type_get_type_detect_alias(t)) { case TYPE_ENUM: if (!declonly && t->defined && !t->written) { - if (t->name) fprintf(h, "enum %s {\n", t->name); + if (name) fprintf(h, "enum %s {\n", name); else fprintf(h, "enum {\n"); t->written = TRUE; indentation++; - write_enums(h, type_enum_get_values(t)); + write_enums(h, type_enum_get_values(t), is_global_namespace(t->namespace) ? NULL : t->name); indent(h, -1); fprintf(h, "}"); } - else fprintf(h, "enum %s", t->name ? t->name : ""); + else fprintf(h, "enum %s", name ? name : ""); break; case TYPE_STRUCT: case TYPE_ENCAPSULATED_UNION: @@ -333,7 +340,7 @@ void write_type_left(FILE *h, type_t *t, int declonly) else fprintf(h, "union %s", t->name ? t->name : ""); break; case TYPE_POINTER: - write_type_left(h, type_pointer_get_ref(t), declonly); + write_type_left(h, type_pointer_get_ref(t), name_type, declonly); fprintf(h, "%s*", needs_space_after(type_pointer_get_ref(t)) ? " " : ""); if (is_attr(t->attrs, ATTR_CONST)) fprintf(h, "const "); break; @@ -342,7 +349,7 @@ void write_type_left(FILE *h, type_t *t, int declonly) fprintf(h, "%s", t->name); else { - write_type_left(h, type_array_get_element(t), declonly); + write_type_left(h, type_array_get_element(t), name_type, declonly); if (type_array_is_decl_as_ptr(t)) fprintf(h, "%s*", needs_space_after(type_array_get_element(t)) ? " " : ""); } @@ -397,7 +404,7 @@ void write_type_left(FILE *h, type_t *t, int declonly) fprintf(h, "void"); break; case TYPE_BITFIELD: - write_type_left(h, type_bitfield_get_field(t), declonly); + write_type_left(h, type_bitfield_get_field(t), name_type, declonly); break; case TYPE_ALIAS: case TYPE_FUNCTION: @@ -463,14 +470,14 @@ static void write_type_v(FILE *h, type_t *t, int is_field, int declonly, const c const char *callconv = get_attrp(pt->attrs, ATTR_CALLCONV); if (!callconv && is_object_interface) callconv = "STDMETHODCALLTYPE"; if (is_attr(pt->attrs, ATTR_INLINE)) fprintf(h, "inline "); - write_type_left(h, type_function_get_rettype(pt), declonly); + write_type_left(h, type_function_get_rettype(pt), NAME_DEFAULT, declonly); fputc(' ', h); if (ptr_level) fputc('(', h); if (callconv) fprintf(h, "%s ", callconv); for (i = 0; i < ptr_level; i++) fputc('*', h); } else - write_type_left(h, t, declonly); + write_type_left(h, t, NAME_DEFAULT, declonly); } if (name) fprintf(h, "%s%s", !t || needs_space_after(t) ? " " : "", name ); @@ -496,6 +503,30 @@ static void write_type_def_or_decl(FILE *f, type_t *t, int field, const char *na write_type_v(f, t, field, FALSE, name); } +static void write_type_definition(FILE *f, type_t *t) +{ + int in_namespace = t->namespace && !is_global_namespace(t->namespace); + int save_written = t->written; + + if(in_namespace) { + fprintf(f, "#ifdef __cplusplus\n"); + fprintf(f, "} /* extern \"C\" */\n"); + write_namespace_start(f, t->namespace); + } + indent(f, 0); + write_type_left(f, t, NAME_DEFAULT, FALSE); + fprintf(f, ";\n"); + if(in_namespace) { + t->written = save_written; + write_namespace_end(f, t->namespace); + fprintf(f, "extern \"C\" {\n"); + fprintf(f, "#else\n"); + write_type_left(f, t, NAME_C, FALSE); + fprintf(f, ";\n"); + fprintf(f, "#endif\n\n"); + } +} + void write_type_decl(FILE *f, type_t *t, const char *name) { write_type_v(f, t, FALSE, TRUE, name); @@ -503,7 +534,7 @@ void write_type_decl(FILE *f, type_t *t, const char *name) void write_type_decl_left(FILE *f, type_t *t) { - write_type_left(f, t, TRUE); + write_type_left(f, t, NAME_DEFAULT, TRUE); } static int user_type_registered(const char *name) @@ -1539,8 +1570,7 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons write_coclass(header, stmt->u.type); else { - write_type_def_or_decl(header, stmt->u.type, FALSE, NULL); - fprintf(header, ";\n\n"); + write_type_definition(header, stmt->u.type); } break; case STMT_TYPEREF: diff --git a/tools/widl/header.h b/tools/widl/header.h index 10601ff734e..3798af06321 100644 --- a/tools/widl/header.h +++ b/tools/widl/header.h @@ -29,7 +29,7 @@ extern int is_attr(const attr_list_t *list, enum attr_type t); extern void *get_attrp(const attr_list_t *list, enum attr_type t); extern unsigned int get_attrv(const attr_list_t *list, enum attr_type t); extern const char* get_name(const var_t *v); -extern void write_type_left(FILE *h, type_t *t, int declonly); +extern void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly); extern void write_type_right(FILE *h, type_t *t, int is_field); extern void write_type_decl(FILE *f, type_t *t, const char *name); extern void write_type_decl_left(FILE *f, type_t *t); diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 0a149b01f1c..725cd3b6329 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -378,7 +378,7 @@ statement: typedecl: enumdef - | tENUM aIDENTIFIER { $$ = type_new_enum($2, FALSE, NULL); } + | tENUM aIDENTIFIER { $$ = type_new_enum($2, current_namespace, FALSE, NULL); } | structdef | tSTRUCT aIDENTIFIER { $$ = type_new_struct($2, FALSE, NULL); } | uniondef @@ -633,7 +633,7 @@ enum: ident '=' expr_int_const { $$ = reg_const($1); } ; -enumdef: tENUM t_ident '{' enums '}' { $$ = type_new_enum($2, TRUE, $4); } +enumdef: tENUM t_ident '{' enums '}' { $$ = type_new_enum($2, current_namespace, TRUE, $4); } ; m_exprs: m_expr { $$ = append_expr( NULL, $1 ); } @@ -1098,7 +1098,7 @@ type: tVOID { $$ = type_new_void(); } | aKNOWNTYPE { $$ = find_type_or_error($1, 0); } | base_type { $$ = $1; } | enumdef { $$ = $1; } - | tENUM aIDENTIFIER { $$ = type_new_enum($2, FALSE, NULL); } + | tENUM aIDENTIFIER { $$ = type_new_enum($2, current_namespace, FALSE, NULL); } | structdef { $$ = $1; } | tSTRUCT aIDENTIFIER { $$ = type_new_struct($2, FALSE, NULL); } | uniondef { $$ = $1; } @@ -1809,6 +1809,10 @@ type_t *reg_type(type_t *type, const char *name, struct namespace *namespace, in hash = hash_ident(name); nt = xmalloc(sizeof(struct rtype)); nt->name = name; + if (is_global_namespace(namespace)) + type->c_name = name; + else + type->c_name = format_namespace(namespace, "__x_", "_C", name); nt->type = type; nt->t = t; nt->next = namespace->type_hash[hash]; @@ -1983,10 +1987,6 @@ type_t *get_type(enum type_type type, char *name, struct namespace *namespace, i tp = make_type(type); tp->name = name; tp->namespace = namespace; - if (is_global_namespace(namespace)) - tp->c_name = name; - else - tp->c_name = format_namespace(namespace, "__x_", "_C", name); if (!name) return tp; return reg_type(tp, name, namespace, t); } diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 045a5b74c54..e63600c71b7 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -4735,7 +4735,7 @@ void write_func_param_struct( FILE *file, const type_t *iface, const type_t *fun if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) { print_file(file, 2, "%s", ""); - write_type_left( file, (type_t *)arg->type, TRUE ); + write_type_left( file, (type_t *)arg->type, NAME_DEFAULT, TRUE ); if (needs_space_after( arg->type )) fputc( ' ', file ); if (is_array( arg->type ) && !type_array_is_decl_as_ptr( arg->type )) fputc( '*', file ); @@ -4800,9 +4800,9 @@ int write_expr_eval_routines(FILE *file, const char *iface) else { print_file(file, 1, "%s", ""); - write_type_left(file, (type_t *)eval->cont_type, TRUE); + write_type_left(file, (type_t *)eval->cont_type, NAME_DEFAULT, TRUE); fprintf(file, " *%s = (", var_name); - write_type_left(file, (type_t *)eval->cont_type, TRUE); + write_type_left(file, (type_t *)eval->cont_type, NAME_DEFAULT, TRUE); fprintf(file, " *)(pStubMsg->StackTop - %u);\n", eval->baseoff); } print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */ diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index 15b7c737a37..3f8ced35ee2 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -78,6 +78,19 @@ static const var_t *find_arg(const var_list_t *args, const char *name) return NULL; } +const char *type_get_name(const type_t *type, enum name_type name_type) +{ + switch(name_type) { + case NAME_DEFAULT: + return type->name; + case NAME_C: + return type->c_name; + } + + assert(0); + return NULL; +} + static char *append_namespace(char *ptr, struct namespace *namespace, const char *separator) { if(is_global_namespace(namespace)) { @@ -258,11 +271,12 @@ type_t *type_new_void(void) return void_type; } -type_t *type_new_enum(const char *name, int defined, var_list_t *enums) +type_t *type_new_enum(const char *name, struct namespace *namespace, int defined, var_list_t *enums) { - type_t *tag_type = name ? find_type(name, NULL, tsENUM) : NULL; + type_t *tag_type = name ? find_type(name, namespace, tsENUM) : NULL; type_t *t = make_type(TYPE_ENUM); t->name = name; + t->namespace = namespace; if (tag_type && tag_type->details.enumeration) t->details.enumeration = tag_type->details.enumeration; @@ -276,7 +290,7 @@ type_t *type_new_enum(const char *name, int defined, var_list_t *enums) if (name) { if (defined) - reg_type(t, name, NULL, tsENUM); + reg_type(t, name, namespace, tsENUM); else add_incomplete(t); } diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h index 1e7ed88951a..873ba8a8915 100644 --- a/tools/widl/typetree.h +++ b/tools/widl/typetree.h @@ -24,6 +24,11 @@ #ifndef WIDL_TYPE_TREE_H #define WIDL_TYPE_TREE_H +enum name_type { + NAME_DEFAULT, + NAME_C +}; + type_t *type_new_function(var_list_t *args); type_t *type_new_pointer(unsigned char pointer_default, type_t *ref, attr_list_t *attrs); type_t *type_new_alias(type_t *t, const char *name); @@ -35,7 +40,7 @@ type_t *type_new_basic(enum type_basic_type basic_type); type_t *type_new_int(enum type_basic_type basic_type, int sign); type_t *type_new_void(void); type_t *type_new_coclass(char *name); -type_t *type_new_enum(const char *name, int defined, var_list_t *enums); +type_t *type_new_enum(const char *name, struct namespace *namespace, int defined, var_list_t *enums); type_t *type_new_struct(char *name, int defined, var_list_t *fields); type_t *type_new_nonencapsulated_union(const char *name, int defined, var_list_t *fields); type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *union_field, var_list_t *cases); @@ -46,6 +51,7 @@ 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); 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); /* FIXME: shouldn't need to export this */ type_t *duptype(type_t *t, int dupname);