Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
asn1-value-editor
Commits
ca562004
Commit
ca562004
authored
Jul 17, 2015
by
Maxime Perrotin
Browse files
Improve the support for VDM
parent
ea5b4744
Changes
3
Hide whitespace changes
Inline
Side-by-side
asn1_value_editor/sdlHandler.py
View file @
ca562004
...
...
@@ -33,6 +33,7 @@ from PySide.QtUiTools import QUiLoader
import
asn1_value_editor
from
standalone_editor
import
asn1sccToasn1ValueEditorTypes
import
vn
import
vdm_vn
import
resources
import
vdmHandler
...
...
@@ -639,26 +640,29 @@ class sdlHandler(QObject):
interface
[
'in'
].
append
((
spec
,
asn1_instance
))
else
:
interface
[
'out'
].
append
((
spec
,
as_bytes
,
asn1_instance
))
#
HERE:
make the function call
# make the function call
vdm_cls
=
getattr
(
procedure
,
"vdm_instance"
,
None
)
if
vdm_cls
:
# convert input parameters to VDM value notation
inp_as_vdm
=
[]
for
_
,
asn1_instance
in
interface
[
'in'
]:
inp_as_vdm
.
append
(
asn1_instance
.
GSER
())
for
spec
,
asn1_instance
in
interface
[
'in'
]:
as_pyside
=
vn
.
fromValueNotationToPySide
(
'var'
,
asn1_instance
.
GSER
())
as_vdm
=
vdm_vn
.
pyside_to_vdm
(
as_pyside
.
popitem
()[
1
],
spec
[
'type'
],
self
.
proc
.
dataview
)
inp_as_vdm
.
append
(
as_vdm
)
# Actual function call with input parameters in VDM format:
outp
=
self
.
vdm
.
call_function
(
vdm_cls
,
name
,
','
.
join
(
inp_as_vdm
))
print
"CALLED VDM. Result ="
,
outp
#
Use the pyside intermediate form to get the SWIG data
#
outp = outp.replace('[', '{').replace(']', '}')
spec
,
_
,
out_asn1_inst
=
interface
[
'out'
][
0
]
# assuming 1 return parameter
vn
.
valueNotationToSwig
(
gser
=
outp
,
dest
=
out_asn1_inst
,
sort
=
spec
[
'type'
],
ASN1_AST
=
self
.
proc
.
dataview
,
ASN1Swig
=
ASN1
)
#spec_in, asn1_inst_in = interface['in'][0]
#spec_out, as_bytes, asn1_inst_out = interface['out'][0]
#asn1_inst_out.Set(asn1_inst_in.Get() + 1)
# assuming 1 return parameter
vdm_vn
.
vdm_to_swig
(
vdm
=
outp
,
dest
=
out_asn1_inst
,
sort
=
spec
[
'type'
],
ASN1_AST
=
self
.
proc
.
dataview
,
ASN1Swig
=
ASN1
)
# Copy the OUT parameters back from SWIG to ctypes
for
spec
,
as_bytes
,
asn1_instance
in
interface
[
'out'
]:
# Create new SWIG byte array
...
...
asn1_value_editor/vdmHandler.py
View file @
ca562004
...
...
@@ -35,7 +35,6 @@ from functools import partial
from
itertools
import
chain
from
standalone_editor
import
asn1sccToasn1ValueEditorTypes
import
vn
try
:
import
dataview_uniq_asn
as
ASN1
...
...
asn1_value_editor/vdm_vn.py
View file @
ca562004
...
...
@@ -13,10 +13,10 @@
Set of: { a, b. c }
Sequence of: [a, b, c]
Enum: <value>
Choice:
?
Choice:
direct value, no reference to the selected field
Bit string literal : ?
Octet string literal : ?
String Literal :
?
String Literal :
"abc"
Copyright (c) 2012-2015 European Space Agency
...
...
@@ -97,9 +97,9 @@ SETOF << LBRACKET + Optional(delimitedList(value)) + RBRACKET
ENUM
<<
LT
+
ID
+
GT
# Parse actions allow to transform the AST on the fly
SEQUENCE
.
setParseAction
(
lambda
s
,
l
,
t
:
[
t
.
asList
()
]
)
SEQUENCE
.
setParseAction
(
lambda
s
,
l
,
t
:
{
'Seq'
:
t
.
asList
()
}
)
SEQOF
.
setParseAction
(
lambda
s
,
l
,
t
:
[
t
.
asList
()])
SETOF
.
setParseAction
(
lambda
s
,
l
,
t
:
[
t
.
asList
()]
)
SETOF
.
setParseAction
(
lambda
s
,
l
,
t
:
set
(
t
)
)
ENUM
.
setParseAction
(
lambda
s
,
l
,
t
:
{
'Enum'
:
t
[
0
].
replace
(
'-'
,
'_'
)})
FloatingPointLiteral
.
setParseAction
(
lambda
s
,
l
,
t
:
float
(
t
[
0
]))
INT
.
setParseAction
(
lambda
s
,
l
,
t
:
int
(
t
[
0
]))
...
...
@@ -119,18 +119,27 @@ def pyside_to_vdm(val, sort=None, ASN1_AST=None):
''' Create a VDM reprentation of the Python variable '''
if
isinstance
(
val
,
dict
):
if
'Choice'
in
val
:
result
=
pyside_to_vdm
(
val
[
val
[
'Choice'
]])
choice
=
val
[
'Choice'
].
replace
(
'_'
,
'-'
)
type_ref
=
ASN1_AST
[
sort
.
ReferencedTypeName
].
type
child_sort
=
type_ref
.
Children
[
choice
].
type
result
=
pyside_to_vdm
(
val
[
val
[
'Choice'
]],
child_sort
,
ASN1_AST
)
elif
'Enum'
in
val
:
result
=
'<{}>'
.
format
(
unicode
(
val
[
'Enum'
]).
strip
())
else
:
# SEQUENCE
# We need the typename XXX
values
=
(
pyside_to_vdm
(
field
)
for
_
,
field
in
val
.
viewitems
())
result
=
'mk_TypeName({})'
.
format
(
', '
.
join
(
values
))
elif
isinstance
(
val
,
list
):
# SEQUENCE OF or SET OF
# We need to know the type (SEQOF and SETOF are different in VDM)
values
=
(
pyside_to_vdm
(
item
)
for
item
in
val
)
result
=
'[{}]'
.
format
(
', '
.
join
(
values
))
# SEQ OF
#result = '{{{}}'.format(', '.join(values)) # SET OF
typename
=
sort
.
ReferencedTypeName
.
replace
(
'-'
,
'_'
)
type_ref
=
ASN1_AST
[
sort
.
ReferencedTypeName
].
type
values
=
(
pyside_to_vdm
(
field
,
type_ref
.
Children
[
field
.
replace
(
'_'
,
'-'
)],
ASN1_AST
)
for
_
,
field
in
val
.
viewitems
())
result
=
'mk_{}({})'
.
format
(
typename
,
', '
.
join
(
values
))
elif
isinstance
(
val
,
list
):
# Check if it is a SEQOF or SETOF
# Warning: ASN.1 backend python.stg only supports SequenceOf
type_ref
=
ASN1_AST
[
sort
.
ReferencedTypeName
].
type
child_sort
=
type_ref
.
type
values
=
(
pyside_to_vdm
(
item
,
child_sort
,
ASN1_AST
)
for
item
in
val
)
pattern
=
'[{}]'
if
type_ref
.
kind
==
'SequenceOfType'
else
'{{{}}}'
result
=
pattern
.
format
(
', '
.
join
(
values
))
elif
isinstance
(
val
,
bool
):
# boolean are in lower case in VDM
result
=
str
(
val
).
lower
()
...
...
@@ -145,22 +154,35 @@ def pyside_to_vdm(val, sort=None, ASN1_AST=None):
return
result
def
vdm_to_swig
(
gser
,
dest
,
sort
,
ASN1Swig
,
ASN1_AST
,
var
=
None
):
def
vdm_to_swig
(
vdm
,
dest
,
sort
,
ASN1Swig
,
ASN1_AST
,
var
=
None
):
''' Parse a VDM value and fill a SWIG variable with it
Inputs:
gser
: input
GSER
string
vdm
: input string
in VDM value notation
dest : output SWIG instance to be filled
ASN1Swig : python module containing SWIG DV access
sort: ASN1 typename, with dashes, no underscores
ASN1_AST : AST generated by ASN1SCC
var : optional already pyside-converted
GSER
string
var : optional already pyside-converted
input
string
Outputs:
none - "dest" is modified by this function
'''
var
=
var
or
value
.
parseString
(
gser
,
True
)[
0
]
# Parse the VDM string and transform it to a python value
var
=
var
or
value
.
parseString
(
vdm
,
True
)[
0
]
def
find_basic_type
(
a_type
):
''' Return the ASN.1 basic type of a_type '''
basic_type
=
a_type
while
basic_type
.
kind
==
'ReferenceType'
:
# Find type with proper case in the data view
for
typename
in
ASN1_AST
.
viewkeys
():
if
typename
.
lower
()
==
basic_type
.
ReferencedTypeName
.
lower
():
basic_type
=
TYPES
[
typename
].
type
break
return
basic_type
def
reach
(
field
,
orig
,
idx
=
True
):
''' Helper: move swig pointer to the next field, and optionaly
index (if idx=True)
index (if idx=True)
Inputs: field is a string with optional index (e.g. "a[0]")
orig is the swig pointer
idx: set to true if you want the index to be reached
...
...
@@ -174,8 +196,8 @@ def vdm_to_swig(gser, dest, sort, ASN1Swig, ASN1_AST, var=None):
''' Recursively fill up the value '''
if
sort
.
kind
==
'ReferenceType'
:
sort
=
ASN1_AST
[
sort
.
ReferencedTypeName
]
if
isinstance
(
inp
,
list
):
# SEQUENCE OF
kind
=
sort
.
type
.
kind
if
kind
in
(
'SequenceOfType'
,
'SetOfType'
):
# get the path to the sequence of
_
,
params
,
path
=
outp
.
GetState
()
if
path
:
...
...
@@ -192,43 +214,83 @@ def vdm_to_swig(gser, dest, sort, ASN1Swig, ASN1_AST, var=None):
reach
(
each
,
outp
)
# The ASN1SCC AST only knows if the list has a fixed length
outp
.
SetLength
(
len
(
inp
))
elif
isinstance
(
inp
,
(
int
,
float
,
bool
)
):
elif
kind
in
(
'IntegerType'
,
'RealType'
,
'BooleanType'
):
outp
.
Set
(
inp
)
elif
isinstance
(
inp
,
dict
):
if
'Enum'
in
inp
:
# Get proper enum id from the ASN1SCC AST
enum_id
=
sort
.
type
.
EnumValues
[
inp
[
'Enum'
].
replace
(
'_'
,
'-'
)].
EnumID
val
=
getattr
(
ASN1Swig
.
DV
,
enum_id
)
outp
.
Set
(
val
)
elif
'Choice'
in
inp
:
child_name
=
inp
[
'Choice'
]
ch_ty
=
sort
.
type
.
Children
[
child_name
.
replace
(
'_'
,
'-'
)]
enum_val
=
getattr
(
ASN1Swig
.
DV
,
ch_ty
.
EnumID
)
outp
.
kind
.
Set
(
enum_val
)
rec
(
inp
[
child_name
],
getattr
(
outp
,
child_name
.
replace
(
'-'
,
'_'
)),
ch_ty
.
type
)
else
:
# SEQUENCE
# get the path to the sequence
_
,
params
,
path
=
outp
.
GetState
()
if
path
:
path
=
path
.
strip
(
'.'
).
split
(
'.'
)
for
field
,
data
in
inp
.
viewitems
():
outp
.
Reset
()
for
each
in
path
:
# Reach the path, including indexes
reach
(
each
,
outp
)
# Then get the field itself
reach
(
field
.
replace
(
'-'
,
'_'
),
outp
)
field_ty
=
sort
.
type
.
Children
[
field
.
replace
(
'_'
,
'-'
)]
rec
(
data
,
outp
,
field_ty
.
type
)
# move back to original path
elif
kind
==
'EnumeratedType'
:
# Get proper enum id from the ASN1SCC AST
enum_id
=
sort
.
type
.
EnumValues
[
inp
[
'Enum'
].
replace
(
'_'
,
'-'
)].
EnumID
val
=
getattr
(
ASN1Swig
.
DV
,
enum_id
)
outp
.
Set
(
val
)
elif
kind
==
'ChoiceType'
:
# choice : determinant is not set in the vdm string input
# it must be inferred based on the type
map_kind_type
=
{
'BooleanType'
:
bool
,
'IntegerType'
:
int
,
'RealType'
:
float
,
'SequenceType'
:
dict
(
Seq
=
[]),
'EnumeratedType'
:
dict
(
Enum
=
[]),
'SequenceOfType'
:
list
,
'SetOfType'
:
set
}
map_name_sort
=
{}
for
child_name
,
child_sort
in
sort
.
type
.
Children
.
viewitems
():
# find out the basic kind of each child (BooleanType, ...)
basic_kind
=
find_basic_type
(
each
.
type
).
kind
# and map it to a python basic type (except for choices)
if
basic_kind
!=
'ChoiceType'
:
pytype
=
map_kind_type
[
basic_kind
]
else
:
pytype
=
'choice_{}'
.
format
(
child_name
)
if
pytype
in
map_sort_name
:
raise
RuntimeError
(
'VDM does not support CHOICEs with '
'more than one option of a given type'
)
map_name_sort
[
pytype
]
=
child_name
# to be completed. CHOICEs are complicated because vdm does not
# give the name of the choice made
# so if you have a union like this: nat | T1 | T2
# there are two cases: either T1 and T2 are basic types
# (but different from nat) - there is no ambiguity, because from
# the notation we can directly discrimitate the union
# but if T1 and T2 are union types we need to recursively analyse
# them to figure out which path to take to encode the ASN.1 value
# Assuming the ASN.1 type CHOICE { a INTEGER, b CHOICE {...},
# c CHOICE {...} } The code above creates a mapping:
# { int: "a", "choice_b": "b", "choice_c": "c" }
# so if the VDM variable is an int -> no problem, we get field a
# but if it is not an int.. We must search in "b" and "c" choice
# types for a path that leads to a basic type corresponding to the
# VDM value. Todo...
# child_name = inp['Choice']
# ch_ty = sort.type.Children[child_name.replace('_', '-')]
# enum_val = getattr(ASN1Swig.DV, ch_ty.EnumID)
# outp.kind.Set(enum_val)
# rec(inp[child_name],
# getattr(outp,
# child_name.replace('-', '_')),
# ch_ty.type)
elif
kind
==
'SequenceType'
:
# get the path to the sequence
_
,
params
,
path
=
outp
.
GetState
()
if
path
:
path
=
path
.
strip
(
'.'
).
split
(
'.'
)
for
field
,
data
in
zip
(
sort
.
type
.
Children
.
viewkeys
(),
inp
[
'Seq'
]):
# Yikes! Ordering of fiels in the Sequence is not guaranteed
# in a normal dict....
outp
.
Reset
()
if
len
(
path
):
reach
(
path
[
0
],
outp
)
for
each
in
path
:
# Reach the path, including indexes
reach
(
each
,
outp
)
# Then get the field itself
reach
(
field
.
replace
(
'-'
,
'_'
),
outp
)
field_ty
=
sort
.
type
.
Children
[
field
.
replace
(
'_'
,
'-'
)]
rec
(
data
,
outp
,
field_ty
.
type
)
# move back to original path
outp
.
Reset
()
if
len
(
path
):
reach
(
path
[
0
],
outp
)
else
:
# Unsupported type
pass
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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