widl function pointers
Ove Kaaven
ovek at arcticnet.no
Wed Feb 11 09:29:59 CST 2004
This implements full function pointer support in widl. Alexandre's
previous patch for it didn't seem like it would know the difference
between int* (*pfn)() and int (**pfn)(), so I've done it differently
(and allowed function pointers in structure fields and typedefs while I
was at it); hence, this patch reverses his patch and implements my way
instead.
Incidentally, that means I also reversed his indentation suppression of
the arguments of these function pointers, but I don't see the "old"
indentation as a problem - after all, MIDL does not suppress indentation
of function pointer arguments, why should widl?
But I could probably submit a patch with Alexandre's indentation changes
preserved if he's really attached to it.
Log:
Implement proper function pointer support.
Index: header.c
===================================================================
RCS file: /home/wine/wine/tools/widl/header.c,v
retrieving revision 1.20
diff -u -r1.20 header.c
--- header.c 7 Jan 2004 04:21:27 -0000 1.20
+++ header.c 11 Feb 2004 15:14:41 -0000
@@ -120,27 +120,39 @@
if (!v) return;
if (v->type) {
indent(0);
- write_type(h, v->type, NULL, v->tname);
- if (get_name(v)) {
- fprintf(h, " ");
+ if (v->type->funcs && !v->type->type) {
+ /* function pointer */
+ var_t *def = v->type->funcs->def;
+ write_type(h, def->type, def, def->tname);
+ fprintf(h, " (STDMETHODCALLTYPE ");
write_pident(h, v);
+ fprintf(h, ")(\n");
+ write_args(h, v->type->funcs->args, NULL, 0);
+ fprintf(h, ")");
}
else {
- /* not all C/C++ compilers support anonymous structs and unions */
- switch (v->type->type) {
- case RPC_FC_STRUCT:
- case RPC_FC_ENCAPSULATED_UNION:
- fprintf(h, " DUMMYSTRUCTNAME");
- break;
- case RPC_FC_NON_ENCAPSULATED_UNION:
- fprintf(h, " DUMMYUNIONNAME");
- break;
- default:
- /* ? */
- break;
+ write_type(h, v->type, NULL, v->tname);
+ if (get_name(v)) {
+ fprintf(h, " ");
+ write_pident(h, v);
}
+ else {
+ /* not all C/C++ compilers support anonymous structs and unions */
+ switch (v->type->type) {
+ case RPC_FC_STRUCT:
+ case RPC_FC_ENCAPSULATED_UNION:
+ fprintf(h, " DUMMYSTRUCTNAME");
+ break;
+ case RPC_FC_NON_ENCAPSULATED_UNION:
+ fprintf(h, " DUMMYUNIONNAME");
+ break;
+ default:
+ /* ? */
+ break;
+ }
+ }
+ write_array(h, v->array, 1);
}
- write_array(h, v->array, 1);
fprintf(h, ";\n");
}
}
@@ -290,13 +302,26 @@
while (NEXT_LINK(names)) names = NEXT_LINK(names);
lname = names;
fprintf(header, "typedef ");
- write_type(header, type, NULL, tname);
- fprintf(header, " ");
- while (names) {
+ if (type->funcs && !type->type) {
+ /* function pointer */
+ var_t *def = type->funcs->def;
+ write_type(header, def->type, def, def->tname);
+ fprintf(header, " (STDMETHODCALLTYPE ");
write_pident(header, names);
- if (PREV_LINK(names))
- fprintf(header, ", ");
- names = PREV_LINK(names);
+ fprintf(header, ")(\n");
+ write_args(header, type->funcs->args, NULL, 0);
+ fprintf(header, ")");
+ if (PREV_LINK(names)) yyerror("can't emit more than one function pointer per typedef\n");
+ }
+ else {
+ write_type(header, type, NULL, tname);
+ fprintf(header, " ");
+ while (names) {
+ write_pident(header, names);
+ if (PREV_LINK(names))
+ fprintf(header, ", ");
+ names = PREV_LINK(names);
+ }
}
fprintf(header, ";\n");
@@ -449,19 +474,8 @@
fprintf(header, ")(%s", arg ? "THIS_ " : "THIS" );
while (arg) {
write_type(header, arg->type, arg, arg->tname);
- if (arg->args)
- {
- fprintf(header, " (STDMETHODCALLTYPE *");
- write_name(header,arg);
- fprintf( header,")(");
- write_args(header, arg->args, NULL, 0, FALSE);
- fprintf(header,")");
- }
- else
- {
- fprintf(header, " ");
- write_name(header,arg);
- }
+ fprintf(header, " ");
+ write_name(header,arg);
write_array(header, arg->array, 0);
arg = PREV_LINK(arg);
if (arg) fprintf(header, ", ");
@@ -517,53 +531,47 @@
return idx;
}
-void write_args(FILE *h, var_t *arg, char *name, int method, int do_indent)
+void write_args(FILE *h, var_t *arg, char *name, int method)
{
int count = 0;
if (arg) {
while (NEXT_LINK(arg))
arg = NEXT_LINK(arg);
}
- if (do_indent)
- {
- if (h == header) {
- indentation++;
- indent(0);
- } else fprintf(h, " ");
- }
+ if (h == header) {
+ indentation++;
+ indent(0);
+ } else fprintf(h, " ");
if (method == 1) {
fprintf(h, "%s* This", name);
count++;
}
while (arg) {
if (count) {
- if (do_indent)
- {
- fprintf(h, ",\n");
- if (h == header) indent(0);
- else fprintf(h, " ");
- }
- else fprintf(h, ",");
+ fprintf(h, ",\n");
+ if (h == header) indent(0);
+ else fprintf(h, " ");
}
- write_type(h, arg->type, arg, arg->tname);
- if (arg->args)
- {
- fprintf(h, " (STDMETHODCALLTYPE *");
- write_name(h,arg);
- fprintf(h, ")(");
- write_args(h, arg->args, NULL, 0, FALSE);
+ if (arg->type->funcs && !arg->type->type) {
+ /* function pointer */
+ var_t *def = arg->type->funcs->def;
+ write_type(h, def->type, def, def->tname);
+ fprintf(h, " (STDMETHODCALLTYPE ");
+ write_pident(h, arg);
+ fprintf(h, ")(\n");
+ write_args(h, arg->type->funcs->args, NULL, 0);
fprintf(h, ")");
}
- else
- {
+ else {
+ write_type(h, arg->type, arg, arg->tname);
fprintf(h, " ");
write_name(h, arg);
+ write_array(h, arg->array, 0);
}
- write_array(h, arg->array, 0);
arg = PREV_LINK(arg);
count++;
}
- if (do_indent && h == header) indentation--;
+ if (h == header) indentation--;
}
static void write_cpp_method_def(type_t *iface)
@@ -581,7 +589,7 @@
fprintf(header, " STDMETHODCALLTYPE ");
write_name(header, def);
fprintf(header, "(\n");
- write_args(header, cur->args, iface->name, 2, TRUE);
+ write_args(header, cur->args, iface->name, 2);
fprintf(header, ") = 0;\n");
fprintf(header, "\n");
}
@@ -607,7 +615,7 @@
fprintf(header, " (STDMETHODCALLTYPE *");
write_name(header, def);
fprintf(header, ")(\n");
- write_args(header, cur->args, name, 1, TRUE);
+ write_args(header, cur->args, name, 1);
fprintf(header, ");\n");
fprintf(header, "\n");
}
@@ -635,7 +643,7 @@
fprintf(header, " CALLBACK %s_", iface->name);
write_name(header, def);
fprintf(header, "_Proxy(\n");
- write_args(header, cur->args, iface->name, 1, TRUE);
+ write_args(header, cur->args, iface->name, 1);
fprintf(header, ");\n");
/* stub prototype */
fprintf(header, "void __RPC_STUB %s_", iface->name);
@@ -657,14 +665,14 @@
fprintf(header, " CALLBACK %s_", iface->name);
write_name(header, mdef);
fprintf(header, "_Proxy(\n");
- write_args(header, m->args, iface->name, 1, TRUE);
+ write_args(header, m->args, iface->name, 1);
fprintf(header, ");\n");
/* stub prototype - use remotable prototype */
write_type(header, def->type, def, def->tname);
fprintf(header, " __RPC_STUB %s_", iface->name);
write_name(header, mdef);
fprintf(header, "_Stub(\n");
- write_args(header, cur->args, iface->name, 1, TRUE);
+ write_args(header, cur->args, iface->name, 1);
fprintf(header, ");\n");
}
else {
@@ -687,7 +695,7 @@
fprintf(header, " ");
write_name(header, def);
fprintf(header, "(\n");
- write_args(header, cur->args, iface->name, 0, TRUE);
+ write_args(header, cur->args, iface->name, 0);
fprintf(header, ");\n");
cur = PREV_LINK(cur);
Index: header.h
===================================================================
RCS file: /home/wine/wine/tools/widl/header.h,v
retrieving revision 1.5
diff -u -r1.5 header.h
--- header.h 7 Jan 2004 04:21:27 -0000 1.5
+++ header.h 11 Feb 2004 15:14:41 -0000
@@ -31,7 +31,7 @@
extern int is_object(attr_t *a);
extern int is_local(attr_t *a);
extern var_t *is_callas(attr_t *a);
-extern void write_args(FILE *h, var_t *arg, char *name, int obj, int do_indent);
+extern void write_args(FILE *h, var_t *arg, char *name, int obj);
extern void write_forward(type_t *iface);
extern void write_interface(type_t *iface);
extern void write_typedef(type_t *type, var_t *names);
Index: parser.y
===================================================================
RCS file: /home/wine/wine/tools/widl/parser.y,v
retrieving revision 1.12
diff -u -r1.12 parser.y
--- parser.y 7 Jan 2004 04:21:27 -0000 1.12
+++ parser.y 11 Feb 2004 15:14:41 -0000
@@ -184,9 +184,10 @@
%type <type> enumdef structdef typedef uniondef
%type <ifref> gbl_statements coclass_ints coclass_int
%type <tref> type
-%type <var> m_args no_args args arg
-%type <var> fields field s_field cases case enums enum_list enum constdef externdef
+%type <var> m_args no_args args arg_list var_spec
+%type <var> fields field cases case enums enum_list enum constdef externdef
%type <var> m_ident t_ident ident p_ident pident pident_list
+%type <var> funcptr p_funcptr pfuncptr
%type <var> dispint_props
%type <func> funcdef int_statements
%type <func> dispint_meths
@@ -265,29 +266,28 @@
no_args: tVOID { $$ = NULL; }
;
-args: arg
- | args ',' arg { LINK($3, $1); $$ = $3; }
+args: arg_list
| no_args
;
+arg_list: var_spec
+ | args ',' var_spec { LINK($3, $1); $$ = $3; }
+ ;
+
/* split into two rules to get bison to resolve a tVOID conflict */
-arg: attributes type pident array { $$ = $3;
+var_spec: attributes type pident array { $$ = $3;
set_type($$, $2, $4);
$$->attrs = $1;
}
| type pident array { $$ = $2;
set_type($$, $1, $3);
}
- | attributes type pident '(' m_args ')' { $$ = $3;
- $$->ptr_level--;
- set_type($$, $2, NULL);
+ | attributes type pfuncptr { $$ = $3;
+ set_type($$->type->funcs->def, $2, NULL);
$$->attrs = $1;
- $$->args = $5;
}
- | type pident '(' m_args ')' { $$ = $2;
- $$->ptr_level--;
- set_type($$, $1, NULL);
- $$->args = $4;
+ | type pfuncptr { $$ = $2;
+ set_type($$->type->funcs->def, $1, NULL);
}
;
@@ -331,6 +331,7 @@
| tIDEMPOTENT { $$ = make_attr(ATTR_IDEMPOTENT); }
| tIIDIS '(' ident ')' { $$ = make_attrp(ATTR_IIDIS, $3); }
| tIN { $$ = make_attr(ATTR_IN); }
+ | tINPUTSYNC { $$ = make_attr(ATTR_INPUTSYNC); }
| tLENGTHIS '(' m_exprs ')' { $$ = make_attrp(ATTR_LENGTHIS, $3); }
| tLOCAL { $$ = make_attr(ATTR_LOCAL); }
| tOBJECT { $$ = make_attr(ATTR_OBJECT); }
@@ -464,15 +465,15 @@
}
;
-field: s_field ';' { $$ = $1; }
- | m_attributes uniondef ';' { $$ = make_var(NULL); $$->type = $2; $$->attrs = $1; }
+field: var_spec ';' { $$ = $1; }
+ /* can't use m_attributes here, need to use two uniondef rules, as bison
+ * gets confused if we don't match the rule split in var_spec */
+ | attributes uniondef ';' { $$ = make_var(NULL); $$->type = $2; $$->attrs = $1; }
+ | uniondef ';' { $$ = make_var(NULL); $$->type = $1; }
| attributes ';' { $$ = make_var(NULL); $$->attrs = $1; }
| ';' { $$ = NULL; }
;
-s_field: m_attributes type pident array { $$ = $3; set_type($$, $2, $4); $$->attrs = $1; }
- ;
-
funcdef:
m_attributes type callconv pident
'(' m_args ')' { set_type($4, $2, NULL);
@@ -570,7 +571,7 @@
;
dispint_props: tPROPERTIES ':' { $$ = NULL; }
- | dispint_props s_field ';' { LINK($2, $1); $$ = $2; }
+ | dispint_props var_spec ';' { LINK($2, $1); $$ = $2; }
;
dispint_meths: tMETHODS ':' { $$ = NULL; }
@@ -660,6 +661,30 @@
| pident_list ',' pident { LINK($3, $1); $$ = $3; }
;
+funcptr: '(' p_ident ')'
+ '(' m_args ')' { $$ = $2;
+ $$->type = make_type(0, NULL);
+ $$->type->funcs = make_func(make_var(NULL), $5);
+ if (!$$->ptr_level) yyerror("%s must be a pointer\n", $$->name);
+ }
+ /* for syntactical consistency */
+ | ident
+ '(' m_args ')' { $$ = $1;
+ $$->type = make_type(0, NULL);
+ $$->type->funcs = make_func(make_var(NULL), $3);
+ yyerror("%s must be a pointer\n", $$->name);
+ }
+ ;
+
+p_funcptr: '*' pfuncptr %prec PPTR { $$ = $2; $$->type->funcs->def->ptr_level++; }
+ | tCONST p_funcptr { $$ = $2; /* FIXME */ }
+ ;
+
+pfuncptr: funcptr
+ | p_funcptr
+ | '(' pfuncptr ')' { $$ = $2; }
+ ;
+
pointer_type:
tREF { $$ = RPC_FC_RP; }
| tUNIQUE { $$ = RPC_FC_UP; }
@@ -691,6 +716,13 @@
if (!parse_only) write_typedef($$, $4);
reg_types($$, $4, 0);
}
+ | tTYPEDEF m_attributes type pfuncptr {
+ $$ = $4->type;
+ set_type($$->funcs->def, $3, NULL);
+ $$->attrs = $2;
+ if (!parse_only) write_typedef($$, $4);
+ reg_types($$, $4, 0);
+ }
;
uniondef: tUNION t_ident '{' fields '}' { $$ = get_typev(RPC_FC_NON_ENCAPSULATED_UNION, $2, tsUNION);
@@ -698,7 +730,7 @@
$$->defined = TRUE;
}
| tUNION t_ident
- tSWITCH '(' s_field ')'
+ tSWITCH '(' var_spec ')'
m_ident '{' cases '}' { var_t *u = $7;
$$ = get_typev(RPC_FC_ENCAPSULATED_UNION, $2, tsUNION);
if (!u) u = make_var("tagged_union");
Index: proxy.c
===================================================================
RCS file: /home/wine/wine/tools/widl/proxy.c,v
retrieving revision 1.9
diff -u -r1.9 proxy.c
--- proxy.c 7 Jan 2004 04:21:27 -0000 1.9
+++ proxy.c 11 Feb 2004 15:14:42 -0000
@@ -71,7 +71,7 @@
fprintf(proxy, " CALLBACK %s_", iface->name);
write_name(proxy, def);
fprintf(proxy, "_Proxy(\n");
- write_args(proxy, cur->args, iface->name, 1, TRUE);
+ write_args(proxy, cur->args, iface->name, 1);
fprintf(proxy, ")\n");
fprintf(proxy, "{\n");
/* local variables */
Index: widltypes.h
===================================================================
RCS file: /home/wine/wine/tools/widl/widltypes.h,v
retrieving revision 1.11
diff -u -r1.11 widltypes.h
--- widltypes.h 7 Jan 2004 04:21:27 -0000 1.11
+++ widltypes.h 11 Feb 2004 15:14:42 -0000
@@ -161,7 +161,6 @@
int ptr_level;
expr_t *array;
type_t *type;
- var_t *args; /* for function pointers */
char *tname;
attr_t *attrs;
expr_t *eval;
More information about the wine-patches
mailing list