Sync to wine-0.9.60:

- Rob Shearman <rob@codeweavers.com> Fri, 11 Apr 2008
widl: Support non-default calling conventions for object methods.

- Rob Shearman <rob@codeweavers.com> Fri, 11 Apr 2008
widl: Support non-default calling conventions for non-object functions.

- Rob Shearman <rob@codeweavers.com> Mon, 14 Apr 2008
widl: Check that attributes applied to interfaces, functions and arguments are applicable and issue an error if not.

- Rob Shearman <rob@codeweavers.com> Mon, 14 Apr 2008
widl: Check that attributes applied to typedefs and fields are applicable and issue an error otherwise.

- Rob Shearman <rob@codeweavers.com> Mon, 14 Apr 2008
widl: Make the attrs parameter passed to start_typelib const.

- Rob Shearman <rob@codeweavers.com> Mon, 14 Apr 2008
widl: The odl attribute is valid for dispinterfaces.

- Rob Shearman <rob@codeweavers.com> Mon, 14 Apr 2008
widl: Check that attributes are applicable for libraries,  modules, dispinterfaces and coclasses and otherwise issue an error.

- Rob Shearman <rob@codeweavers.com> Mon, 14 Apr 2008
widl: Output a warning if duplicate attributes are specified.

- Rob Shearman <rob@codeweavers.com> Mon, 14 Apr 2008
widl: Add support for the broadcast and idempotent operation attributes.

- Rob Shearman <rob@codeweavers.com> Mon, 14 Apr 2008
widl: Write out TYPEFLAG, FUNCFLAG and VARFLAG flags for all attribute we currently parse.
Add FIXMEs for the remaining ones and remove the warning for unimplemented attribute types since we now support all the attributes that we parse.

- Rob Shearman <rob@codeweavers.com> Mon, 14 Apr 2008
widl: Add functions to print an error or warning message using location information to enable these to be printed accurately when a check is done after an element is parsed.
Add location information to variable automatically, since this is will be useful for type checking of arguments.

- Rob Shearman <rob@codeweavers.com> Mon, 14 Apr 2008
widl: Add checking to arguments of non-local functions.
Check that out arguments have enough levels of indirection and that they don't derive from void * or a function pointer.

- Rob Shearman <rob@codeweavers.com> Tue, 15 Apr 2008
widl: Change alls calls to error in the parser to error_loc so that line number information is printed.

svn path=/trunk/; revision=37260
This commit is contained in:
Eric Kohl 2008-11-09 14:21:53 +00:00
parent 5387d5fcac
commit 1fc7265fa2
13 changed files with 1854 additions and 1162 deletions

View file

@ -26,7 +26,7 @@ reactos/tools/wpp # Synced to Wine-20081105 (~Wine-1.1.7)
reactos/tools/winebuild # Synced to Wine-20081105 (~Wine-1.1.7)
reactos/tools/wmc # Synced to Wine-20081105 (~Wine-1.1.7)
reactos/tools/wrc # Synced to Wine-20081105 (~Wine-1.1.7)
reactos/tools/widl # Synced to Wine-0_9_59
reactos/tools/widl # Synced to Wine-0_9_60
The following libraries are shared with Wine.

View file

@ -102,6 +102,7 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset)
const var_t* explicit_generic_handle_var = NULL;
const var_t* context_handle_var = NULL;
int has_full_pointer = is_full_pointer_function(func);
const char *callconv = get_attrp(def->type->attrs, ATTR_CALLCONV);
/* check for a defined binding handle */
explicit_handle_var = get_explicit_handle_var(func);
@ -131,6 +132,7 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset)
write_type_decl_left(client, get_func_return_type(func));
if (needs_space_after(get_func_return_type(func)))
fprintf(client, " ");
if (callconv) fprintf(client, "%s ", callconv);
write_prefix_name(client, prefix_client, def);
fprintf(client, "(\n");
indent++;
@ -184,6 +186,16 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset)
indent--;
fprintf(client, "\n");
if (is_attr(def->attrs, ATTR_IDEMPOTENT) || is_attr(def->attrs, ATTR_BROADCAST))
{
print_client("_RpcMessage.RpcFlags = ( RPC_NCA_FLAGS_DEFAULT ");
if (is_attr(def->attrs, ATTR_IDEMPOTENT))
fprintf(client, "| RPC_NCA_FLAGS_IDEMPOTENT ");
if (is_attr(def->attrs, ATTR_BROADCAST))
fprintf(client, "| RPC_NCA_FLAGS_BROADCAST ");
fprintf(client, ");\n\n");
}
if (implicit_handle)
{
print_client("_Handle = %s;\n", implicit_handle);

View file

@ -737,10 +737,12 @@ static void write_cpp_method_def(const type_t *iface)
{
var_t *def = cur->def;
if (!is_callas(def->attrs)) {
const char *callconv = get_attrp(def->type->attrs, ATTR_CALLCONV);
if (!callconv) callconv = "";
indent(header, 0);
fprintf(header, "virtual ");
write_type_decl_left(header, get_func_return_type(cur));
fprintf(header, " STDMETHODCALLTYPE ");
fprintf(header, " %s ", callconv);
write_name(header, def);
fprintf(header, "(\n");
write_args(header, cur->args, iface->name, 2, TRUE);
@ -763,9 +765,11 @@ static void do_write_c_method_def(const type_t *iface, const char *name)
{
const var_t *def = cur->def;
if (!is_callas(def->attrs)) {
const char *callconv = get_attrp(def->type->attrs, ATTR_CALLCONV);
if (!callconv) callconv = "";
indent(header, 0);
write_type_decl_left(header, get_func_return_type(cur));
fprintf(header, " (STDMETHODCALLTYPE *");
fprintf(header, " (%s *", callconv);
write_name(header, def);
fprintf(header, ")(\n");
write_args(header, cur->args, name, 1, TRUE);
@ -795,9 +799,11 @@ static void write_method_proto(const type_t *iface)
const var_t *def = cur->def;
if (!is_local(def->attrs)) {
const char *callconv = get_attrp(def->type->attrs, ATTR_CALLCONV);
if (!callconv) callconv = "";
/* proxy prototype */
write_type_decl_left(header, get_func_return_type(cur));
fprintf(header, " CALLBACK %s_", iface->name);
fprintf(header, " %s %s_", callconv, iface->name);
write_name(header, def);
fprintf(header, "_Proxy(\n");
write_args(header, cur->args, iface->name, 1, TRUE);
@ -881,10 +887,12 @@ void write_locals(FILE *fp, const type_t *iface, int body)
static void write_function_proto(const type_t *iface, const func_t *fun, const char *prefix)
{
var_t *def = fun->def;
const char *callconv = get_attrp(def->type->attrs, ATTR_CALLCONV);
/* FIXME: do we need to handle call_as? */
write_type_decl_left(header, get_func_return_type(fun));
fprintf(header, " ");
if (callconv) fprintf(header, "%s ", callconv);
write_prefix_name(header, prefix, def);
fprintf(header, "(\n");
if (fun->args)

File diff suppressed because it is too large Load diff

View file

@ -309,7 +309,7 @@
#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
#line 139 "parser.y"
#line 151 "parser.y"
typedef union YYSTYPE {
attr_t *attr;
attr_list_t *attr_list;

View file

@ -67,6 +67,8 @@
unsigned char pointer_default = RPC_FC_UP;
static int is_object_interface = FALSE;
/* are we inside a library block? */
static int is_inside_library = FALSE;
typedef struct list typelist_t;
struct typenode {
@ -129,7 +131,17 @@ static int compute_method_indexes(type_t *iface);
static char *gen_name(void);
static void process_typedefs(var_list_t *names);
static void check_arg(var_t *arg);
static void check_functions(const type_t *iface);
static void check_all_user_types(ifref_list_t *ifaces);
static const attr_list_t *check_iface_attrs(const char *name, const attr_list_t *attrs);
static attr_list_t *check_function_attrs(const char *name, attr_list_t *attrs);
static attr_list_t *check_typedef_attrs(attr_list_t *attrs);
static attr_list_t *check_field_attrs(const char *name, attr_list_t *attrs);
static const attr_list_t *check_library_attrs(const char *name, const attr_list_t *attrs);
static attr_list_t *check_dispiface_attrs(const char *name, attr_list_t *attrs);
static const attr_list_t *check_module_attrs(const char *name, const attr_list_t *attrs);
static const attr_list_t *check_coclass_attrs(const char *name, const attr_list_t *attrs);
const char *get_attr_display_name(enum attr_type type);
#define tsENUM 1
#define tsSTRUCT 2
@ -378,13 +390,15 @@ importlib: tIMPORTLIB '(' aSTRING ')'
libraryhdr: tLIBRARY aIDENTIFIER { $$ = $2; }
;
library_start: attributes libraryhdr '{' { if (!parse_only) start_typelib($2, $1);
library_start: attributes libraryhdr '{' { check_library_attrs($2, $1);
if (!parse_only) start_typelib($2, $1);
if (!parse_only && do_header) write_library($2, $1);
if (!parse_only && do_idfile) write_libid($2, $1);
is_inside_library = TRUE;
}
;
librarydef: library_start imp_statements '}'
semicolon_opt { if (!parse_only) end_typelib(); }
semicolon_opt { if (!parse_only) end_typelib(); is_inside_library = FALSE; }
;
m_args: { $$ = NULL; }
@ -447,6 +461,7 @@ attribute: { $$ = NULL; }
| tASYNC { $$ = make_attr(ATTR_ASYNC); }
| tAUTOHANDLE { $$ = make_attr(ATTR_AUTO_HANDLE); }
| tBINDABLE { $$ = make_attr(ATTR_BINDABLE); }
| tBROADCAST { $$ = make_attr(ATTR_BROADCAST); }
| tCALLAS '(' ident ')' { $$ = make_attrp(ATTR_CALLAS, $3); }
| tCASE '(' expr_list_const ')' { $$ = make_attrp(ATTR_CASE, $3); }
| tCONTEXTHANDLE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); }
@ -653,7 +668,7 @@ field: s_field ';' { $$ = $1; }
;
s_field: m_attributes type pident array { $$ = $3->var;
$$->attrs = $1;
$$->attrs = check_field_attrs($$->name, $1);
set_type($$, $2, $3, $4, FALSE);
free($3);
}
@ -662,13 +677,10 @@ s_field: m_attributes type pident array { $$ = $3->var;
funcdef:
m_attributes type pident { var_t *v = $3->var;
var_list_t *args = $3->args;
v->attrs = $1;
v->attrs = check_function_attrs(v->name, $1);
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);
}
}
;
@ -736,7 +748,7 @@ coclass: tCOCLASS aIDENTIFIER { $$ = make_class($2); }
;
coclasshdr: attributes coclass { $$ = $2;
$$->attrs = $1;
$$->attrs = check_coclass_attrs($2->name, $1);
if (!parse_only && do_header)
write_coclass($$);
if (!parse_only && do_idfile)
@ -768,7 +780,7 @@ dispinterfacehdr: attributes dispinterface { attr_t *attrs;
$$ = $2;
if ($$->defined) error_loc("multiple definition error\n");
attrs = make_attr(ATTR_DISPINTERFACE);
$$->attrs = append_attr( $1, attrs );
$$->attrs = append_attr( check_dispiface_attrs($2->name, $1), attrs );
$$->ref = find_type("IDispatch", 0);
if (!$$->ref) error_loc("IDispatch is undefined\n");
$$->defined = TRUE;
@ -816,7 +828,7 @@ interfacehdr: attributes interface { $$.interface = $2;
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->attrs = check_iface_attrs($2->name, $1);
$2->defined = TRUE;
if (!parse_only && do_header) write_forward($2);
}
@ -826,6 +838,7 @@ interfacedef: interfacehdr inherit
'{' int_statements '}' semicolon_opt { $$ = $1.interface;
$$->ref = $2;
$$->funcs = $4;
check_functions($$);
compute_method_indexes($$);
if (!parse_only && do_header) write_interface($$);
if (!parse_only && local_stubs) write_locals(local_stubs, $$, TRUE);
@ -859,7 +872,7 @@ module: tMODULE aIDENTIFIER { $$ = make_type(0, NULL); $$->name = $2; $$->ki
;
modulehdr: attributes module { $$ = $2;
$$->attrs = $1;
$$->attrs = check_module_attrs($2->name, $1);
}
;
@ -929,7 +942,7 @@ type: tVOID { $$ = duptype(find_type("void", 0), 1); }
| tSAFEARRAY '(' type ')' { $$ = make_safearray($3); }
;
typedef: tTYPEDEF m_attributes type pident_list { reg_typedefs($3, $4, $2);
typedef: tTYPEDEF m_attributes type pident_list { reg_typedefs($3, $4, check_typedef_attrs($2));
process_typedefs($4);
}
;
@ -1025,12 +1038,21 @@ static str_list_t *append_str(str_list_t *list, char *str)
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;
}
@ -1168,7 +1190,7 @@ static expr_t *make_expr1(enum expr_type type, expr_t *expr)
{
expr_t *e;
if (type == EXPR_ADDRESSOF && expr->type != EXPR_IDENTIFIER)
error("address-of operator applied to invalid expression\n");
error_loc("address-of operator applied to invalid expression\n");
e = xmalloc(sizeof(expr_t));
e->type = type;
e->ref = expr;
@ -1372,7 +1394,7 @@ static void set_type(var_t *v, type_t *type, const pident_t *pident, array_dims_
}
}
else if (!arr && ptr_attr)
error("%s: pointer attribute applied to non-pointer type\n", v->name);
error_loc("%s: pointer attribute applied to non-pointer type\n", v->name);
}
if (pident && pident->is_func) {
@ -1394,7 +1416,7 @@ static void set_type(var_t *v, type_t *type, const pident_t *pident, array_dims_
if (arr) LIST_FOR_EACH_ENTRY_REV(dim, arr, expr_t, entry)
{
if (sizeless)
error("%s: only the first array dimension can be unspecified\n", v->name);
error_loc("%s: only the first array dimension can be unspecified\n", v->name);
if (dim->is_const)
{
@ -1402,10 +1424,10 @@ static void set_type(var_t *v, type_t *type, const pident_t *pident, array_dims_
size_t size = type_memsize(v->type, &align);
if (dim->cval <= 0)
error("%s: array dimension must be positive\n", v->name);
error_loc("%s: array dimension must be positive\n", v->name);
if (0xffffffffuL / size < (unsigned long) dim->cval)
error("%s: total array size is too large\n", v->name);
error_loc("%s: total array size is too large\n", v->name);
else if (0xffffuL < size * dim->cval)
v->type = make_type(RPC_FC_LGFARRAY, v->type);
else
@ -1431,10 +1453,10 @@ static void set_type(var_t *v, type_t *type, const pident_t *pident, array_dims_
atype = *ptype = duptype(*ptype, 0);
if (atype->type == RPC_FC_SMFARRAY || atype->type == RPC_FC_LGFARRAY)
error("%s: cannot specify size_is for a fixed sized array\n", v->name);
error_loc("%s: cannot specify size_is for a fixed sized array\n", v->name);
if (atype->type != RPC_FC_CARRAY && !is_ptr(atype))
error("%s: size_is attribute applied to illegal type\n", v->name);
error_loc("%s: size_is attribute applied to illegal type\n", v->name);
atype->type = RPC_FC_CARRAY;
atype->size_is = dim;
@ -1442,7 +1464,7 @@ static void set_type(var_t *v, type_t *type, const pident_t *pident, array_dims_
ptype = &(*ptype)->ref;
if (*ptype == NULL)
error("%s: too many expressions in size_is attribute\n", v->name);
error_loc("%s: too many expressions in size_is attribute\n", v->name);
}
ptype = &v->type;
@ -1460,14 +1482,14 @@ static void set_type(var_t *v, type_t *type, const pident_t *pident, array_dims_
else if (atype->type == RPC_FC_CARRAY)
atype->type = RPC_FC_CVARRAY;
else
error("%s: length_is attribute applied to illegal type\n", v->name);
error_loc("%s: length_is attribute applied to illegal type\n", v->name);
atype->length_is = dim;
}
ptype = &(*ptype)->ref;
if (*ptype == NULL)
error("%s: too many expressions in length_is attribute\n", v->name);
error_loc("%s: too many expressions in length_is attribute\n", v->name);
}
if (has_varconf && !last_array(v->type))
@ -1543,6 +1565,9 @@ static var_t *make_var(char *name)
v->type = NULL;
v->attrs = NULL;
v->eval = NULL;
v->loc_info.input_name = input_name ? input_name : "stdin";
v->loc_info.line_number = line_number;
v->loc_info.near_text = parser_text;
return v;
}
@ -2114,12 +2139,287 @@ static void process_typedefs(pident_list_t *pidents)
}
}
struct allowed_attr
{
unsigned int dce_compatible : 1;
unsigned int acf : 1;
unsigned int on_interface : 1;
unsigned int on_function : 1;
unsigned int on_arg : 1;
unsigned int on_type : 1;
unsigned int on_field : 1;
unsigned int on_library : 1;
unsigned int on_dispinterface : 1;
unsigned int on_module : 1;
unsigned int on_coclass : 1;
const char *display_name;
};
struct allowed_attr allowed_attr[] =
{
/* attr { D ACF I Fn ARG T Fi L DI M C <display name> } */
/* ATTR_AGGREGATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "aggregatable" },
/* ATTR_APPOBJECT */ { 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, "async" },
/* ATTR_AUTO_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "auto_handle" },
/* ATTR_BINDABLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "bindable" },
/* ATTR_BROADCAST */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "broadcast" },
/* ATTR_CALLAS */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "call_as" },
/* ATTR_CALLCONV */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL },
/* ATTR_CASE */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "case" },
/* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "context_handle" },
/* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, "control" },
/* ATTR_DEFAULT */ { 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, "default" },
/* ATTR_DEFAULTCOLLELEM */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "defaultcollelem" },
/* ATTR_DEFAULTVALUE_EXPR */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "defaultvalue" },
/* ATTR_DEFAULTVALUE_STRING */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "defaultvalue" },
/* ATTR_DEFAULTVTABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "defaultvtable" },
/* ATTR_DISPINTERFACE */ { 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, "displaybind" },
/* ATTR_DLLNAME */ { 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, "dual" },
/* ATTR_ENDPOINT */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "endpoint" },
/* ATTR_ENTRY_ORDINAL */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "entry" },
/* ATTR_ENTRY_STRING */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "entry" },
/* ATTR_EXPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "explicit_handle" },
/* ATTR_HANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "handle" },
/* ATTR_HELPCONTEXT */ { 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, "helpcontext" },
/* ATTR_HELPFILE */ { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "helpfile" },
/* ATTR_HELPSTRING */ { 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, "helpstring" },
/* ATTR_HELPSTRINGCONTEXT */ { 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, "helpstringcontext" },
/* ATTR_HELPSTRINGDLL */ { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "helpstringdll" },
/* ATTR_HIDDEN */ { 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, "hidden" },
/* ATTR_ID */ { 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, "id" },
/* ATTR_IDEMPOTENT */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "idempotent" },
/* ATTR_IIDIS */ { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, "iid_is" },
/* ATTR_IMMEDIATEBIND */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "immediatebind" },
/* ATTR_IMPLICIT_HANDLE */ { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "implicit_handle" },
/* ATTR_IN */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "in" },
/* ATTR_INPUTSYNC */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" },
/* ATTR_LENGTHIS */ { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, "length_is" },
/* ATTR_LOCAL */ { 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, "local" },
/* ATTR_NONBROWSABLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "nonbrowsable" },
/* ATTR_NONCREATABLE */ { 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, "nonextensible" },
/* ATTR_OBJECT */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "object" },
/* ATTR_ODL */ { 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, "odl" },
/* ATTR_OLEAUTOMATION */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "oleautomation" },
/* ATTR_OPTIONAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "optional" },
/* ATTR_OUT */ { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "out" },
/* ATTR_POINTERDEFAULT */ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "pointer_default" },
/* ATTR_POINTERTYPE */ { 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, "ref, unique or ptr" },
/* ATTR_PROPGET */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "propget" },
/* ATTR_PROPPUT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "propput" },
/* ATTR_PROPPUTREF */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "propputref" },
/* ATTR_PUBLIC */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "public" },
/* ATTR_RANGE */ { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, "range" },
/* ATTR_READONLY */ { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, "readonly" },
/* ATTR_REQUESTEDIT */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "requestedit" },
/* ATTR_RESTRICTED */ { 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, "restricted" },
/* ATTR_RETVAL */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "retval" },
/* ATTR_SIZEIS */ { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, "size_is" },
/* ATTR_SOURCE */ { 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, "source" },
/* ATTR_STRICTCONTEXTHANDLE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "strict_context_handle" },
/* ATTR_STRING */ { 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, "string" },
/* ATTR_SWITCHIS */ { 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, "switch_is" },
/* ATTR_SWITCHTYPE */ { 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, "switch_type" },
/* ATTR_TRANSMITAS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "transmit_as" },
/* ATTR_UUID */ { 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, "uuid" },
/* ATTR_V1ENUM */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "v1_enum" },
/* ATTR_VARARG */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "vararg" },
/* ATTR_VERSION */ { 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, "version" },
/* ATTR_WIREMARSHAL */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "wire_marshal" },
};
const char *get_attr_display_name(enum attr_type type)
{
return allowed_attr[type].display_name;
}
static const attr_list_t *check_iface_attrs(const char *name, const 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_interface)
error_loc("inapplicable attribute %s for interface %s\n",
allowed_attr[attr->type].display_name, name);
}
return attrs;
}
static attr_list_t *check_function_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_function)
error_loc("inapplicable attribute %s for function %s\n",
allowed_attr[attr->type].display_name, name);
}
return attrs;
}
static void check_arg(var_t *arg)
{
type_t *t = arg->type;
const type_t *t = arg->type;
const attr_t *attr;
if (t->type == 0 && ! is_var_ptr(arg))
error_loc("argument '%s' has void type\n", arg->name);
if (arg->attrs)
{
LIST_FOR_EACH_ENTRY(attr, arg->attrs, const attr_t, entry)
{
if (!allowed_attr[attr->type].on_arg)
error_loc("inapplicable attribute %s for argument %s\n",
allowed_attr[attr->type].display_name, arg->name);
}
}
}
static attr_list_t *check_typedef_attrs(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_type)
error_loc("inapplicable attribute %s for typedef\n",
allowed_attr[attr->type].display_name);
}
return attrs;
}
static attr_list_t *check_field_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_field)
error_loc("inapplicable attribute %s for field %s\n",
allowed_attr[attr->type].display_name, name);
}
return attrs;
}
static const attr_list_t *check_library_attrs(const char *name, const 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_library)
error_loc("inapplicable attribute %s for library %s\n",
allowed_attr[attr->type].display_name, name);
}
return attrs;
}
static attr_list_t *check_dispiface_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_dispinterface)
error_loc("inapplicable attribute %s for dispinterface %s\n",
allowed_attr[attr->type].display_name, name);
}
return attrs;
}
static const attr_list_t *check_module_attrs(const char *name, const 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_module)
error_loc("inapplicable attribute %s for module %s\n",
allowed_attr[attr->type].display_name, name);
}
return attrs;
}
static const attr_list_t *check_coclass_attrs(const char *name, const 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_coclass)
error_loc("inapplicable attribute %s for coclass %s\n",
allowed_attr[attr->type].display_name, name);
}
return attrs;
}
/* checks that arguments for a function make sense for marshalling and unmarshalling */
static void check_remoting_args(const func_t *func)
{
const char *funcname = func->def->name;
const var_t *arg;
if (func->args) LIST_FOR_EACH_ENTRY( arg, func->args, const var_t, entry )
{
int ptr_level = 0;
const type_t *type = arg->type;
int is_wire_marshal = 0;
int is_context_handle = 0;
/* get pointer level and fundamental type for the argument */
for (;;)
{
if (!is_wire_marshal && is_attr(type->attrs, ATTR_WIREMARSHAL))
is_wire_marshal = 1;
if (!is_context_handle && is_attr(type->attrs, ATTR_CONTEXTHANDLE))
is_context_handle = 1;
if (type->kind == TKIND_ALIAS)
type = type->orig;
else if (is_ptr(type))
{
ptr_level++;
type = type->ref;
}
else
break;
}
/* check that [out] parameters have enough pointer levels */
if (is_attr(arg->attrs, ATTR_OUT))
{
if (!is_array(type))
{
if (!ptr_level)
error_loc_info(&arg->loc_info, "out parameter \'%s\' of function \'%s\' is not a pointer\n", arg->name, funcname);
if (type->type == RPC_FC_IP && ptr_level == 1)
error_loc_info(&arg->loc_info, "out interface pointer \'%s\' of function \'%s\' is not a double pointer\n", arg->name, funcname);
}
}
if (type->type == 0 && !is_attr(arg->attrs, ATTR_IIDIS) && !is_wire_marshal && !is_context_handle)
error_loc_info(&arg->loc_info, "parameter \'%s\' of function \'%s\' cannot derive from void *\n", arg->name, funcname);
else if (type->type == RPC_FC_FUNCTION)
error_loc_info(&arg->loc_info, "parameter \'%s\' of function \'%s\' cannot be a function pointer\n", arg->name, funcname);
}
}
static void check_functions(const type_t *iface)
{
if (!is_inside_library && !is_attr(iface->attrs, ATTR_LOCAL))
{
const func_t *func;
if (iface->funcs) LIST_FOR_EACH_ENTRY( func, iface->funcs, const func_t, entry )
{
if (!is_attr(func->def->attrs, ATTR_LOCAL))
check_remoting_args(func);
}
}
}
static void check_all_user_types(ifref_list_t *ifrefs)

View file

@ -253,10 +253,12 @@ static void gen_proxy(type_t *iface, const func_t *cur, int idx,
var_t *def = cur->def;
int has_ret = !is_void(get_func_return_type(cur));
int has_full_pointer = is_full_pointer_function(cur);
const char *callconv = get_attrp(def->type->attrs, ATTR_CALLCONV);
if (!callconv) callconv = "";
indent = 0;
write_type_decl_left(proxy, get_func_return_type(cur));
print_proxy( " STDMETHODCALLTYPE %s_", iface->name);
print_proxy( " %s %s_", callconv, iface->name);
write_name(proxy, def);
print_proxy( "_Proxy(\n");
write_args(proxy, cur->args, iface->name, 1, TRUE);

View file

@ -240,7 +240,7 @@ unsigned short get_type_vt(type_t *t)
return 0;
}
void start_typelib(char *name, attr_list_t *attrs)
void start_typelib(char *name, const attr_list_t *attrs)
{
in_typelib++;
if (!do_typelib) return;

View file

@ -22,7 +22,7 @@
#define __WIDL_TYPELIB_H
extern int in_typelib;
extern void start_typelib(char *name, attr_list_t *attrs);
extern void start_typelib(char *name, const attr_list_t *attrs);
extern void end_typelib(void);
extern void add_typelib_entry(type_t *t);
extern void add_importlib(const char *name);

View file

@ -33,6 +33,8 @@
#include "utils.h"
#include "parser.h"
#define CURRENT_LOCATION { input_name ? input_name : "stdin", line_number, parser_text }
static const int want_near_indication = 0;
static void make_print(char *str)
@ -45,17 +47,17 @@ static void make_print(char *str)
}
}
static void generic_msg(const char *s, const char *t, const char *n, va_list ap)
static void generic_msg(const loc_info_t *loc_info, const char *s, const char *t, va_list ap)
{
fprintf(stderr, "%s:%d: %s: ", input_name ? input_name : "stdin", line_number, t);
fprintf(stderr, "%s:%d: %s: ", loc_info->input_name, loc_info->line_number, t);
vfprintf(stderr, s, ap);
if (want_near_indication)
{
char *cpy;
if(n)
if(loc_info->near_text)
{
cpy = xstrdup(n);
cpy = xstrdup(loc_info->near_text);
make_print(cpy);
fprintf(stderr, " near '%s'", cpy);
free(cpy);
@ -67,9 +69,10 @@ static void generic_msg(const char *s, const char *t, const char *n, va_list ap)
/* yyerror: yacc assumes this is not newline terminated. */
int parser_error(const char *s, ...)
{
loc_info_t cur_location = CURRENT_LOCATION;
va_list ap;
va_start(ap, s);
generic_msg(s, "Error", parser_text, ap);
generic_msg(&cur_location, s, "Error", ap);
fprintf(stderr, "\n");
va_end(ap);
exit(1);
@ -78,18 +81,29 @@ int parser_error(const char *s, ...)
void error_loc(const char *s, ...)
{
loc_info_t cur_loc = CURRENT_LOCATION;
va_list ap;
va_start(ap, s);
generic_msg(s, "Error", parser_text, ap);
generic_msg(&cur_loc, s, "Error", ap);
va_end(ap);
exit(1);
}
void error_loc_info(const loc_info_t *loc_info, const char *s, ...)
{
va_list ap;
va_start(ap, s);
generic_msg(loc_info, s, "Error", ap);
va_end(ap);
exit(1);
}
int parser_warning(const char *s, ...)
{
loc_info_t cur_loc = CURRENT_LOCATION;
va_list ap;
va_start(ap, s);
generic_msg(s, "Warning", parser_text, ap);
generic_msg(&cur_loc, s, "Warning", ap);
va_end(ap);
return 0;
}
@ -113,6 +127,14 @@ void warning(const char *s, ...)
va_end(ap);
}
void warning_loc_info(const loc_info_t *loc_info, const char *s, ...)
{
va_list ap;
va_start(ap, s);
generic_msg(loc_info, s, "Warning", ap);
va_end(ap);
}
void chat(const char *s, ...)
{
if(debuglevel & DEBUGLEVEL_CHAT)

View file

@ -37,7 +37,9 @@ int parser_error(const char *s, ...) __attribute__((format (printf, 1, 2)));
int parser_warning(const char *s, ...) __attribute__((format (printf, 1, 2)));
void error_loc(const char *s, ...) __attribute__((format (printf, 1, 2)));
void error(const char *s, ...) __attribute__((format (printf, 1, 2)));
void error_loc_info(const loc_info_t *, const char *s, ...) __attribute__((format (printf, 2, 3)));
void warning(const char *s, ...) __attribute__((format (printf, 1, 2)));
void warning_loc_info(const loc_info_t *, const char *s, ...) __attribute__((format (printf, 2, 3)));
void chat(const char *s, ...) __attribute__((format (printf, 1, 2)));
char *dup_basename(const char *name, const char *ext);

View file

@ -45,6 +45,7 @@ typedef GUID UUID;
#define RPC_FC_FUNCTION 0xfe
typedef struct _loc_info_t loc_info_t;
typedef struct _attr_t attr_t;
typedef struct _expr_t expr_t;
typedef struct _type_t type_t;
@ -78,6 +79,7 @@ enum attr_type
ATTR_ASYNC,
ATTR_AUTO_HANDLE,
ATTR_BINDABLE,
ATTR_BROADCAST,
ATTR_CALLAS,
ATTR_CALLCONV, /* calling convention pseudo-attribute */
ATTR_CASE,
@ -184,6 +186,13 @@ enum type_kind
TKIND_MAX
};
struct _loc_info_t
{
const char *input_name;
int line_number;
const char *near_text;
};
struct str_list_entry_t
{
char *str;
@ -248,6 +257,8 @@ struct _var_t {
attr_list_t *attrs;
expr_t *eval;
struct _loc_info_t loc_info;
/* parser-internal */
struct list entry;
};
@ -316,7 +327,7 @@ struct _importlib_t {
struct _typelib_t {
char *name;
char *filename;
attr_list_t *attrs;
const attr_list_t *attrs;
struct list entries;
struct list importlibs;
};

View file

@ -1317,10 +1317,14 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, const func_t *func, int
expr_t *expr = attr->u.pval;
switch(attr->type) {
case ATTR_BINDABLE:
funcflags |= 0x4; /* FUNCFLAG_BINDABLE */
funcflags |= 0x4; /* FUNCFLAG_FBINDABLE */
break;
/* FIXME: FUNCFLAG_FDEFAULTBIND */
case ATTR_DEFAULTCOLLELEM:
funcflags |= 0x100; /* FUNCFLAG_FDEFAULTCOLLELEM */
break;
case ATTR_DISPLAYBIND:
funcflags |= 0x10; /* FUNCFLAG_DISPLAYBIND */
funcflags |= 0x10; /* FUNCFLAG_FDISPLAYBIND */
break;
case ATTR_ENTRY_ORDINAL:
extra_attr = max(extra_attr, 3);
@ -1349,8 +1353,11 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, const func_t *func, int
case ATTR_ID:
id = expr->cval;
break;
case ATTR_IMMEDIATEBIND:
funcflags |= 0x1000; /* FUNCFLAG_FIMMEDIATEBIND */
break;
case ATTR_NONBROWSABLE:
funcflags |= 0x400; /* FUNCFLAG_NONBROWSABLE */
funcflags |= 0x400; /* FUNCFLAG_FNONBROWSABLE */
break;
case ATTR_OUT:
break;
@ -1363,9 +1370,18 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, const func_t *func, int
case ATTR_PROPPUTREF:
invokekind = 0x8; /* INVOKE_PROPERTYPUTREF */
break;
/* FIXME: FUNCFLAG_FREPLACEABLE */
case ATTR_REQUESTEDIT:
funcflags |= 0x8; /* FUNCFLAG_FREQUESTEDIT */
break;
case ATTR_RESTRICTED:
funcflags |= 0x1; /* FUNCFLAG_FRESTRICTED */
break;
case ATTR_SOURCE:
funcflags |= 0x2; /* FUNCFLAG_FSOURCE */
break;
/* FIXME: FUNCFLAG_FUIDEFAULT */
/* FIXME: FUNCFLAG_FUSESGETLASTERROR */
case ATTR_VARARG:
if (num_optional || num_defaults)
warning("add_func_desc: ignoring vararg in function with optional or defaultvalue params\n");
@ -1373,7 +1389,6 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, const func_t *func, int
num_optional = -1;
break;
default:
warning("add_func_desc: ignoring attr %d\n", attr->type);
break;
}
}
@ -1595,23 +1610,44 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var)
if (var->attrs) LIST_FOR_EACH_ENTRY( attr, var->attrs, const attr_t, entry ) {
expr_t *expr = attr->u.pval;
switch(attr->type) {
case ATTR_BINDABLE:
varflags |= 0x04; /* VARFLAG_FBINDABLE */
break;
/* FIXME: VARFLAG_FDEFAULTBIND */
case ATTR_DEFAULTCOLLELEM:
varflags |= 0x100; /* VARFLAG_FDEFAULTCOLLELEM */
break;
case ATTR_DISPLAYBIND:
varflags |= 0x10; /* VARFLAG_FDISPLAYBIND */
break;
case ATTR_HIDDEN:
varflags |= 0x40; /* VARFLAG_FHIDDEN */
break;
case ATTR_ID:
id = expr->cval;
break;
case ATTR_IMMEDIATEBIND:
varflags |= 0x1000; /* VARFLAG_FIMMEDIATEBIND */
break;
case ATTR_NONBROWSABLE:
varflags |= 0x400; /* VARFLAG_FNONBROWSABLE */
break;
case ATTR_READONLY:
varflags |= 0x01; /* VARFLAG_FREADONLY */
break;
/* FIXME: VARFLAG_FREPLACEABLE */
break;
case ATTR_REQUESTEDIT:
varflags |= 0x08; /* VARFLAG_FREQUESTEDIT */
break;
case ATTR_RESTRICTED:
varflags |= 0x80; /* VARFLAG_FRESTRICTED */
break;
case ATTR_SOURCE:
varflags |= 0x02; /* VARFLAG_FSOURCE */
break;
/* FIXME: VARFLAG_FUIDEFAULT */
default:
warning("AddVarDesc: unhandled attr type %d\n", attr->type);
break;
}
}
@ -1799,9 +1835,6 @@ static msft_typeinfo_t *create_msft_typeinfo(msft_typelib_t *typelib, enum type_
typeinfo->flags |= 0x20; /* TYPEFLAG_FCONTROL */
break;
case ATTR_DISPINTERFACE:
break;
case ATTR_DLLNAME:
{
int offset = ctl2_alloc_string(typelib, attr->u.pval);
@ -1838,8 +1871,7 @@ static msft_typeinfo_t *create_msft_typeinfo(msft_typelib_t *typelib, enum type_
typeinfo->flags |= 0x10; /* TYPEFLAG_FHIDDEN */
break;
case ATTR_LOCAL:
break;
/* FIXME: TYPEFLAG_FLICENSED */
case ATTR_NONCREATABLE:
typeinfo->flags &= ~0x2; /* TYPEFLAG_FCANCREATE */
@ -1849,18 +1881,15 @@ static msft_typeinfo_t *create_msft_typeinfo(msft_typelib_t *typelib, enum type_
typeinfo->flags |= 0x80; /* TYPEFLAG_FNONEXTENSIBLE */
break;
case ATTR_OBJECT:
break;
case ATTR_ODL:
break;
case ATTR_OLEAUTOMATION:
typeinfo->flags |= 0x100; /* TYPEFLAG_FOLEAUTOMATION */
break;
case ATTR_PUBLIC:
break;
/* FIXME: TYPEFLAG_FPREDCLID */
/* FIXME: TYPEFLAG_FPROXY */
/* FIXME: TYPEFLAG_FREPLACEABLE */
case ATTR_RESTRICTED:
typeinfo->flags |= 0x200; /* TYPEFLAG_FRESTRICTED */
@ -1883,7 +1912,6 @@ static msft_typeinfo_t *create_msft_typeinfo(msft_typelib_t *typelib, enum type_
break;
default:
warning("create_msft_typeinfo: ignoring attr %d\n", attr->type);
break;
}
}
@ -2102,6 +2130,9 @@ static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls)
case ATTR_DEFAULT:
ref->flags |= 0x1; /* IMPLTYPEFLAG_FDEFAULT */
break;
case ATTR_DEFAULTVTABLE:
ref->flags |= 0x8; /* IMPLTYPEFLAG_FDEFAULTVTABLE */
break;
case ATTR_RESTRICTED:
ref->flags |= 0x4; /* IMPLTYPEFLAG_FRESTRICTED */
break;