Commit 76512154 authored by Richard Pospesel's avatar Richard Pospesel Committed by Alexandre Julliard

widl: Refactor to have pointer type's ref use decl_spec_t rather than type_t.

parent c7d68454
...@@ -580,7 +580,7 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc ...@@ -580,7 +580,7 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc
case EXPR_PPTR: case EXPR_PPTR:
result = resolve_expression(expr_loc, cont_type, e->ref); result = resolve_expression(expr_loc, cont_type, e->ref);
if (result.type && is_ptr(result.type)) if (result.type && is_ptr(result.type))
result.type = type_pointer_get_ref(result.type); result.type = type_pointer_get_ref_type(result.type);
else if(result.type && is_array(result.type) else if(result.type && is_array(result.type)
&& type_array_is_decl_as_ptr(result.type)) && type_array_is_decl_as_ptr(result.type))
result.type = type_array_get_element_type(result.type); result.type = type_array_get_element_type(result.type);
......
...@@ -77,7 +77,7 @@ int is_ptrchain_attr(const var_t *var, enum attr_type t) ...@@ -77,7 +77,7 @@ int is_ptrchain_attr(const var_t *var, enum attr_type t)
else if (type_is_alias(type)) else if (type_is_alias(type))
type = type_alias_get_aliasee(type); type = type_alias_get_aliasee(type);
else if (is_ptr(type)) else if (is_ptr(type))
type = type_pointer_get_ref(type); type = type_pointer_get_ref_type(type);
else return 0; else return 0;
} }
} }
...@@ -351,8 +351,8 @@ void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly) ...@@ -351,8 +351,8 @@ void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly)
break; break;
case TYPE_POINTER: case TYPE_POINTER:
{ {
write_type_left(h, type_pointer_get_ref(t), name_type, declonly); write_type_left(h, type_pointer_get_ref_type(t), name_type, declonly);
write_pointer_left(h, type_pointer_get_ref(t)); write_pointer_left(h, type_pointer_get_ref_type(t));
if (is_attr(t->attrs, ATTR_CONST)) fprintf(h, "const "); if (is_attr(t->attrs, ATTR_CONST)) fprintf(h, "const ");
break; break;
} }
...@@ -461,7 +461,7 @@ void write_type_right(FILE *h, type_t *t, int is_field) ...@@ -461,7 +461,7 @@ void write_type_right(FILE *h, type_t *t, int is_field)
} }
case TYPE_POINTER: case TYPE_POINTER:
{ {
type_t *ref = type_pointer_get_ref(t); type_t *ref = type_pointer_get_ref_type(t);
if (!type_is_alias(ref) && is_array(ref) && !type_array_is_decl_as_ptr(ref)) if (!type_is_alias(ref) && is_array(ref) && !type_array_is_decl_as_ptr(ref))
fprintf(h, ")"); fprintf(h, ")");
write_type_right(h, ref, FALSE); write_type_right(h, ref, FALSE);
...@@ -493,7 +493,7 @@ static void write_type_v(FILE *h, type_t *t, int is_field, int declonly, const c ...@@ -493,7 +493,7 @@ static void write_type_v(FILE *h, type_t *t, int is_field, int declonly, const c
if (!h) return; if (!h) return;
if (t) { if (t) {
for (pt = t; is_ptr(pt); pt = type_pointer_get_ref(pt), ptr_level++) for (pt = t; is_ptr(pt); pt = type_pointer_get_ref_type(pt), ptr_level++)
; ;
if (type_get_type_detect_alias(pt) == TYPE_FUNCTION) { if (type_get_type_detect_alias(pt) == TYPE_FUNCTION) {
...@@ -603,7 +603,7 @@ unsigned int get_context_handle_offset( const type_t *type ) ...@@ -603,7 +603,7 @@ unsigned int get_context_handle_offset( const type_t *type )
while (!is_attr( type->attrs, ATTR_CONTEXTHANDLE )) while (!is_attr( type->attrs, ATTR_CONTEXTHANDLE ))
{ {
if (type_is_alias( type )) type = type_alias_get_aliasee( type ); if (type_is_alias( type )) type = type_alias_get_aliasee( type );
else if (is_ptr( type )) type = type_pointer_get_ref( type ); else if (is_ptr( type )) type = type_pointer_get_ref_type( type );
else error( "internal error: %s is not a context handle\n", type->name ); else error( "internal error: %s is not a context handle\n", type->name );
} }
LIST_FOR_EACH_ENTRY( ch, &context_handle_list, context_handle_t, entry ) LIST_FOR_EACH_ENTRY( ch, &context_handle_list, context_handle_t, entry )
...@@ -623,7 +623,7 @@ unsigned int get_generic_handle_offset( const type_t *type ) ...@@ -623,7 +623,7 @@ unsigned int get_generic_handle_offset( const type_t *type )
while (!is_attr( type->attrs, ATTR_HANDLE )) while (!is_attr( type->attrs, ATTR_HANDLE ))
{ {
if (type_is_alias( type )) type = type_alias_get_aliasee( type ); if (type_is_alias( type )) type = type_alias_get_aliasee( type );
else if (is_ptr( type )) type = type_pointer_get_ref( type ); else if (is_ptr( type )) type = type_pointer_get_ref_type( type );
else error( "internal error: %s is not a generic handle\n", type->name ); else error( "internal error: %s is not a generic handle\n", type->name );
} }
LIST_FOR_EACH_ENTRY( gh, &generic_handle_list, generic_handle_t, entry ) LIST_FOR_EACH_ENTRY( gh, &generic_handle_list, generic_handle_t, entry )
...@@ -703,7 +703,7 @@ void check_for_additional_prototype_types(type_t *type) ...@@ -703,7 +703,7 @@ void check_for_additional_prototype_types(type_t *type)
if (type_is_alias(type)) if (type_is_alias(type))
type = type_alias_get_aliasee(type); type = type_alias_get_aliasee(type);
else if (is_ptr(type)) else if (is_ptr(type))
type = type_pointer_get_ref(type); type = type_pointer_get_ref_type(type);
else if (is_array(type)) else if (is_array(type))
type = type_array_get_element_type(type); type = type_array_get_element_type(type);
else else
...@@ -805,7 +805,7 @@ int is_const_decl(const var_t *var) ...@@ -805,7 +805,7 @@ int is_const_decl(const var_t *var)
if (is_attr(t->attrs, ATTR_CONST)) if (is_attr(t->attrs, ATTR_CONST))
return TRUE; return TRUE;
else if (is_ptr(t)) else if (is_ptr(t))
t = type_pointer_get_ref(t); t = type_pointer_get_ref_type(t);
else break; else break;
} }
return FALSE; return FALSE;
...@@ -852,7 +852,7 @@ const type_t* get_explicit_generic_handle_type(const var_t* var) ...@@ -852,7 +852,7 @@ const type_t* get_explicit_generic_handle_type(const var_t* var)
const type_t *t; const type_t *t;
for (t = var->declspec.type; for (t = var->declspec.type;
is_ptr(t) || type_is_alias(t); is_ptr(t) || type_is_alias(t);
t = type_is_alias(t) ? type_alias_get_aliasee(t) : type_pointer_get_ref(t)) t = type_is_alias(t) ? type_alias_get_aliasee(t) : type_pointer_get_ref_type(t))
if ((type_get_type_detect_alias(t) != TYPE_BASIC || type_basic_get_type(t) != TYPE_BASIC_HANDLE) && if ((type_get_type_detect_alias(t) != TYPE_BASIC || type_basic_get_type(t) != TYPE_BASIC_HANDLE) &&
is_attr(t->attrs, ATTR_HANDLE)) is_attr(t->attrs, ATTR_HANDLE))
return t; return t;
......
...@@ -83,7 +83,7 @@ static inline int is_conformant_array(const type_t *t) ...@@ -83,7 +83,7 @@ static inline int is_conformant_array(const type_t *t)
static inline int last_ptr(const type_t *type) static inline int last_ptr(const type_t *type)
{ {
return is_ptr(type) && !is_declptr(type_pointer_get_ref(type)); return is_ptr(type) && !is_declptr(type_pointer_get_ref_type(type));
} }
static inline int last_array(const type_t *type) static inline int last_array(const type_t *type)
...@@ -102,7 +102,7 @@ static inline int is_context_handle(const type_t *type) ...@@ -102,7 +102,7 @@ static inline int is_context_handle(const type_t *type)
const type_t *t; const type_t *t;
for (t = type; for (t = type;
is_ptr(t) || type_is_alias(t); is_ptr(t) || type_is_alias(t);
t = type_is_alias(t) ? type_alias_get_aliasee(t) : type_pointer_get_ref(t)) t = type_is_alias(t) ? type_alias_get_aliasee(t) : type_pointer_get_ref_type(t))
if (is_attr(t->attrs, ATTR_CONTEXTHANDLE)) if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
return 1; return 1;
return 0; return 0;
......
...@@ -1467,7 +1467,7 @@ static int is_allowed_range_type(const type_t *type) ...@@ -1467,7 +1467,7 @@ static int is_allowed_range_type(const type_t *type)
static type_t *get_array_or_ptr_ref(type_t *type) static type_t *get_array_or_ptr_ref(type_t *type)
{ {
if (is_ptr(type)) if (is_ptr(type))
return type_pointer_get_ref(type); return type_pointer_get_ref_type(type);
else if (is_array(type)) else if (is_array(type))
return type_array_get_element_type(type); return type_array_get_element_type(type);
return NULL; return NULL;
...@@ -1483,7 +1483,7 @@ static type_t *append_chain_type(type_t *chain, type_t *type) ...@@ -1483,7 +1483,7 @@ static type_t *append_chain_type(type_t *chain, type_t *type)
; ;
if (is_ptr(chain_type)) if (is_ptr(chain_type))
chain_type->details.pointer.ref = type; chain_type->details.pointer.ref.type = type;
else if (is_array(chain_type)) else if (is_array(chain_type))
chain_type->details.array.elem.type = type; chain_type->details.array.elem.type = type;
else else
...@@ -1526,7 +1526,7 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl ...@@ -1526,7 +1526,7 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
{ {
type_t *t; type_t *t;
/* move inline attribute from return type node to function node */ /* move inline attribute from return type node to function node */
for (t = func_type; is_ptr(t); t = type_pointer_get_ref(t)) for (t = func_type; is_ptr(t); t = type_pointer_get_ref_type(t))
; ;
t->attrs = move_attr(t->attrs, type->attrs, ATTR_INLINE); t->attrs = move_attr(t->attrs, type->attrs, ATTR_INLINE);
} }
...@@ -1557,7 +1557,7 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl ...@@ -1557,7 +1557,7 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
if (is_ptr(ptr)) if (is_ptr(ptr))
{ {
if (ptr_attr && ptr_attr != FC_UP && if (ptr_attr && ptr_attr != FC_UP &&
type_get_type(type_pointer_get_ref(ptr)) == TYPE_INTERFACE) type_get_type(type_pointer_get_ref_type(ptr)) == TYPE_INTERFACE)
warning_loc_info(&v->loc_info, warning_loc_info(&v->loc_info,
"%s: pointer attribute applied to interface " "%s: pointer attribute applied to interface "
"pointer type has no effect\n", v->name); "pointer type has no effect\n", v->name);
...@@ -1585,7 +1585,7 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl ...@@ -1585,7 +1585,7 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
for (;;) for (;;)
{ {
if (is_ptr(t)) if (is_ptr(t))
t = type_pointer_get_ref(t); t = type_pointer_get_ref_type(t);
else if (is_array(t)) else if (is_array(t))
t = type_array_get_element_type(t); t = type_array_get_element_type(t);
else else
...@@ -1628,14 +1628,14 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl ...@@ -1628,14 +1628,14 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
0, dim, NULL, FC_RP); 0, dim, NULL, FC_RP);
} }
else if (is_ptr(*ptype)) else if (is_ptr(*ptype))
*ptype = type_new_array((*ptype)->name, type_pointer_get_ref(*ptype), TRUE, *ptype = type_new_array((*ptype)->name, type_pointer_get_ref_type(*ptype), TRUE,
0, dim, NULL, pointer_default); 0, dim, NULL, pointer_default);
else else
error_loc("%s: size_is attribute applied to illegal type\n", v->name); error_loc("%s: size_is attribute applied to illegal type\n", v->name);
} }
if (is_ptr(*ptype)) if (is_ptr(*ptype))
ptype = &(*ptype)->details.pointer.ref; ptype = &(*ptype)->details.pointer.ref.type;
else if (is_array(*ptype)) else if (is_array(*ptype))
ptype = &(*ptype)->details.array.elem.type; ptype = &(*ptype)->details.array.elem.type;
else else
...@@ -1661,7 +1661,7 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl ...@@ -1661,7 +1661,7 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
} }
if (is_ptr(*ptype)) if (is_ptr(*ptype))
ptype = &(*ptype)->details.pointer.ref; ptype = &(*ptype)->details.pointer.ref.type;
else if (is_array(*ptype)) else if (is_array(*ptype))
ptype = &(*ptype)->details.array.elem.type; ptype = &(*ptype)->details.array.elem.type;
else else
...@@ -1676,20 +1676,20 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl ...@@ -1676,20 +1676,20 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
type_t *ft, *t; type_t *ft, *t;
type_t *return_type = v->declspec.type; type_t *return_type = v->declspec.type;
v->declspec.type = func_type; v->declspec.type = func_type;
for (ft = v->declspec.type; is_ptr(ft); ft = type_pointer_get_ref(ft)) for (ft = v->declspec.type; is_ptr(ft); ft = type_pointer_get_ref_type(ft))
; ;
assert(type_get_type_detect_alias(ft) == TYPE_FUNCTION); assert(type_get_type_detect_alias(ft) == TYPE_FUNCTION);
ft->details.function->retval = make_var(xstrdup("_RetVal")); ft->details.function->retval = make_var(xstrdup("_RetVal"));
ft->details.function->retval->declspec.type = return_type; ft->details.function->retval->declspec.type = return_type;
/* move calling convention attribute, if present, from pointer nodes to /* move calling convention attribute, if present, from pointer nodes to
* function node */ * function node */
for (t = v->declspec.type; is_ptr(t); t = type_pointer_get_ref(t)) for (t = v->declspec.type; is_ptr(t); t = type_pointer_get_ref_type(t))
ft->attrs = move_attr(ft->attrs, t->attrs, ATTR_CALLCONV); ft->attrs = move_attr(ft->attrs, t->attrs, ATTR_CALLCONV);
} }
else else
{ {
type_t *t; type_t *t;
for (t = v->declspec.type; is_ptr(t); t = type_pointer_get_ref(t)) for (t = v->declspec.type; is_ptr(t); t = type_pointer_get_ref_type(t))
if (is_attr(t->attrs, ATTR_CALLCONV)) if (is_attr(t->attrs, ATTR_CALLCONV))
error_loc("calling convention applied to non-function-pointer type\n"); error_loc("calling convention applied to non-function-pointer type\n");
} }
...@@ -2484,7 +2484,7 @@ static int is_ptr_guid_type(const type_t *type) ...@@ -2484,7 +2484,7 @@ static int is_ptr_guid_type(const type_t *type)
/* second, make sure it is a pointer to something of size sizeof(GUID), /* second, make sure it is a pointer to something of size sizeof(GUID),
* i.e. 16 bytes */ * i.e. 16 bytes */
return (type_memsize(type_pointer_get_ref(type)) == 16); return (type_memsize(type_pointer_get_ref_type(type)) == 16);
} }
static void check_conformance_expr_list(const char *attr_name, const var_t *arg, const type_t *container_type, expr_list_t *expr_list) static void check_conformance_expr_list(const char *attr_name, const var_t *arg, const type_t *container_type, expr_list_t *expr_list)
...@@ -2638,13 +2638,13 @@ static void check_field_common(const type_t *container_type, ...@@ -2638,13 +2638,13 @@ static void check_field_common(const type_t *container_type,
{ {
const type_t *t = type; const type_t *t = type;
while (is_ptr(t)) while (is_ptr(t))
t = type_pointer_get_ref(t); t = type_pointer_get_ref_type(t);
if (is_aliaschain_attr(t, ATTR_RANGE)) if (is_aliaschain_attr(t, ATTR_RANGE))
warning_loc_info(&arg->loc_info, "%s: range not verified for a string of ranged types\n", arg->name); warning_loc_info(&arg->loc_info, "%s: range not verified for a string of ranged types\n", arg->name);
break; break;
} }
case TGT_POINTER: case TGT_POINTER:
type = type_pointer_get_ref(type); type = type_pointer_get_ref_type(type);
more_to_do = TRUE; more_to_do = TRUE;
break; break;
case TGT_ARRAY: case TGT_ARRAY:
......
...@@ -107,8 +107,8 @@ static void clear_output_vars( const var_list_t *args ) ...@@ -107,8 +107,8 @@ static void clear_output_vars( const var_list_t *args )
if (!is_attr(arg->attrs, ATTR_OUT)) continue; if (!is_attr(arg->attrs, ATTR_OUT)) continue;
if (is_ptr(arg->declspec.type)) if (is_ptr(arg->declspec.type))
{ {
if (type_get_type(type_pointer_get_ref(arg->declspec.type)) == TYPE_BASIC) continue; if (type_get_type(type_pointer_get_ref_type(arg->declspec.type)) == TYPE_BASIC) continue;
if (type_get_type(type_pointer_get_ref(arg->declspec.type)) == TYPE_ENUM) continue; if (type_get_type(type_pointer_get_ref_type(arg->declspec.type)) == TYPE_ENUM) continue;
} }
print_proxy( "if (%s) MIDL_memset( %s, 0, ", arg->name, arg->name ); print_proxy( "if (%s) MIDL_memset( %s, 0, ", arg->name, arg->name );
if (is_array(arg->declspec.type) && type_array_has_conformance(arg->declspec.type)) if (is_array(arg->declspec.type) && type_array_has_conformance(arg->declspec.type))
......
...@@ -99,7 +99,7 @@ static unsigned short builtin_vt(const type_t *t) ...@@ -99,7 +99,7 @@ static unsigned short builtin_vt(const type_t *t)
if (is_array(t)) if (is_array(t))
elem_type = type_array_get_element_type(t); elem_type = type_array_get_element_type(t);
else else
elem_type = type_pointer_get_ref(t); elem_type = type_pointer_get_ref_type(t);
if (type_get_type(elem_type) == TYPE_BASIC) if (type_get_type(elem_type) == TYPE_BASIC)
{ {
switch (type_basic_get_type(elem_type)) switch (type_basic_get_type(elem_type))
......
...@@ -182,7 +182,7 @@ type_t *type_new_pointer(unsigned char pointer_default, type_t *ref, attr_list_t ...@@ -182,7 +182,7 @@ type_t *type_new_pointer(unsigned char pointer_default, type_t *ref, attr_list_t
{ {
type_t *t = make_type(TYPE_POINTER); type_t *t = make_type(TYPE_POINTER);
t->details.pointer.def_fc = pointer_default; t->details.pointer.def_fc = pointer_default;
t->details.pointer.ref = ref; t->details.pointer.ref.type = ref;
t->attrs = attrs; t->attrs = attrs;
return t; return t;
} }
......
...@@ -294,11 +294,16 @@ static inline ifref_list_t *type_coclass_get_ifaces(const type_t *type) ...@@ -294,11 +294,16 @@ static inline ifref_list_t *type_coclass_get_ifaces(const type_t *type)
return type->details.coclass.ifaces; return type->details.coclass.ifaces;
} }
static inline type_t *type_pointer_get_ref(const type_t *type) static inline const decl_spec_t *type_pointer_get_ref(const type_t *type)
{ {
type = type_get_real_type(type); type = type_get_real_type(type);
assert(type_get_type(type) == TYPE_POINTER); assert(type_get_type(type) == TYPE_POINTER);
return type->details.pointer.ref; return &type->details.pointer.ref;
}
static inline type_t *type_pointer_get_ref_type(const type_t *type)
{
return type_pointer_get_ref(type)->type;
} }
static inline unsigned char type_pointer_get_default_fc(const type_t *type) static inline unsigned char type_pointer_get_default_fc(const type_t *type)
......
...@@ -384,7 +384,7 @@ struct basic_details ...@@ -384,7 +384,7 @@ struct basic_details
struct pointer_details struct pointer_details
{ {
struct _type_t *ref; struct _decl_spec_t ref;
unsigned char def_fc; unsigned char def_fc;
}; };
...@@ -458,7 +458,6 @@ struct _type_t { ...@@ -458,7 +458,6 @@ struct _type_t {
struct _var_t { struct _var_t {
char *name; char *name;
decl_spec_t declspec; decl_spec_t declspec;
attr_list_t *attrs; attr_list_t *attrs;
expr_t *eval; expr_t *eval;
unsigned int procstring_offset; unsigned int procstring_offset;
......
...@@ -862,8 +862,8 @@ static int encode_type( ...@@ -862,8 +862,8 @@ static int encode_type(
case VT_PTR: case VT_PTR:
{ {
int next_vt; int next_vt;
for(next_vt = 0; is_ptr(type); type = type_pointer_get_ref(type)) { for(next_vt = 0; is_ptr(type); type = type_pointer_get_ref_type(type)) {
next_vt = get_type_vt(type_pointer_get_ref(type)); next_vt = get_type_vt(type_pointer_get_ref_type(type));
if (next_vt != 0) if (next_vt != 0)
break; break;
} }
...@@ -871,7 +871,7 @@ static int encode_type( ...@@ -871,7 +871,7 @@ static int encode_type(
if (next_vt == 0) if (next_vt == 0)
next_vt = VT_VOID; next_vt = VT_VOID;
encode_type(typelib, next_vt, type_pointer_get_ref(type), encode_type(typelib, next_vt, type_pointer_get_ref_type(type),
&target_type, &child_size); &target_type, &child_size);
/* these types already have an implicit pointer, so we don't need to /* these types already have an implicit pointer, so we don't need to
* add another */ * add another */
...@@ -1093,7 +1093,7 @@ static int encode_var( ...@@ -1093,7 +1093,7 @@ static int encode_var(
vt = get_type_vt(type); vt = get_type_vt(type);
if (vt == VT_PTR) { if (vt == VT_PTR) {
type_t *ref = is_ptr(type) ? type_t *ref = is_ptr(type) ?
type_pointer_get_ref(type) : type_array_get_element_type(type); type_pointer_get_ref_type(type) : type_array_get_element_type(type);
int skip_ptr = encode_var(typelib, ref, var, &target_type, &child_size); int skip_ptr = encode_var(typelib, ref, var, &target_type, &child_size);
if(skip_ptr == 2) { if(skip_ptr == 2) {
...@@ -1204,7 +1204,7 @@ static void write_default_value(msft_typelib_t *typelib, type_t *type, expr_t *e ...@@ -1204,7 +1204,7 @@ static void write_default_value(msft_typelib_t *typelib, type_t *type, expr_t *e
if (type_get_type(type) == TYPE_ENUM) { if (type_get_type(type) == TYPE_ENUM) {
vt = VT_I4; vt = VT_I4;
} else if (is_ptr(type)) { } else if (is_ptr(type)) {
vt = get_type_vt(type_pointer_get_ref(type)); vt = get_type_vt(type_pointer_get_ref_type(type));
if (vt == VT_USERDEFINED) if (vt == VT_USERDEFINED)
vt = VT_I4; vt = VT_I4;
if (expr->cval) if (expr->cval)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment