Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
proview
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Esteban Blanc
proview
Commits
745a9609
Commit
745a9609
authored
Apr 20, 2010
by
claes
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
CustomBuild configuration object and generation of custom_build.sh file
parent
654643b6
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
357 additions
and
13 deletions
+357
-13
src/lib/rt/src/rt_load.x
src/lib/rt/src/rt_load.x
+1
-0
src/wbl/pwrb/src/pwrb_c_custombuild.wb_load
src/wbl/pwrb/src/pwrb_c_custombuild.wb_load
+102
-0
src/wbl/pwrs/src/pwrs_td_opsysenum.wb_load
src/wbl/pwrs/src/pwrs_td_opsysenum.wb_load
+10
-0
src/wbl/pwrs/src/pwrs_td_opsysmask.wb_load
src/wbl/pwrs/src/pwrs_td_opsysmask.wb_load
+10
-0
wb/exp/wb/src/pwr_wb_palette.cnf
wb/exp/wb/src/pwr_wb_palette.cnf
+1
-0
wb/lib/wb/src/wb_lfu.cpp
wb/lib/wb/src/wb_lfu.cpp
+212
-3
wb/lib/wb/src/wb_pkg.cpp
wb/lib/wb/src/wb_pkg.cpp
+13
-9
wb/lib/wb/src/wb_pkg.h
wb/lib/wb/src/wb_pkg.h
+8
-1
No files found.
src/lib/rt/src/rt_load.x
View file @
745a9609
...
...
@@ -68,6 +68,7 @@
%# define load_cNameRttCrrCode "rtt_crrc_%3.3d_%3.3d_%3.3d_%3.3d.dat"
%# define load_cNameRttPlc "rtt_plc_%3.3d_%3.3d_%3.3d_%3.3d.dat"
%# define load_cNamePkg "pwrp_pkg_%s_%04d.tgz"
%# define load_cNameCustomBuild "$pwrp_exe/custom_build.sh"
%#endif
%
%
...
...
src/wbl/pwrb/src/pwrb_c_custombuild.wb_load
0 → 100644
View file @
745a9609
!
! Proview $Id$
! Copyright (C) 2005 SSAB Oxelsund AB.
!
! This program is free software; you can redistribute it and/or
! modify it under the terms of the GNU General Public License as
! published by the Free Software Foundation, either version 2 of
! the License, or (at your option) any later version.
!
! This program is distributed in the hope that it will be useful
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with the program, if not, write to the Free Software
! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
!
! pwrb_c_distribute.wb_load -- Defines the class Distribute.
!
SObject pwrb:Class
!/**
! @Version 1.0
! @Group ProjectConfiguration
! @Summary Configures cumstomized build.
! Configures custumized build for embedded systems with cross compilation.
!
! @b See also
! @classlink NodeConfig pwrb_nodeconfig.html
! @classlink ApplDistribute pwrb_appldistribute.html
!*/
Object CustomBuild $ClassDef 542
Body SysBody
Attr Editor = pwr_eEditor_AttrEd
Attr Method = pwr_eMethod_RtAndDevBodies
EndBody
Object DevBody $ObjBodyDef 2
!/**
! c compiler, e.g arm-linux-gnueabi-gcc.
!*/
Object cc $Attribute 1
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!/**
! c++ compiler, e.g arm-linux-gnueabi-g++.
!*/
Object cxx $Attribute 2
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!/**
! archiver, e.g arm-linux-gnueabi-ar.
!*/
Object ar $Attribute 3
Body SysBody
Attr TypeRef = "pwrs:Type-$String80"
EndBody
EndObject
!/**
! Operating system.
!*/
Object OperatingSystem $Attribute 4
Body SysBody
Attr TypeRef = "pwrs:Type-$OpSysEnum"
EndBody
EndObject
!/**
! Build directories.
!*/
Object Platform $Attribute 5
Body SysBody
Attr TypeRef = "pwrs:Type-$String40"
EndBody
EndObject
!/**
! Release.
!*/
Object Release $Attribute 6
Body SysBody
Attr TypeRef = "pwrs:Type-$String40"
EndBody
EndObject
EndObject
Object Template CustomBuild
EndObject
EndObject
EndSObject
src/wbl/pwrs/src/pwrs_td_opsysenum.wb_load
View file @
745a9609
...
...
@@ -120,5 +120,15 @@ SObject pwrs:Type
Attr Value = 256
EndBody
EndObject
!/**
! Operating system is Linux on ARM
!*/
Object ARM_LINUX $Value
Body SysBody
Attr PgmName = "ARM_LINUX"
Attr Text = "Linux on ARM"
Attr Value = 512
EndBody
EndObject
EndObject
EndSObject
src/wbl/pwrs/src/pwrs_td_opsysmask.wb_load
View file @
745a9609
...
...
@@ -123,5 +123,15 @@ SObject pwrs:Type
Attr Value = 256
EndBody
EndObject
!/**
! Operating system is Mac OS X on x86_64
!*/
Object ARM_LINUX $Bit
Body SysBody
Attr PgmName = "ARM_X86"
Attr Text = "Linux on ARM"
Attr Value = 512
EndBody
EndObject
EndObject
EndSObject
wb/exp/wb/src/pwr_wb_palette.cnf
View file @
745a9609
...
...
@@ -464,6 +464,7 @@ palette ProjectNavigatorPalette
class ApplDistribute
class BusConfig
class ClassVolumeLoad
class CustomBuild
class Distribute
class DetachedClassVolumeLoad
class FriendNodeConfig
...
...
wb/lib/wb/src/wb_lfu.cpp
View file @
745a9609
...
...
@@ -667,6 +667,7 @@ pwr_tStatus lfu_SaveDirectoryVolume(
char
fname
[
200
];
char
path
[
80
];
int
path_file_created
=
0
;
pwr_tString80
custom_platform
;
syntax_error
=
0
;
strcpy
(
null_nodename
,
"-"
);
...
...
@@ -2056,17 +2057,65 @@ pwr_tStatus lfu_SaveDirectoryVolume(
if
(
!
found
)
distr_options
=
(
lfu_mDistrOpt
)((
int
)
distr_options
|
lfu_mDistrOpt_NoRootVolume
);
fprintf
(
file
,
"node %s %s %d %d %s
\n
"
,
strcpy
(
custom_platform
,
"-"
);
/* Find any CustomBuild for this node */
class_vect
[
0
]
=
pwr_cClass_CustomBuild
;
class_vect
[
1
]
=
0
;
objcount
=
0
;
objlist
=
0
;
sts
=
trv_create_ctx
(
&
trvctx
,
ldhses
,
nodeobjid
,
class_vect
,
NULL
,
NULL
);
if
(
EVEN
(
sts
))
return
sts
;
sts
=
trv_object_search
(
trvctx
,
&
utl_objidlist_insert
,
&
objlist
,
&
objcount
,
0
,
0
,
0
);
if
(
EVEN
(
sts
))
return
sts
;
sts
=
trv_delete_ctx
(
trvctx
);
for
(
obj_ptr
=
objlist
;
obj_ptr
;
obj_ptr
=
obj_ptr
->
next
)
{
applobjid
=
obj_ptr
->
objid
;
sts
=
ldh_GetObjectClass
(
ldhses
,
applobjid
,
&
ccid
);
if
(
EVEN
(
sts
))
return
sts
;
switch
(
ccid
)
{
case
pwr_cClass_CustomBuild
:
{
char
*
platform_p
;
sts
=
ldh_ObjidToName
(
ldhses
,
applobjid
,
ldh_eName_Object
,
appl_name
,
sizeof
(
appl_name
),
&
size
);
if
(
EVEN
(
sts
))
return
sts
;
/* Check Source attribute */
sts
=
ldh_GetObjectPar
(
ldhses
,
applobjid
,
"DevBody"
,
"Platform"
,
&
platform_p
,
&
size
);
if
(
EVEN
(
sts
))
return
sts
;
if
(
strcmp
(
platform_p
,
""
)
!=
0
)
strncpy
(
custom_platform
,
platform_p
,
sizeof
(
custom_platform
));
free
(
platform_p
);
break
;
}
default:
;
}
}
fprintf
(
file
,
"node %s %s %d %d %s %s
\n
"
,
nodename_ptr
,
os_str
,
*
bus_number_ptr
,
distr_options
,
bootnode_ptr
);
bootnode_ptr
,
custom_platform
);
/* Find the applications for this node */
class_vect
[
0
]
=
pwr_cClass_Distribute
;
class_vect
[
1
]
=
pwr_cClass_ApplDistribute
;
class_vect
[
3
]
=
0
;
class_vect
[
2
]
=
0
;
objcount
=
0
;
objlist
=
0
;
...
...
@@ -2276,7 +2325,167 @@ pwr_tStatus lfu_SaveDirectoryVolume(
system
(
"purge/nolog "
load_cNameDistribute
);
#endif
// Generate custom_build files
for
(
wb_object
buso
=
sp
->
object
();
buso
;
buso
=
buso
.
after
())
{
if
(
buso
.
cid
()
!=
pwr_cClass_BusConfig
)
continue
;
// Get all nodeconfig and friendnodes for this bus
for
(
wb_object
nodeo
=
buso
.
first
();
nodeo
;
nodeo
=
nodeo
.
after
())
{
if
(
nodeo
.
cid
()
!=
pwr_cClass_NodeConfig
)
continue
;
for
(
wb_object
customo
=
nodeo
.
first
();
customo
;
customo
=
customo
.
after
())
{
if
(
customo
.
cid
()
!=
pwr_cClass_CustomBuild
)
continue
;
pwr_tString80
nodename
;
pwr_tString80
cc
;
pwr_tString80
cxx
;
pwr_tString80
ar
;
pwr_tOpSysEnum
opsys
;
pwr_tString40
platform
;
pwr_tString40
release
;
FILE
*
fp
;
// Get NodeName
wb_attribute
a
=
sp
->
attribute
(
nodeo
.
oid
(),
"RtBody"
,
"NodeName"
);
if
(
!
a
)
return
a
.
sts
();
a
.
value
(
nodename
);
if
(
!
a
)
return
sts
;
// Get attribute cc
a
=
sp
->
attribute
(
customo
.
oid
(),
"DevBody"
,
"cc"
);
if
(
!
a
)
return
a
.
sts
();
a
.
value
(
cc
);
if
(
!
a
)
return
sts
;
// Get attribute cxx
a
=
sp
->
attribute
(
customo
.
oid
(),
"DevBody"
,
"cxx"
);
if
(
!
a
)
return
a
.
sts
();
a
.
value
(
cxx
);
if
(
!
a
)
return
sts
;
// Get attribute ar
a
=
sp
->
attribute
(
customo
.
oid
(),
"DevBody"
,
"ar"
);
if
(
!
a
)
return
a
.
sts
();
a
.
value
(
ar
);
if
(
!
a
)
return
sts
;
// Get attribute OperatingSystem
a
=
sp
->
attribute
(
customo
.
oid
(),
"DevBody"
,
"OperatingSystem"
);
if
(
!
a
)
return
a
.
sts
();
a
.
value
(
(
void
*
)
&
opsys
);
if
(
!
a
)
return
sts
;
// Get attribute Platform
a
=
sp
->
attribute
(
customo
.
oid
(),
"DevBody"
,
"Platform"
);
if
(
!
a
)
return
a
.
sts
();
a
.
value
(
platform
);
if
(
!
a
)
return
sts
;
// Get attribute Release
a
=
sp
->
attribute
(
customo
.
oid
(),
"DevBody"
,
"Release"
);
if
(
!
a
)
return
a
.
sts
();
a
.
value
(
release
);
if
(
!
a
)
return
sts
;
if
(
!
strcmp
(
nodename
,
""
))
{
char
msg
[
200
];
sprintf
(
msg
,
"Error in NodeConfig object '%s', NodeName is missing
\n
"
,
nodeo
.
longName
().
c_str
());
MsgWindow
::
message
(
'E'
,
msg
,
msgw_ePop_Default
);
syntax_error
=
1
;
}
if
(
!
(
(
strcmp
(
cc
,
""
)
!=
0
&&
strcmp
(
cxx
,
""
)
!=
0
&&
strcmp
(
ar
,
""
)
!=
0
)
||
(
strcmp
(
cc
,
""
)
==
0
&&
strcmp
(
cxx
,
""
)
==
0
&&
strcmp
(
ar
,
""
)
==
0
)))
{
char
msg
[
200
];
sprintf
(
msg
,
"Error in CustomBuild object '%s', all or none of cc, cxx and ar has to be supplied
\n
"
,
customo
.
longName
().
c_str
());
MsgWindow
::
message
(
'E'
,
msg
,
msgw_ePop_Default
);
syntax_error
=
1
;
}
// Print custom build file
if
(
!
(
opsys
==
pwr_mOpSys_PPC_LINUX
||
opsys
==
pwr_mOpSys_X86_LINUX
||
opsys
==
pwr_mOpSys_ARM_LINUX
))
continue
;
sprintf
(
fname
,
load_cNameCustomBuild
);
dcli_translate_filename
(
fname
,
fname
);
fp
=
fopen
(
fname
,
"w"
);
if
(
file
==
0
)
{
char
msg
[
200
];
sprintf
(
msg
,
"Error, Unable to open file %s"
,
fname
);
MsgWindow
::
message
(
'E'
,
msg
,
msgw_ePop_Default
);
return
LFU__NOFILE
;
}
fprintf
(
fp
,
"#!/bin/bash
\n\n
"
);
fprintf
(
fp
,
"let OpSys_PPC_LINUX=32
\n
"
);
fprintf
(
fp
,
"let OpSys_X86_LINUX=64
\n
"
);
fprintf
(
fp
,
"let OpSys_ARM_LINUX=256
\n\n
"
);
if
(
strcmp
(
release
,
""
)
!=
0
)
fprintf
(
fp
,
"source $pwra_db/pwra_env.sh set base %s
\n\n
"
,
release
);
if
(
strcmp
(
cc
,
""
)
!=
0
)
{
fprintf
(
fp
,
"export pwre_cc=%s
\n
"
,
cc
);
fprintf
(
fp
,
"export pwre_cxx=%s
\n
"
,
cxx
);
fprintf
(
fp
,
"export pwre_ar=%s
\n\n
"
,
ar
);
}
if
(
strcmp
(
platform
,
""
)
!=
0
)
{
fprintf
(
fp
,
"if [ ! -e $pwrp_root/bld/%s ]; then
\n
"
,
platform
);
fprintf
(
fp
,
" mkdir $pwrp_root/bld/%s
\n
"
,
platform
);
fprintf
(
fp
,
"fi
\n
"
);
fprintf
(
fp
,
"if [ ! -e $pwrp_root/bld/%s/obj ]; then
\n
"
,
platform
);
fprintf
(
fp
,
" mkdir $pwrp_root/bld/%s/obj
\n
"
,
platform
);
fprintf
(
fp
,
"fi
\n
"
);
fprintf
(
fp
,
"if [ ! -e $pwrp_root/bld/%s/lib ]; then
\n
"
,
platform
);
fprintf
(
fp
,
" mkdir $pwrp_root/bld/%s/lib
\n
"
,
platform
);
fprintf
(
fp
,
"fi
\n
"
);
fprintf
(
fp
,
"if [ ! -e $pwrp_root/bld/%s/lis ]; then
\n
"
,
platform
);
fprintf
(
fp
,
" mkdir $pwrp_root/bld/%s/lis
\n
"
,
platform
);
fprintf
(
fp
,
"fi
\n
"
);
fprintf
(
fp
,
"if [ ! -e $pwrp_root/bld/%s/exe ]; then
\n
"
,
platform
);
fprintf
(
fp
,
" mkdir $pwrp_root/bld/%s/exe
\n
"
,
platform
);
fprintf
(
fp
,
"fi
\n
"
);
fprintf
(
fp
,
"export pwrp_obj=$pwrp_root/bld/%s/obj
\n
"
,
platform
);
fprintf
(
fp
,
"export pwrp_lib=$pwrp_root/bld/%s/lib
\n
"
,
platform
);
fprintf
(
fp
,
"export pwrp_lis=$pwrp_root/bld/%s/lis
\n
"
,
platform
);
fprintf
(
fp
,
"export pwrp_exe=$pwrp_root/bld/%s/exe
\n\n
"
,
platform
);
}
switch
(
opsys
)
{
case
pwr_mOpSys_PPC_LINUX
:
fprintf
(
fp
,
"$pwrb_root/os_linux/hw_ppc/exp/exe/wb_gcg.sh
\"
$1
\"
\"
$2
\"
\"
$3
\"
\"
$OpSys_PPC_LINUX
\"
\"
$5
\"
\"
$6
\"
\"
$7
\"
\"
$8
\"\n
"
);
break
;
case
pwr_mOpSys_X86_LINUX
:
fprintf
(
fp
,
"$pwrb_root/os_linux/hw_x86/exp/exe/wb_gcg.sh
\"
$1
\"
\"
$2
\"
\"
$3
\"
\"
$OpSys_X86_LINUX
\"
\"
$5
\"
\"
$6
\"
\"
$7
\"
\"
$8
\"\n
"
);
break
;
case
pwr_mOpSys_ARM_LINUX
:
fprintf
(
fp
,
"$pwrb_root/os_linux/hw_arm/exp/exe/wb_gcg.sh
\"
$1
\"
\"
$2
\"
\"
$3
\"
\"
$OpSys_ARM_LINUX
\"
\"
$5
\"
\"
$6
\"
\"
$7
\"
\"
$8
\"\n
"
);
break
;
default:
;
}
fclose
(
fp
);
pwr_tCmd
cmd
;
sprintf
(
cmd
,
"chmod a+x %s
\n
"
,
fname
);
system
(
cmd
);
}
}
}
if
(
volumecount
>
0
)
free
(
(
char
*
)
volumelist
);
...
...
wb/lib/wb/src/wb_pkg.cpp
View file @
745a9609
...
...
@@ -62,7 +62,7 @@ void wb_pkg::readConfig()
{
char
fname
[
200
];
char
line
[
200
];
char
line_item
[
6
][
80
];
char
line_item
[
7
][
80
];
int
num
;
int
sts
;
...
...
@@ -85,8 +85,9 @@ void wb_pkg::readConfig()
int
bus
;
pwr_tMask
dstatus
;
char
bootnode
[
80
];
pwr_tString80
custom_platform
;
if
(
!
(
num
==
5
||
num
==
6
)
)
if
(
num
!=
7
)
throw
wb_error_str
(
"File corrupt "
load_cNameDistribute
);
sts
=
sscanf
(
line_item
[
2
],
"%d"
,
(
int
*
)
&
opsys
);
...
...
@@ -101,13 +102,11 @@ void wb_pkg::readConfig()
if
(
sts
!=
1
)
throw
wb_error_str
(
"File corrupt "
load_cNameDistribute
);
if
(
num
==
6
)
strcpy
(
bootnode
,
line_item
[
5
]);
else
strcpy
(
bootnode
,
"-"
);
strcpy
(
bootnode
,
line_item
[
5
]);
strcpy
(
custom_platform
,
line_item
[
6
]);
if
(
m_allnodes
)
{
pkg_node
node
(
line_item
[
1
],
opsys
,
bus
,
dstatus
,
bootnode
);
pkg_node
node
(
line_item
[
1
],
opsys
,
bus
,
dstatus
,
bootnode
,
custom_platform
);
m_nodelist
.
push_back
(
node
);
}
else
{
...
...
@@ -119,6 +118,7 @@ void wb_pkg::readConfig()
m_nodelist
[
i
].
setBus
(
bus
);
m_nodelist
[
i
].
setDStatus
(
dstatus
);
m_nodelist
[
i
].
setBootnode
(
bootnode
);
m_nodelist
[
i
].
setCustomPlatform
(
custom_platform
);
m_nodelist
[
i
].
setValid
();
break
;
}
...
...
@@ -179,9 +179,13 @@ void wb_pkg::readConfig()
if
(
plcname
[
0
]
!=
0
)
{
pwr_tFileName
dir
;
sprintf
(
dir
,
"$pwrp_root/bld/%s/exe/"
,
cdh_OpSysToStr
(
n
.
opsys
()));
if
(
n
.
opsys
()
==
pwr_mOpSys_CustomBuild
&&
strcmp
(
n
.
customPlatform
(),
"-"
)
!=
0
)
sprintf
(
dir
,
"$pwrp_root/bld/%s/exe/"
,
n
.
customPlatform
());
else
sprintf
(
dir
,
"$pwrp_root/bld/%s/exe/"
,
cdh_OpSysToStr
(
n
.
opsys
()));
sprintf
(
fname
,
"%s%s"
,
dir
,
plcname
);
sprintf
(
dir
,
"$pwrp_
root/%s/exe/"
,
cdh_OpSysToStr
(
n
.
opsys
())
);
sprintf
(
dir
,
"$pwrp_
exe/"
);
pkg_pattern
pplc
(
fname
,
dir
,
'W'
);
n
.
push_back
(
pplc
);
}
...
...
wb/lib/wb/src/wb_pkg.h
View file @
745a9609
...
...
@@ -116,6 +116,7 @@ class pkg_node {
int
m_errors
;
int
m_warnings
;
char
m_user
[
80
];
char
m_custom_platform
[
80
];
public:
pkg_node
(
char
*
name
)
:
m_opsys
(
pwr_mOpSys__
),
m_bus
(
0
),
...
...
@@ -124,9 +125,10 @@ class pkg_node {
strncpy
(
m_name
,
name
,
sizeof
(
m_name
));
strcpy
(
m_user
,
"pwrp"
);
strcpy
(
m_bootnode
,
"-"
);
strcpy
(
m_custom_platform
,
"-"
);
}
pkg_node
(
char
*
name
,
pwr_mOpSys
opsys
,
int
bus
,
pwr_tMask
dstatus
,
char
*
bootnode
)
:
pwr_tMask
dstatus
,
char
*
bootnode
,
char
*
custom_platform
)
:
m_opsys
(
opsys
),
m_bus
(
bus
),
m_dstatus
(
dstatus
),
m_valid
(
true
),
m_errors
(
0
),
m_warnings
(
0
)
{
...
...
@@ -141,12 +143,14 @@ class pkg_node {
strcpy
(
m_bootnode
,
bootnode
);
}
strncpy
(
m_name
,
name
,
sizeof
(
m_name
));
strncpy
(
m_custom_platform
,
custom_platform
,
sizeof
(
m_custom_platform
));
}
char
*
name
()
{
return
m_name
;}
pwr_mOpSys
opsys
()
{
return
m_opsys
;}
int
bus
()
{
return
m_bus
;}
pwr_tMask
dstatus
()
{
return
m_dstatus
;}
char
*
bootnode
()
{
return
m_bootnode
;}
char
*
customPlatform
()
{
return
m_custom_platform
;}
bool
valid
()
{
return
m_valid
;}
void
setOpsys
(
pwr_mOpSys
opsys
)
{
m_opsys
=
opsys
;}
void
setBus
(
int
bus
)
{
m_bus
=
bus
;}
...
...
@@ -163,6 +167,9 @@ class pkg_node {
strcpy
(
m_bootnode
,
bootnode
);
}
}
void
setCustomPlatform
(
char
*
custom_platform
)
{
strncpy
(
m_custom_platform
,
custom_platform
,
sizeof
(
m_custom_platform
));
}
void
setValid
()
{
m_valid
=
true
;}
void
push_back
(
pkg_pattern
&
pattern
)
{
pattern
.
node
(
this
);
...
...
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