{
if (!h) return;
- write_type_left(h, t, declonly);
+ if (t->type == RPC_FC_FUNCTION) {
+ const char *callconv = get_attrp(t->attrs, ATTR_CALLCONV);
+ if (!callconv) callconv = "";
+ write_type_left(h, t->ref, declonly);
+ fprintf(h, " (%s *", callconv);
+ } else
+ write_type_left(h, t, declonly);
if (fmt) {
if (needs_space_after(t))
fprintf(h, " ");
vfprintf(h, fmt, args);
}
- write_type_right(h, t, is_field);
+ if (t->type == RPC_FC_FUNCTION) {
+ fprintf(h, ")(");
+ write_args(h, t->fields_or_args, NULL, 0, FALSE);
+ fprintf(h, ")");
+ } else
+ write_type_right(h, t, is_field);
}
void write_type_def_or_decl(FILE *f, type_t *t, int field, const char *fmt, ...)
}
else fprintf(h, ",");
}
- if (arg->type->type == RPC_FC_FUNCTION)
- {
- write_type_decl_left(h, arg->type->ref);
- fprintf(h, " (STDMETHODCALLTYPE *");
- write_name(h,arg);
- fprintf(h, ")(");
- write_args(h, arg->type->fields_or_args, NULL, 0, FALSE);
- fprintf(h, ")");
- }
- else
- write_type_decl(h, arg->type, "%s", arg->name);
+ write_type_decl(h, arg->type, "%s", arg->name);
count++;
}
if (do_indent) indentation--;
#endif
unsigned char pointer_default = RPC_FC_UP;
+static int is_object_interface = FALSE;
typedef struct list typelist_t;
struct typenode {
%type <func_list> int_statements dispint_meths
%type <type> coclass coclasshdr coclassdef
%type <num> pointer_type version
-%type <str> libraryhdr
+%type <str> libraryhdr callconv
%type <uuid> uuid_string
%type <num> import_start
$$ = parse_uuid($1); }
;
-callconv:
- | tSTDCALL
+callconv: tCDECL { $$ = $<str>1; }
+ | tSTDCALL { $$ = $<str>1; }
;
cases: { $$ = NULL; }
;
funcdef:
- m_attributes type callconv pident { var_t *v = $4->var;
- var_list_t *args = $4->args;
+ m_attributes type pident { var_t *v = $3->var;
+ var_list_t *args = $3->args;
v->attrs = $1;
- set_type(v, $2, $4, NULL, FALSE);
- free($4);
+ set_type(v, $2, $3, NULL, FALSE);
+ free($3);
$$ = make_func(v, args);
if (is_attr(v->attrs, ATTR_IN)) {
error_loc("inapplicable attribute [in] for function '%s'\n",$$->def->name);
;
dispinterfacehdr: attributes dispinterface { attr_t *attrs;
+ is_object_interface = TRUE;
$$ = $2;
if ($$->defined) error_loc("multiple definition error\n");
attrs = make_attr(ATTR_DISPINTERFACE);
$$.old_pointer_default = pointer_default;
if (is_attr($1, ATTR_POINTERDEFAULT))
pointer_default = get_attrv($1, ATTR_POINTERDEFAULT);
+ is_object_interface = is_object($1);
if ($2->defined) error_loc("multiple definition error\n");
$2->attrs = $1;
$2->defined = TRUE;
pident: '*' pident %prec PPTR { $$ = $2; $$->ptr_level++; }
| tCONST pident { $$ = $2; /* FIXME */ }
+ | callconv pident { $$ = $2;
+ if ($$->callconv) parser_warning("multiple calling conventions %s, %s for function %s\n", $$->callconv, $1, $$->var->name);
+ $$->callconv = $1;
+ }
| direct_ident
;
-func_ident: direct_ident '(' m_args ')' { $$ = $1; $1->args = $3; $1->is_func = TRUE; }
+func_ident: direct_ident '(' m_args ')'
+ { $$ = $1;
+ $1->args = $3;
+ $1->is_func = TRUE;
+ }
+ ;
direct_ident: ident { $$ = make_pident($1); }
| '(' pident ')' { $$ = $2; }
if (func_ptr_level == 1) func_ptr_level = 0;
v->type = make_type(RPC_FC_FUNCTION, v->type);
v->type->fields_or_args = pident->args;
+ if (pident->callconv)
+ v->type->attrs = append_attr(NULL, make_attrp(ATTR_CALLCONV, pident->callconv));
+ else if (is_object_interface) {
+ static char *stdmethodcalltype;
+ if (!stdmethodcalltype) stdmethodcalltype = strdup("STDMETHODCALLTYPE");
+ v->type->attrs = append_attr(NULL, make_attrp(ATTR_CALLCONV, stdmethodcalltype));
+ }
for (; func_ptr_level > 0; func_ptr_level--)
v->type = make_type(ptr_type, v->type);
}
p->ptr_level = 0;
p->func_ptr_level = 0;
p->args = NULL;
+ p->callconv = NULL;
return p;
}
cur->fields_or_args = pident->args;
for (; func_ptr_level > 0; func_ptr_level--)
cur = make_type(pointer_default, cur);
+ if (pident->callconv)
+ cur->attrs = append_attr(NULL, make_attrp(ATTR_CALLCONV, pident->callconv));
+ else if (is_object_interface) {
+ static char *stdmethodcalltype;
+ if (!stdmethodcalltype) stdmethodcalltype = strdup("STDMETHODCALLTYPE");
+ cur->attrs = append_attr(NULL, make_attrp(ATTR_CALLCONV, stdmethodcalltype));
+ }
}
cur = alias(cur, name->name);
cur->attrs = attrs;