Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
a83563aa
Commit
a83563aa
authored
Mar 26, 2010
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
widl: Long constants must be 32-bit on all platforms.
parent
bd6f2181
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
33 additions
and
33 deletions
+33
-33
expr.c
tools/widl/expr.c
+4
-4
expr.h
tools/widl/expr.h
+1
-1
header.c
tools/widl/header.c
+2
-2
header.h
tools/widl/header.h
+1
-1
parser.l
tools/widl/parser.l
+5
-5
parser.y
tools/widl/parser.y
+2
-2
typegen.c
tools/widl/typegen.c
+8
-8
widltypes.h
tools/widl/widltypes.h
+3
-3
write_msft.c
tools/widl/write_msft.c
+7
-7
No files found.
tools/widl/expr.c
View file @
a83563aa
...
@@ -117,7 +117,7 @@ expr_t *make_expr(enum expr_type type)
...
@@ -117,7 +117,7 @@ expr_t *make_expr(enum expr_type type)
return
e
;
return
e
;
}
}
expr_t
*
make_exprl
(
enum
expr_type
type
,
long
val
)
expr_t
*
make_exprl
(
enum
expr_type
type
,
int
val
)
{
{
expr_t
*
e
=
xmalloc
(
sizeof
(
expr_t
));
expr_t
*
e
=
xmalloc
(
sizeof
(
expr_t
));
e
->
type
=
type
;
e
->
type
=
type
;
...
@@ -218,7 +218,7 @@ expr_t *make_exprt(enum expr_type type, var_t *var, expr_t *expr)
...
@@ -218,7 +218,7 @@ expr_t *make_exprt(enum expr_type type, var_t *var, expr_t *expr)
{
{
unsigned
int
align
=
0
;
unsigned
int
align
=
0
;
unsigned
int
cast_type_bits
=
type_memsize
(
tref
,
&
align
)
*
8
;
unsigned
int
cast_type_bits
=
type_memsize
(
tref
,
&
align
)
*
8
;
unsigned
long
cast_mask
;
unsigned
int
cast_mask
;
e
->
is_const
=
TRUE
;
e
->
is_const
=
TRUE
;
if
(
is_signed_integer_type
(
tref
))
if
(
is_signed_integer_type
(
tref
))
...
@@ -699,10 +699,10 @@ void write_expr(FILE *h, const expr_t *e, int brackets,
...
@@ -699,10 +699,10 @@ void write_expr(FILE *h, const expr_t *e, int brackets,
case
EXPR_VOID
:
case
EXPR_VOID
:
break
;
break
;
case
EXPR_NUM
:
case
EXPR_NUM
:
fprintf
(
h
,
"%
l
u"
,
e
->
u
.
lval
);
fprintf
(
h
,
"%u"
,
e
->
u
.
lval
);
break
;
break
;
case
EXPR_HEXNUM
:
case
EXPR_HEXNUM
:
fprintf
(
h
,
"0x%
l
x"
,
e
->
u
.
lval
);
fprintf
(
h
,
"0x%x"
,
e
->
u
.
lval
);
break
;
break
;
case
EXPR_DOUBLE
:
case
EXPR_DOUBLE
:
fprintf
(
h
,
"%#.15g"
,
e
->
u
.
dval
);
fprintf
(
h
,
"%#.15g"
,
e
->
u
.
dval
);
...
...
tools/widl/expr.h
View file @
a83563aa
...
@@ -26,7 +26,7 @@ struct expr_loc
...
@@ -26,7 +26,7 @@ struct expr_loc
};
};
extern
expr_t
*
make_expr
(
enum
expr_type
type
);
extern
expr_t
*
make_expr
(
enum
expr_type
type
);
extern
expr_t
*
make_exprl
(
enum
expr_type
type
,
long
val
);
extern
expr_t
*
make_exprl
(
enum
expr_type
type
,
int
val
);
extern
expr_t
*
make_exprd
(
enum
expr_type
type
,
double
val
);
extern
expr_t
*
make_exprd
(
enum
expr_type
type
,
double
val
);
extern
expr_t
*
make_exprs
(
enum
expr_type
type
,
char
*
val
);
extern
expr_t
*
make_exprs
(
enum
expr_type
type
,
char
*
val
);
extern
expr_t
*
make_exprt
(
enum
expr_type
type
,
var_t
*
var
,
expr_t
*
expr
);
extern
expr_t
*
make_exprt
(
enum
expr_type
type
,
var_t
*
var
,
expr_t
*
expr
);
...
...
tools/widl/header.c
View file @
a83563aa
...
@@ -100,7 +100,7 @@ void *get_attrp(const attr_list_t *list, enum attr_type t)
...
@@ -100,7 +100,7 @@ void *get_attrp(const attr_list_t *list, enum attr_type t)
return
NULL
;
return
NULL
;
}
}
unsigned
long
get_attrv
(
const
attr_list_t
*
list
,
enum
attr_type
t
)
unsigned
int
get_attrv
(
const
attr_list_t
*
list
,
enum
attr_type
t
)
{
{
const
attr_t
*
attr
;
const
attr_t
*
attr
;
if
(
list
)
LIST_FOR_EACH_ENTRY
(
attr
,
list
,
const
attr_t
,
entry
)
if
(
list
)
LIST_FOR_EACH_ENTRY
(
attr
,
list
,
const
attr_t
,
entry
)
...
@@ -334,7 +334,7 @@ void write_type_right(FILE *h, type_t *t, int is_field)
...
@@ -334,7 +334,7 @@ void write_type_right(FILE *h, type_t *t, int is_field)
}
}
break
;
break
;
case
TYPE_BITFIELD
:
case
TYPE_BITFIELD
:
fprintf
(
h
,
" : %
l
u"
,
type_bitfield_get_bits
(
t
)
->
cval
);
fprintf
(
h
,
" : %u"
,
type_bitfield_get_bits
(
t
)
->
cval
);
break
;
break
;
case
TYPE_VOID
:
case
TYPE_VOID
:
case
TYPE_BASIC
:
case
TYPE_BASIC
:
...
...
tools/widl/header.h
View file @
a83563aa
...
@@ -27,7 +27,7 @@ extern int is_ptrchain_attr(const var_t *var, enum attr_type t);
...
@@ -27,7 +27,7 @@ extern int is_ptrchain_attr(const var_t *var, enum attr_type t);
extern
int
is_aliaschain_attr
(
const
type_t
*
var
,
enum
attr_type
t
);
extern
int
is_aliaschain_attr
(
const
type_t
*
var
,
enum
attr_type
t
);
extern
int
is_attr
(
const
attr_list_t
*
list
,
enum
attr_type
t
);
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
void
*
get_attrp
(
const
attr_list_t
*
list
,
enum
attr_type
t
);
extern
unsigned
long
get_attrv
(
const
attr_list_t
*
list
,
enum
attr_type
t
);
extern
unsigned
int
get_attrv
(
const
attr_list_t
*
list
,
enum
attr_type
t
);
extern
int
is_void
(
const
type_t
*
t
);
extern
int
is_void
(
const
type_t
*
t
);
extern
int
is_conformant_array
(
const
type_t
*
t
);
extern
int
is_conformant_array
(
const
type_t
*
t
);
extern
int
is_declptr
(
const
type_t
*
t
);
extern
int
is_declptr
(
const
type_t
*
t
);
...
...
tools/widl/parser.l
View file @
a83563aa
...
@@ -85,15 +85,15 @@ int import_stack_ptr = 0;
...
@@ -85,15 +85,15 @@ int import_stack_ptr = 0;
/* converts an integer in string form to an unsigned long and prints an error
/* converts an integer in string form to an unsigned long and prints an error
* on overflow */
* on overflow */
static unsigned
long
xstrtoul(const char *nptr, char **endptr, int base)
static unsigned
int
xstrtoul(const char *nptr, char **endptr, int base)
{
{
unsigned long l;
unsigned long
va
l;
errno = 0;
errno = 0;
l = strtoul(nptr, endptr, base);
va
l = strtoul(nptr, endptr, base);
if (
l == ULONG_MAX && errno == ERANGE
)
if (
(val == ULONG_MAX && errno == ERANGE) || ((unsigned int)val != val)
)
error_loc("integer constant %s is too large\n", nptr);
error_loc("integer constant %s is too large\n", nptr);
return l;
return
va
l;
}
}
UUID *parse_uuid(const char *u)
UUID *parse_uuid(const char *u)
...
...
tools/widl/parser.y
View file @
a83563aa
...
@@ -97,7 +97,7 @@ static attr_list_t *append_attr(attr_list_t *list, attr_t *attr);
...
@@ -97,7 +97,7 @@ static attr_list_t *append_attr(attr_list_t *list, attr_t *attr);
static attr_list_t *append_attr_list(attr_list_t *new_list, attr_list_t *old_list);
static attr_list_t *append_attr_list(attr_list_t *new_list, attr_list_t *old_list);
static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, attr_t *attr, enum storage_class stgclass);
static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, attr_t *attr, enum storage_class stgclass);
static attr_t *make_attr(enum attr_type type);
static attr_t *make_attr(enum attr_type type);
static attr_t *make_attrv(enum attr_type type, unsigned
long
val);
static attr_t *make_attrv(enum attr_type type, unsigned
int
val);
static attr_t *make_attrp(enum attr_type type, void *val);
static attr_t *make_attrp(enum attr_type type, void *val);
static expr_list_t *append_expr(expr_list_t *list, expr_t *expr);
static expr_list_t *append_expr(expr_list_t *list, expr_t *expr);
static array_dims_t *append_array(array_dims_t *list, expr_t *expr);
static array_dims_t *append_array(array_dims_t *list, expr_t *expr);
...
@@ -1248,7 +1248,7 @@ static attr_t *make_attr(enum attr_type type)
...
@@ -1248,7 +1248,7 @@ static attr_t *make_attr(enum attr_type type)
return a;
return a;
}
}
static attr_t *make_attrv(enum attr_type type, unsigned
long
val)
static attr_t *make_attrv(enum attr_type type, unsigned
int
val)
{
{
attr_t *a = xmalloc(sizeof(attr_t));
attr_t *a = xmalloc(sizeof(attr_t));
a->type = type;
a->type = type;
...
...
tools/widl/typegen.c
View file @
a83563aa
...
@@ -988,13 +988,13 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *structure,
...
@@ -988,13 +988,13 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *structure,
if
(
expr
->
is_const
)
if
(
expr
->
is_const
)
{
{
if
(
expr
->
cval
>
UCHAR_MAX
*
(
USHRT_MAX
+
1
)
+
USHRT_MAX
)
if
(
expr
->
cval
>
UCHAR_MAX
*
(
USHRT_MAX
+
1
)
+
USHRT_MAX
)
error
(
"write_conf_or_var_desc: constant value %
l
d is greater than "
error
(
"write_conf_or_var_desc: constant value %d is greater than "
"the maximum constant size of %d
\n
"
,
expr
->
cval
,
"the maximum constant size of %d
\n
"
,
expr
->
cval
,
UCHAR_MAX
*
(
USHRT_MAX
+
1
)
+
USHRT_MAX
);
UCHAR_MAX
*
(
USHRT_MAX
+
1
)
+
USHRT_MAX
);
print_file
(
file
,
2
,
"0x%x, /* Corr desc: constant, val = %
l
d */
\n
"
,
print_file
(
file
,
2
,
"0x%x, /* Corr desc: constant, val = %d */
\n
"
,
RPC_FC_CONSTANT_CONFORMANCE
,
expr
->
cval
);
RPC_FC_CONSTANT_CONFORMANCE
,
expr
->
cval
);
print_file
(
file
,
2
,
"0x%
l
x,
\n
"
,
expr
->
cval
>>
16
);
print_file
(
file
,
2
,
"0x%x,
\n
"
,
expr
->
cval
>>
16
);
print_file
(
file
,
2
,
"NdrFcShort(0x%hx),
\n
"
,
(
unsigned
short
)
expr
->
cval
);
print_file
(
file
,
2
,
"NdrFcShort(0x%hx),
\n
"
,
(
unsigned
short
)
expr
->
cval
);
return
4
;
return
4
;
...
@@ -2655,7 +2655,7 @@ static unsigned int write_union_tfs(FILE *file, type_t *type, unsigned int *tfso
...
@@ -2655,7 +2655,7 @@ static unsigned int write_union_tfs(FILE *file, type_t *type, unsigned int *tfso
/* MIDL doesn't check for duplicate cases, even though that seems
/* MIDL doesn't check for duplicate cases, even though that seems
like a reasonable thing to do, it just dumps them to the TFS
like a reasonable thing to do, it just dumps them to the TFS
like we're going to do here. */
like we're going to do here. */
print_file
(
file
,
2
,
"NdrFcLong(0x%
lx),
\t
/* %l
d */
\n
"
,
c
->
cval
,
c
->
cval
);
print_file
(
file
,
2
,
"NdrFcLong(0x%
x),
\t
/* %
d */
\n
"
,
c
->
cval
,
c
->
cval
);
*
tfsoff
+=
4
;
*
tfsoff
+=
4
;
write_branch_type
(
file
,
ft
,
tfsoff
);
write_branch_type
(
file
,
ft
,
tfsoff
);
}
}
...
@@ -2793,8 +2793,8 @@ static unsigned int write_range_tfs(FILE *file, const attr_list_t *attrs,
...
@@ -2793,8 +2793,8 @@ static unsigned int write_range_tfs(FILE *file, const attr_list_t *attrs,
print_file
(
file
,
0
,
"/* %u */
\n
"
,
*
typeformat_offset
);
print_file
(
file
,
0
,
"/* %u */
\n
"
,
*
typeformat_offset
);
print_file
(
file
,
2
,
"0x%x,
\t
/* FC_RANGE */
\n
"
,
RPC_FC_RANGE
);
print_file
(
file
,
2
,
"0x%x,
\t
/* FC_RANGE */
\n
"
,
RPC_FC_RANGE
);
print_file
(
file
,
2
,
"0x%x,
\t
/* %s */
\n
"
,
fc
,
string_of_type
(
fc
));
print_file
(
file
,
2
,
"0x%x,
\t
/* %s */
\n
"
,
fc
,
string_of_type
(
fc
));
print_file
(
file
,
2
,
"NdrFcLong(0x%
lx),
\t
/* %l
u */
\n
"
,
range_min
->
cval
,
range_min
->
cval
);
print_file
(
file
,
2
,
"NdrFcLong(0x%
x),
\t
/* %
u */
\n
"
,
range_min
->
cval
,
range_min
->
cval
);
print_file
(
file
,
2
,
"NdrFcLong(0x%
lx),
\t
/* %l
u */
\n
"
,
range_max
->
cval
,
range_max
->
cval
);
print_file
(
file
,
2
,
"NdrFcLong(0x%
x),
\t
/* %
u */
\n
"
,
range_max
->
cval
,
range_max
->
cval
);
*
typeformat_offset
+=
10
;
*
typeformat_offset
+=
10
;
return
start_offset
;
return
start_offset
;
...
@@ -3604,9 +3604,9 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const
...
@@ -3604,9 +3604,9 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const
print_file
(
file
,
indent
,
"if ((%s%s < ("
,
local_var_prefix
,
var
->
name
);
print_file
(
file
,
indent
,
"if ((%s%s < ("
,
local_var_prefix
,
var
->
name
);
write_type_decl
(
file
,
var
->
type
,
NULL
);
write_type_decl
(
file
,
var
->
type
,
NULL
);
fprintf
(
file
,
")0x%
l
x) || (%s%s > ("
,
range_min
->
cval
,
local_var_prefix
,
var
->
name
);
fprintf
(
file
,
")0x%x) || (%s%s > ("
,
range_min
->
cval
,
local_var_prefix
,
var
->
name
);
write_type_decl
(
file
,
var
->
type
,
NULL
);
write_type_decl
(
file
,
var
->
type
,
NULL
);
fprintf
(
file
,
")0x%
l
x))
\n
"
,
range_max
->
cval
);
fprintf
(
file
,
")0x%x))
\n
"
,
range_max
->
cval
);
print_file
(
file
,
indent
,
"{
\n
"
);
print_file
(
file
,
indent
,
"{
\n
"
);
print_file
(
file
,
indent
+
1
,
"RpcRaiseException(RPC_S_INVALID_BOUND);
\n
"
);
print_file
(
file
,
indent
+
1
,
"RpcRaiseException(RPC_S_INVALID_BOUND);
\n
"
);
print_file
(
file
,
indent
,
"}
\n
"
);
print_file
(
file
,
indent
,
"}
\n
"
);
...
...
tools/widl/widltypes.h
View file @
a83563aa
...
@@ -255,7 +255,7 @@ struct str_list_entry_t
...
@@ -255,7 +255,7 @@ struct str_list_entry_t
struct
_attr_t
{
struct
_attr_t
{
enum
attr_type
type
;
enum
attr_type
type
;
union
{
union
{
unsigned
long
ival
;
unsigned
int
ival
;
void
*
pval
;
void
*
pval
;
}
u
;
}
u
;
/* parser-internal */
/* parser-internal */
...
@@ -266,7 +266,7 @@ struct _expr_t {
...
@@ -266,7 +266,7 @@ struct _expr_t {
enum
expr_type
type
;
enum
expr_type
type
;
const
expr_t
*
ref
;
const
expr_t
*
ref
;
union
{
union
{
long
lval
;
int
lval
;
double
dval
;
double
dval
;
const
char
*
sval
;
const
char
*
sval
;
const
expr_t
*
ext
;
const
expr_t
*
ext
;
...
@@ -274,7 +274,7 @@ struct _expr_t {
...
@@ -274,7 +274,7 @@ struct _expr_t {
}
u
;
}
u
;
const
expr_t
*
ext2
;
const
expr_t
*
ext2
;
int
is_const
;
int
is_const
;
long
cval
;
int
cval
;
/* parser-internal */
/* parser-internal */
struct
list
entry
;
struct
list
entry
;
};
};
...
...
tools/widl/write_msft.c
View file @
a83563aa
...
@@ -1157,7 +1157,7 @@ static int encode_var(
...
@@ -1157,7 +1157,7 @@ static int encode_var(
return
0
;
return
0
;
}
}
static
unsigned
long
get_ulong_val
(
unsigned
long
val
,
int
vt
)
static
unsigned
int
get_ulong_val
(
unsigned
int
val
,
int
vt
)
{
{
switch
(
vt
)
{
switch
(
vt
)
{
case
VT_I2
:
case
VT_I2
:
...
@@ -1188,7 +1188,7 @@ static void write_value(msft_typelib_t* typelib, int *out, int vt, const void *v
...
@@ -1188,7 +1188,7 @@ static void write_value(msft_typelib_t* typelib, int *out, int vt, const void *v
case
VT_HRESULT
:
case
VT_HRESULT
:
case
VT_PTR
:
case
VT_PTR
:
{
{
const
unsigned
long
lv
=
get_ulong_val
(
*
(
const
unsigned
long
*
)
value
,
vt
);
const
unsigned
int
lv
=
get_ulong_val
(
*
(
const
unsigned
int
*
)
value
,
vt
);
if
((
lv
&
0x3ffffff
)
==
lv
)
{
if
((
lv
&
0x3ffffff
)
==
lv
)
{
*
out
=
0x80000000
;
*
out
=
0x80000000
;
*
out
|=
vt
<<
26
;
*
out
|=
vt
<<
26
;
...
@@ -1226,7 +1226,7 @@ static void write_value(msft_typelib_t* typelib, int *out, int vt, const void *v
...
@@ -1226,7 +1226,7 @@ static void write_value(msft_typelib_t* typelib, int *out, int vt, const void *v
}
}
static
HRESULT
set_custdata
(
msft_typelib_t
*
typelib
,
REFGUID
guid
,
static
HRESULT
set_custdata
(
msft_typelib_t
*
typelib
,
REFGUID
guid
,
int
vt
,
void
*
value
,
int
*
offset
)
int
vt
,
int
value
,
int
*
offset
)
{
{
MSFT_GuidEntry
guidentry
;
MSFT_GuidEntry
guidentry
;
int
guidoffset
;
int
guidoffset
;
...
@@ -1240,7 +1240,7 @@ static HRESULT set_custdata(msft_typelib_t *typelib, REFGUID guid,
...
@@ -1240,7 +1240,7 @@ static HRESULT set_custdata(msft_typelib_t *typelib, REFGUID guid,
guidentry
.
next_hash
=
-
1
;
guidentry
.
next_hash
=
-
1
;
guidoffset
=
ctl2_alloc_guid
(
typelib
,
&
guidentry
);
guidoffset
=
ctl2_alloc_guid
(
typelib
,
&
guidentry
);
write_value
(
typelib
,
&
data_out
,
vt
,
value
);
write_value
(
typelib
,
&
data_out
,
vt
,
&
value
);
custoffset
=
ctl2_alloc_segment
(
typelib
,
MSFT_SEG_CUSTDATAGUID
,
12
,
0
);
custoffset
=
ctl2_alloc_segment
(
typelib
,
MSFT_SEG_CUSTDATAGUID
,
12
,
0
);
...
@@ -1484,7 +1484,7 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index)
...
@@ -1484,7 +1484,7 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index)
}
}
else
else
{
{
chat
(
"default value %
l
d
\n
"
,
expr
->
cval
);
chat
(
"default value %d
\n
"
,
expr
->
cval
);
write_value
(
typeinfo
->
typelib
,
defaultdata
,
vt
,
&
expr
->
cval
);
write_value
(
typeinfo
->
typelib
,
defaultdata
,
vt
,
&
expr
->
cval
);
}
}
break
;
break
;
...
@@ -2599,8 +2599,8 @@ int create_msft_typelib(typelib_t *typelib)
...
@@ -2599,8 +2599,8 @@ int create_msft_typelib(typelib_t *typelib)
and midl's version number */
and midl's version number */
time_override
=
getenv
(
"WIDL_TIME_OVERRIDE"
);
time_override
=
getenv
(
"WIDL_TIME_OVERRIDE"
);
cur_time
=
time_override
?
atol
(
time_override
)
:
time
(
NULL
);
cur_time
=
time_override
?
atol
(
time_override
)
:
time
(
NULL
);
set_custdata
(
msft
,
&
midl_time_guid
,
VT_UI4
,
&
cur_time
,
&
msft
->
typelib_header
.
CustomDataOffset
);
set_custdata
(
msft
,
&
midl_time_guid
,
VT_UI4
,
cur_time
,
&
msft
->
typelib_header
.
CustomDataOffset
);
set_custdata
(
msft
,
&
midl_version_guid
,
VT_UI4
,
&
version
,
&
msft
->
typelib_header
.
CustomDataOffset
);
set_custdata
(
msft
,
&
midl_version_guid
,
VT_UI4
,
version
,
&
msft
->
typelib_header
.
CustomDataOffset
);
if
(
typelib
->
stmts
)
if
(
typelib
->
stmts
)
LIST_FOR_EACH_ENTRY
(
stmt
,
typelib
->
stmts
,
const
statement_t
,
entry
)
LIST_FOR_EACH_ENTRY
(
stmt
,
typelib
->
stmts
,
const
statement_t
,
entry
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment