Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
OpenGEODE
Commits
b3055210
Commit
b3055210
authored
Oct 02, 2014
by
Maxime Perrotin
Browse files
Proper range check when using OCTET STRINGs/SEQUENCE OF
parent
ef5cbe44
Changes
9
Hide whitespace changes
Inline
Side-by-side
AdaGenerator.py
View file @
b3055210
...
@@ -125,6 +125,9 @@ def _process(process):
...
@@ -125,6 +125,9 @@ def _process(process):
# Expression must be a ground expression, i.e. must not
# Expression must be a ground expression, i.e. must not
# require temporary variable to store computed result
# require temporary variable to store computed result
dst
,
dstr
,
dlocal
=
expression
(
def_value
)
dst
,
dstr
,
dlocal
=
expression
(
def_value
)
varbty
=
find_basic_type
(
var_type
)
if
varbty
.
kind
in
(
'SequenceOfType'
,
'OctetStringType'
):
dstr
=
array_content
(
def_value
,
dstr
,
varbty
)
assert
not
dst
and
not
dlocal
,
'DCL: Expecting a ground expression'
assert
not
dst
and
not
dlocal
,
'DCL: Expecting a ground expression'
process_level_decl
.
append
(
process_level_decl
.
append
(
u
'l_{n} : aliased asn1Scc{t}{default};'
.
format
(
u
'l_{n} : aliased asn1Scc{t}{default};'
.
format
(
...
@@ -152,9 +155,6 @@ def _process(process):
...
@@ -152,9 +155,6 @@ def _process(process):
# Add the declaration of the runTransition procedure
# Add the declaration of the runTransition procedure
process_level_decl
.
append
(
'procedure runTransition(Id: Integer);'
)
process_level_decl
.
append
(
'procedure runTransition(Id: Integer);'
)
#process_level_decl.append('procedure state_start;')
#process_level_decl.append('pragma export(C, start, "{}_start");'
# .format(process_name))
# Generate the code of the start transition:
# Generate the code of the start transition:
start_transition
=
[
'begin'
,
start_transition
=
[
'begin'
,
...
@@ -419,31 +419,43 @@ def write_statement(param, newline):
...
@@ -419,31 +419,43 @@ def write_statement(param, newline):
local
=
[]
local
=
[]
basic_type
=
find_basic_type
(
param
.
exprType
)
or
{}
basic_type
=
find_basic_type
(
param
.
exprType
)
or
{}
type_kind
=
basic_type
.
kind
type_kind
=
basic_type
.
kind
if
type_kind
.
endswith
(
'StringType'
):
if
isinstance
(
param
,
ogAST
.
ExprAppend
):
# Append: call Put_Line separately for each side of the expression
st1
,
_
,
lcl1
=
write_statement
(
param
.
left
,
newline
=
False
)
st2
,
_
,
lcl2
=
write_statement
(
param
.
right
,
newline
=
False
)
code
.
extend
(
st1
)
code
.
extend
(
st2
)
local
.
extend
(
lcl1
)
local
.
extend
(
lcl2
)
elif
type_kind
.
endswith
(
'StringType'
):
if
isinstance
(
param
,
ogAST
.
PrimStringLiteral
):
if
isinstance
(
param
,
ogAST
.
PrimStringLiteral
):
# Raw string
# Raw string
string
=
'"'
+
param
.
value
[
1
:
-
1
].
replace
(
'"'
,
"'"
)
+
'"'
code
.
append
(
u
'Put("{}");'
.
format
(
param
.
value
[
1
:
-
1
].
replace
(
'"'
,
"'"
)))
else
:
else
:
code
,
string
,
local
=
expression
(
param
)
code
,
string
,
local
=
expression
(
param
)
if
type_kind
==
'OctetStringType'
:
if
type_kind
==
'OctetStringType'
:
# Octet string -> convert to Ada string
# Octet string -> convert to Ada string
sep
=
u
'
\u00dc
'
sep
=
u
'
\u00dc
'
localstr
=
u
'tmp{}{}str'
.
format
(
str
(
param
.
tmpVar
),
sep
)
last_it
=
u
""
local
.
append
(
u
'{} : String(1 .. {});'
.
format
(
localstr
,
basic_type
.
Max
))
if
isinstance
(
param
,
ogAST
.
PrimSubstring
):
if
isinstance
(
param
,
ogAST
.
PrimSubstring
):
range_str
=
u
"{}'Range"
.
format
(
string
)
range_str
=
u
"{}'Range"
.
format
(
string
)
iterator
=
u
"i - {}'First + 1"
.
format
(
string
)
elif
basic_type
.
Min
==
basic_type
.
Max
:
elif
basic_type
.
Min
==
basic_type
.
Max
:
range_str
=
u
"{}.Data'Range"
.
format
(
string
)
range_str
=
u
"{}.Data'Range"
.
format
(
string
)
string
+=
u
".Data"
string
+=
u
".Data"
iterator
=
u
"i"
else
:
else
:
range_str
=
u
"1 .. {}.Length"
.
format
(
string
)
range_str
=
u
"1 .. {}.Length"
.
format
(
string
)
string
+=
u
".Data"
string
+=
u
".Data"
iterator
=
u
"i"
last_it
=
u
"({})"
.
format
(
range_str
)
code
.
extend
([
u
"for i in {} loop"
.
format
(
range_str
),
code
.
extend
([
u
"for i in {} loop"
.
format
(
range_str
),
u
"
{tmp}(i) :=
Character'Val({st}(i));"
u
"
Put(
Character'Val({st}(i))
)
;"
.
format
(
tmp
=
localstr
,
st
=
string
,
sep
=
sep
),
.
format
(
st
=
string
,
sep
=
sep
,
it
=
iterator
),
u
"end loop;"
])
u
"end loop;"
])
string
=
u
'{}({})'
.
format
(
localstr
,
range_str
)
else
:
code
.
append
(
"Put({});"
.
format
(
string
))
elif
type_kind
in
(
'IntegerType'
,
'RealType'
,
elif
type_kind
in
(
'IntegerType'
,
'RealType'
,
'BooleanType'
,
'Integer32Type'
):
'BooleanType'
,
'Integer32Type'
):
code
,
string
,
local
=
expression
(
param
)
code
,
string
,
local
=
expression
(
param
)
...
@@ -453,15 +465,14 @@ def write_statement(param, newline):
...
@@ -453,15 +465,14 @@ def write_statement(param, newline):
cast
=
'Long_Float'
cast
=
'Long_Float'
elif
type_kind
==
'BooleanType'
:
elif
type_kind
==
'BooleanType'
:
cast
=
'Boolean'
cast
=
'Boolean'
string
=
u
"
{cast}'Image({s})"
.
format
(
cast
=
cast
,
s
=
string
)
code
.
append
(
u
"Put(
{cast}'Image({s})
);
"
.
format
(
cast
=
cast
,
s
=
string
)
)
else
:
else
:
error
=
(
u
'Unsupported parameter in write call '
+
error
=
(
u
'Unsupported parameter in write call '
+
param
.
inputString
)
param
.
inputString
)
LOG
.
error
(
error
)
LOG
.
error
(
error
)
raise
TypeError
(
error
)
raise
TypeError
(
error
)
code
.
append
(
u
'Put{line}({string});'
.
format
(
if
newline
:
line
=
u
'_Line'
if
newline
else
u
''
,
code
.
append
(
u
"New_Line;"
)
string
=
string
))
return
code
,
string
,
local
return
code
,
string
,
local
...
@@ -551,11 +562,16 @@ def _call_external_function(output):
...
@@ -551,11 +562,16 @@ def _call_external_function(output):
# Create a temporary variable for input parameters only
# Create a temporary variable for input parameters only
# (If needed, i.e. if argument is not a local variable)
# (If needed, i.e. if argument is not a local variable)
if
param_direction
==
'in'
\
if
param_direction
==
'in'
\
and
(
not
(
isinstance
(
param
,
ogAST
.
PrimVariable
)
and
and
(
not
(
isinstance
(
param
,
ogAST
.
PrimVariable
)
p_id
.
startswith
(
'l_'
))
or
isinstance
(
param
,
ogAST
.
PrimFPAR
)):
and
p_id
.
startswith
(
'l_'
))
or
isinstance
(
param
,
ogAST
.
PrimFPAR
)):
tmp_id
=
out
[
'tmpVars'
][
idx
]
tmp_id
=
out
[
'tmpVars'
][
idx
]
local_decl
.
append
(
'tmp{idx} : aliased asn1Scc{oType};'
local_decl
.
append
(
'tmp{idx} : aliased asn1Scc{oType};'
.
format
(
idx
=
tmp_id
,
oType
=
typename
))
.
format
(
idx
=
tmp_id
,
oType
=
typename
))
if
isinstance
(
param
,
(
ogAST
.
PrimSequenceOf
,
ogAST
.
PrimStringLiteral
)):
p_id
=
array_content
(
param
,
p_id
,
find_basic_type
(
param_type
))
code
.
append
(
'tmp{idx} := {p_id};'
code
.
append
(
'tmp{idx} := {p_id};'
.
format
(
idx
=
tmp_id
,
p_id
=
p_id
))
.
format
(
idx
=
tmp_id
,
p_id
=
p_id
))
list_of_params
.
append
(
"tmp{idx}'access"
list_of_params
.
append
(
"tmp{idx}'access"
...
@@ -597,7 +613,6 @@ def _task_assign(task):
...
@@ -597,7 +613,6 @@ def _task_assign(task):
# ExprAssign only returns code statements, no string
# ExprAssign only returns code statements, no string
code_assign
,
_
,
decl_assign
=
expression
(
expr
)
code_assign
,
_
,
decl_assign
=
expression
(
expr
)
code
.
extend
(
code_assign
)
code
.
extend
(
code_assign
)
# code.append(ada_string[1:-1] + ';')
local_decl
.
extend
(
decl_assign
)
local_decl
.
extend
(
decl_assign
)
return
code
,
local_decl
return
code
,
local_decl
...
@@ -790,7 +805,6 @@ def _prim_call(prim):
...
@@ -790,7 +805,6 @@ def _prim_call(prim):
elif
ident
==
'num'
:
elif
ident
==
'num'
:
# User wants to get an enumerated corresponding integer value
# User wants to get an enumerated corresponding integer value
exp
=
params
[
0
]
exp
=
params
[
0
]
#exp_type = find_basic_type(exp.exprType)
# Get the ASN.1 type name as it is needed to build the Ada expression
# Get the ASN.1 type name as it is needed to build the Ada expression
exp_typename
=
\
exp_typename
=
\
(
getattr
(
exp
.
exprType
,
'ReferencedTypeName'
,
None
)
(
getattr
(
exp
.
exprType
,
'ReferencedTypeName'
,
None
)
...
@@ -956,8 +970,10 @@ def _prim_selector(prim):
...
@@ -956,8 +970,10 @@ def _prim_selector(prim):
receiver_ty_name
=
receiver
.
exprType
.
ReferencedTypeName
.
replace
(
'-'
,
'_'
)
receiver_ty_name
=
receiver
.
exprType
.
ReferencedTypeName
.
replace
(
'-'
,
'_'
)
if
receiver_bty
.
kind
==
'ChoiceType'
:
if
receiver_bty
.
kind
==
'ChoiceType'
:
ada_string
=
(
'asn1Scc{typename}_{field_name}_get({ada_string})'
.
format
(
ada_string
=
(
'asn1Scc{typename}_{field_name}_get({ada_string})'
typename
=
receiver_ty_name
,
field_name
=
field_name
,
ada_string
=
ada_string
))
.
format
(
typename
=
receiver_ty_name
,
field_name
=
field_name
,
ada_string
=
ada_string
))
else
:
else
:
ada_string
+=
'.'
+
field_name
ada_string
+=
'.'
+
field_name
...
@@ -995,22 +1011,27 @@ def _equality(expr):
...
@@ -995,22 +1011,27 @@ def _equality(expr):
right_stmts
,
right_str
,
right_local
=
expression
(
expr
.
right
)
right_stmts
,
right_str
,
right_local
=
expression
(
expr
.
right
)
code
.
extend
(
right_stmts
)
code
.
extend
(
right_stmts
)
local_decl
.
extend
(
right_local
)
local_decl
.
extend
(
right_local
)
a
ctual
_type
=
getattr
(
expr
.
left
.
exprType
,
a
sn1
_type
=
getattr
(
expr
.
left
.
exprType
,
'ReferencedTypeName'
,
'ReferencedTypeName'
,
None
)
or
expr
.
left
.
exprType
.
kind
None
)
or
expr
.
left
.
exprType
.
kind
actual_type
=
actual_type
.
replace
(
'-'
,
'_'
)
actual_type
=
asn1_type
.
replace
(
'-'
,
'_'
)
basic
=
find_basic_type
(
expr
.
left
.
exprType
).
kind
in
(
'IntegerType'
,
lbty
=
find_basic_type
(
expr
.
left
.
exprType
)
'Integer32Type'
,
basic
=
lbty
.
kind
in
(
'IntegerType'
,
'Integer32Type'
,
'BooleanType'
,
'BooleanType'
,
'RealType'
,
'EnumeratedType'
,
'ChoiceEnumeratedType'
)
'RealType'
,
'EnumeratedType'
,
'ChoiceEnumeratedType'
)
if
basic
:
if
basic
:
ada_string
=
u
'({left} {op} {right})'
.
format
(
ada_string
=
u
'({left} {op} {right})'
.
format
(
left
=
left_str
,
op
=
expr
.
operand
,
right
=
right_str
)
left
=
left_str
,
op
=
expr
.
operand
,
right
=
right_str
)
else
:
else
:
ada_string
=
u
'asn1Scc{asn1}_Equal({left}, {right})'
.
format
(
if
asn1_type
in
TYPES
:
asn1
=
actual_type
,
left
=
left_str
,
right
=
right_str
)
if
isinstance
(
expr
.
right
,
(
ogAST
.
PrimSequenceOf
,
ogAST
.
PrimStringLiteral
)):
right_str
=
array_content
(
expr
.
right
,
right_str
,
lbty
)
ada_string
=
u
'asn1Scc{asn1}_Equal({left}, {right})'
.
format
(
asn1
=
actual_type
,
left
=
left_str
,
right
=
right_str
)
else
:
# Raw types on both left and right.... use simple operator
ada_string
=
u
"({left}) {op} ({right})"
.
format
(
left
=
left_str
,
op
=
expr
.
operand
,
right
=
right_str
)
if
isinstance
(
expr
,
ogAST
.
ExprNeq
):
if
isinstance
(
expr
,
ogAST
.
ExprNeq
):
ada_string
=
u
'not {}'
.
format
(
ada_string
)
ada_string
=
u
'not {}'
.
format
(
ada_string
)
return
code
,
unicode
(
ada_string
),
local_decl
return
code
,
unicode
(
ada_string
),
local_decl
...
@@ -1026,13 +1047,33 @@ def _assign_expression(expr):
...
@@ -1026,13 +1047,33 @@ def _assign_expression(expr):
# If left side is a string/seqOf and right side is a substring, we must
# If left side is a string/seqOf and right side is a substring, we must
# assign the .Data and .Length parts properly
# assign the .Data and .Length parts properly
basic_left
=
find_basic_type
(
expr
.
left
.
exprType
)
basic_left
=
find_basic_type
(
expr
.
left
.
exprType
)
if
basic_left
.
kind
in
(
'SequenceOfType'
,
'OctetStringType'
)
\
if
basic_left
.
kind
in
(
'SequenceOfType'
,
'OctetStringType'
):
and
isinstance
(
expr
.
right
,
ogAST
.
PrimSubstring
):
rlen
=
"{}'Length"
.
format
(
right_str
)
strings
.
append
(
u
"{lvar}.Data(1..{rvar}'Length) := {rvar};"
if
isinstance
(
expr
.
right
,
ogAST
.
PrimSubstring
):
strings
.
append
(
u
"{lvar}.Data(1..{rvar}'Length) := {rvar};"
.
format
(
lvar
=
left_str
,
rvar
=
right_str
))
.
format
(
lvar
=
left_str
,
rvar
=
right_str
))
if
basic_left
.
Min
!=
basic_left
.
Max
:
elif
isinstance
(
expr
.
right
,
ogAST
.
ExprAppend
):
strings
.
append
(
u
"{lvar}.Length := {rvar}'Length;"
basic_right
=
find_basic_type
(
expr
.
right
.
exprType
)
.
format
(
lvar
=
left_str
,
rvar
=
right_str
))
rlen
=
append_size
(
expr
.
right
)
strings
.
append
(
u
"{lvar}.Data(1..{lstr}) := {rvar};"
.
format
(
lvar
=
left_str
,
rvar
=
right_str
,
lstr
=
rlen
))
elif
isinstance
(
expr
.
right
,
(
ogAST
.
PrimSequenceOf
,
ogAST
.
PrimStringLiteral
)):
strings
.
append
(
u
"{lvar} := {value};"
.
format
(
lvar
=
left_str
,
value
=
array_content
(
expr
.
right
,
right_str
,
basic_left
)))
rlen
=
None
else
:
# Right part is a variable
strings
.
append
(
u
"{} := {};"
.
format
(
left_str
,
right_str
))
rlen
=
None
if
rlen
and
basic_left
.
Min
!=
basic_left
.
Max
:
strings
.
append
(
u
"{lvar}.Length := {rlen};"
.
format
(
lvar
=
left_str
,
rlen
=
rlen
))
else
:
else
:
strings
.
append
(
u
"{} := {};"
.
format
(
left_str
,
right_str
))
strings
.
append
(
u
"{} := {};"
.
format
(
left_str
,
right_str
))
code
.
extend
(
left_stmts
)
code
.
extend
(
left_stmts
)
...
@@ -1134,60 +1175,16 @@ def _append(expr):
...
@@ -1134,60 +1175,16 @@ def _append(expr):
stmts
.
extend
(
right_stmts
)
stmts
.
extend
(
right_stmts
)
local_decl
.
extend
(
left_local
)
local_decl
.
extend
(
left_local
)
local_decl
.
extend
(
right_local
)
local_decl
.
extend
(
right_local
)
# Declare a temporary variable to hold the result of the append
ada_string
=
'tmp{}'
.
format
(
expr
.
tmpVar
)
left
=
'{}{}'
.
format
(
left_str
,
string_payload
(
expr
.
left
,
left_str
)
if
local_decl
.
append
(
'{tmp} : aliased asn1Scc{eType};'
.
format
(
isinstance
(
expr
.
left
,
(
ogAST
.
PrimVariable
,
tmp
=
ada_string
,
ogAST
.
PrimConstant
))
else
''
)
eType
=
expr
.
exprType
.
ReferencedTypeName
right
=
'{}{}'
.
format
(
right_str
,
string_payload
(
expr
.
right
,
right_str
)
if
.
replace
(
'-'
,
'_'
)))
isinstance
(
expr
.
right
,
(
ogAST
.
PrimVariable
,
ogAST
.
PrimConstant
))
else
''
)
# If right or left is raw, declare a temporary variable for it, too
for
sexp
,
sid
in
zip
((
expr
.
right
,
expr
.
left
),
(
right_str
,
left_str
)):
ada_string
=
'(({}) & ({}))'
.
format
(
left
,
right
)
if
sexp
.
is_raw
:
local_decl
.
append
(
u
'tmp{idx} : aliased asn1Scc{eType};'
.
format
(
idx
=
sexp
.
tmpVar
,
eType
=
sexp
.
exprType
.
ReferencedTypeName
.
replace
(
'-'
,
'_'
)))
stmts
.
append
(
u
'tmp{idx} := {s_id};'
.
format
(
idx
=
sexp
.
tmpVar
,
s_id
=
sid
))
sexp
.
sid
=
u
'tmp'
+
unicode
(
sexp
.
tmpVar
)
# Length of raw string - update for sequence of
if
isinstance
(
sexp
,
ogAST
.
PrimStringLiteral
):
sexp
.
slen
=
unicode
(
len
(
sexp
.
value
[
1
:
-
1
]))
elif
isinstance
(
sexp
,
ogAST
.
PrimEmptyString
):
sexp
.
slen
=
u
'0'
elif
isinstance
(
sexp
,
ogAST
.
PrimSequenceOf
):
sexp
.
slen
=
unicode
(
len
(
sexp
.
value
))
else
:
raise
TypeError
(
'Not a string/Sequence in APPEND'
)
else
:
sexp
.
sid
=
sid
basic
=
find_basic_type
(
sexp
.
exprType
)
if
basic
.
Min
==
basic
.
Max
:
# Fixed-size string
sexp
.
slen
=
unicode
(
basic
.
Max
)
else
:
# Variable-size types have a Length field
if
isinstance
(
sexp
,
ogAST
.
PrimSubstring
):
sexp
.
slen
=
u
"{}'Length"
.
format
(
sexp
.
sid
)
else
:
sexp
.
slen
=
u
'{}.Length'
.
format
(
sexp
.
sid
)
left_payload
=
expr
.
left
.
sid
+
string_payload
(
expr
.
left
,
expr
.
left
.
sid
)
right_payload
=
expr
.
right
.
sid
+
string_payload
(
expr
.
right
,
expr
.
right
.
sid
)
if
unicode
.
isnumeric
(
expr
.
left
.
slen
)
\
and
unicode
.
isnumeric
(
expr
.
right
.
slen
):
length
=
unicode
(
int
(
expr
.
left
.
slen
)
+
int
(
expr
.
right
.
slen
))
else
:
length
=
u
'{} + {}'
.
format
(
expr
.
left
.
slen
,
expr
.
right
.
slen
)
stmts
.
append
(
u
'{res}.Data(1 .. {length}) := {lid} & {rid};'
.
format
(
length
=
length
,
res
=
ada_string
,
lid
=
left_payload
,
rid
=
right_payload
))
basic_tmp
=
find_basic_type
(
expr
.
exprType
)
if
basic_tmp
.
Min
!=
basic_tmp
.
Max
:
# Update lenght field of resulting variable (if variable size)
stmts
.
append
(
u
'{}.Length := {};'
.
format
(
ada_string
,
length
))
return
stmts
,
unicode
(
ada_string
),
local_decl
return
stmts
,
unicode
(
ada_string
),
local_decl
...
@@ -1280,13 +1277,7 @@ def _string_literal(primary):
...
@@ -1280,13 +1277,7 @@ def _string_literal(primary):
# as expected by the Ada type corresponding to Octet String
# as expected by the Ada type corresponding to Octet String
unsigned_8
=
[
str
(
ord
(
val
))
for
val
in
primary
.
value
[
1
:
-
1
]]
unsigned_8
=
[
str
(
ord
(
val
))
for
val
in
primary
.
value
[
1
:
-
1
]]
ada_string
=
u
'(Data => ('
+
', '
.
join
(
ada_string
=
u
', '
.
join
(
unsigned_8
)
unsigned_8
)
+
', others => 0)'
if
basic_type
.
Min
!=
basic_type
.
Max
:
# Non-fixed string size -> add Length field
ada_string
+=
u
', Length => {}'
.
format
(
str
(
len
(
primary
.
value
[
1
:
-
1
])))
ada_string
+=
')'
return
[],
unicode
(
ada_string
),
[]
return
[],
unicode
(
ada_string
),
[]
...
@@ -1367,11 +1358,15 @@ def _sequence(seq):
...
@@ -1367,11 +1358,15 @@ def _sequence(seq):
for
elem
,
value
in
seq
.
value
.
viewitems
():
for
elem
,
value
in
seq
.
value
.
viewitems
():
# Set the type of the field - easy thanks to ASN.1 flattened AST
# Set the type of the field - easy thanks to ASN.1 flattened AST
delem
=
elem
.
replace
(
'_'
,
'-'
)
delem
=
elem
.
replace
(
'_'
,
'-'
)
#value.exprType = (TYPES
elem_specty
=
find_basic_type
(
seqType
).
Children
[
delem
].
type
# [seqType.ReferencedTypeName].type.Children[delem].type)
#value.exprType = find_basic_type(seqType).Children[delem].type
value
.
exprType
=
find_basic_type
(
seqType
).
Children
[
delem
].
type
value_stmts
,
value_str
,
local_var
=
expression
(
value
)
value_stmts
,
value_str
,
local_var
=
expression
(
value
)
ada_string
+=
sep
+
elem
+
' => '
+
value_str
if
isinstance
(
value
,
(
ogAST
.
PrimSequenceOf
,
ogAST
.
PrimStringLiteral
)):
# Raw SEQOF element need additional parentheses
#value_str = '(Data => ({}))'.format(value_str)
value_str
=
array_content
(
value
,
value_str
,
find_basic_type
(
elem_specty
))
ada_string
+=
"{} {} => {}"
.
format
(
sep
,
elem
,
value_str
)
sep
=
', '
sep
=
', '
stmts
.
extend
(
value_stmts
)
stmts
.
extend
(
value_stmts
)
local_decl
.
extend
(
local_var
)
local_decl
.
extend
(
local_var
)
...
@@ -1384,31 +1379,22 @@ def _sequence_of(seqof):
...
@@ -1384,31 +1379,22 @@ def _sequence_of(seqof):
''' Return Ada string for an ASN.1 SEQUENCE OF '''
''' Return Ada string for an ASN.1 SEQUENCE OF '''
stmts
,
local_decl
=
[],
[]
stmts
,
local_decl
=
[],
[]
seqofType
=
seqof
.
exprType
seqofType
=
seqof
.
exprType
typename
=
seqofType
.
ReferencedTypeName
try
:
LOG
.
debug
(
'SequenceOf Typename:'
+
str
(
typename
))
typename
=
seqofType
.
ReferencedTypeName
asn_type
=
TYPES
[
typename
].
type
LOG
.
debug
(
'SequenceOf Typename:'
+
str
(
typename
))
min_size
=
asn_type
.
Min
asn_type
=
TYPES
[
typename
].
type
max_size
=
asn_type
.
Max
min_size
=
asn_type
.
Min
ada_string
=
'asn1Scc{seqofType}
\'
('
.
format
(
max_size
=
asn_type
.
Max
seqofType
=
typename
.
replace
(
'-'
,
'_'
))
except
AttributeError
:
if
min_size
==
max_size
:
min_size
,
max_size
=
seqofType
.
Min
,
seqofType
.
Max
# Fixed-length array - no need to set the Length field
ada_string
+=
'Data => asn1Scc{seqofType}_array
\'
('
.
format
(
tab
=
[]
seqofType
=
typename
.
replace
(
'-'
,
'_'
))
else
:
# Variable-length array
ada_string
+=
(
'Length => {length}, Data => asn1Scc{seqofType}_array
\'
('
.
format
(
seqofType
=
typename
.
replace
(
'-'
,
'_'
),
length
=
len
(
seqof
.
value
)))
for
i
in
xrange
(
len
(
seqof
.
value
)):
for
i
in
xrange
(
len
(
seqof
.
value
)):
# Set the type of the element (should not be useful anymore)
#seqof.value[i].exprType = TYPES[typename].type.type
item_stmts
,
item_str
,
local_var
=
expression
(
seqof
.
value
[
i
])
item_stmts
,
item_str
,
local_var
=
expression
(
seqof
.
value
[
i
])
stmts
.
extend
(
item_stmts
)
stmts
.
extend
(
item_stmts
)
local_decl
.
extend
(
local_var
)
local_decl
.
extend
(
local_var
)
ada_string
+=
'{i} => {value}
,
'
.
format
(
i
=
i
+
1
,
value
=
item_str
)
tab
.
append
(
'{i} => {value}'
.
format
(
i
=
i
+
1
,
value
=
item_str
)
)
ada_string
+
=
'
others => {anyVal}))'
.
format
(
anyVal
=
item_str
)
ada_string
=
'
, '
.
join
(
tab
)
return
stmts
,
unicode
(
ada_string
),
local_decl
return
stmts
,
unicode
(
ada_string
),
local_decl
...
@@ -1463,6 +1449,10 @@ def _decision(dec):
...
@@ -1463,6 +1449,10 @@ def _decision(dec):
local_decl
.
extend
(
ans_decl
)
local_decl
.
extend
(
ans_decl
)
if
not
basic
:
if
not
basic
:
if
a
.
openRangeOp
in
(
ogAST
.
ExprEq
,
ogAST
.
ExprNeq
):
if
a
.
openRangeOp
in
(
ogAST
.
ExprEq
,
ogAST
.
ExprNeq
):
if
isinstance
(
a
.
constant
,
(
ogAST
.
PrimSequenceOf
,
ogAST
.
PrimStringLiteral
)):
ans_str
=
array_content
(
a
.
constant
,
ans_str
,
find_basic_type
(
question_type
))
exp
=
u
'asn1Scc{actType}_Equal(tmp{idx}, {ans})'
.
format
(
exp
=
u
'asn1Scc{actType}_Equal(tmp{idx}, {ans})'
.
format
(
actType
=
actual_type
,
idx
=
dec
.
tmpVar
,
ans
=
ans_str
)
actType
=
actual_type
,
idx
=
dec
.
tmpVar
,
ans
=
ans_str
)
if
a
.
openRangeOp
==
ogAST
.
ExprNeq
:
if
a
.
openRangeOp
==
ogAST
.
ExprNeq
:
...
@@ -1664,6 +1654,9 @@ def _inner_procedure(proc):
...
@@ -1664,6 +1654,9 @@ def _inner_procedure(proc):
# Expression must be a ground expression, i.e. must not
# Expression must be a ground expression, i.e. must not
# require temporary variable to store computed result
# require temporary variable to store computed result
dst
,
dstr
,
dlocal
=
expression
(
def_value
)
dst
,
dstr
,
dlocal
=
expression
(
def_value
)
varbty
=
find_basic_type
(
var_type
)
if
varbty
.
kind
in
(
'SequenceOfType'
,
'OctetStringType'
):
dstr
=
array_content
(
def_value
,
dstr
,
varbty
)
assert
not
dst
and
not
dlocal
,
'Ground expression error'
assert
not
dst
and
not
dlocal
,
'Ground expression error'
code
.
append
(
'l_{name} : asn1Scc{sort}{default};'
.
format
(
code
.
append
(
'l_{name} : asn1Scc{sort}{default};'
.
format
(
name
=
var_name
,
name
=
var_name
,
...
@@ -1709,6 +1702,55 @@ def string_payload(prim, ada_string):
...
@@ -1709,6 +1702,55 @@ def string_payload(prim, ada_string):
return
payload
return
payload
def
array_content
(
prim
,
values
,
asnty
):
''' String literal and SEQOF are given as a sequence of elements ;
this function builds the Ada string needed to fit it in an ASN.1 array
i.e. convert "1,2,3" to "Data => (1,2,3, others=>0), [Length => 3]"
inputs: prim is of type PrimStringLiteral or PrimSequenceOf
values is a string with the sequence of numbers as processed by expression
asnty is the reference type of the string literal '''
rtype
=
find_basic_type
(
prim
.
exprType
)
if
asnty
.
Min
!=
asnty
.
Max
:
# Reference type can vary -> there is a Length field
rlen
=
u
", Length => {}"
.
format
(
rtype
.
Min
)
else
:
rlen
=
u
""
if
isinstance
(
prim
,
ogAST
.
PrimStringLiteral
):
df
=
'0'
else
:
# Find a default value for the "others" field in case of SEQOF
_
,
df
,
_
=
expression
(
prim
.
value
[
0
])
return
u
"(Data => ({}, others => {}){})"
.
format
(
values
,
df
,
rlen
)
def
append_size
(
append
):
''' Return a string corresponding to the length of an APPEND construct
This function is recursive, to handle cases such as a//b//c
that is handled as (a//b) // c -> get the length of a//b then add c
'''
result
=
''
basic
=
find_basic_type
(
append
.
exprType
)
if
basic
.
Min
==
basic
.
Max
:
# Simple case when appending two fixed-length sizes
return
basic
.
Min
for
each
in
(
append
.
left
,
append
.
right
):
if
result
:
result
+=
' + '
if
isinstance
(
each
,
ogAST
.
ExprAppend
):
# Inner append -> go recursively
result
+=
append_size
(
each
)
else
:
bty
=
find_basic_type
(
each
.
exprType
)
if
bty
.
Min
==
bty
.
Max
:
result
+=
bty
.
Min
else
:
# Must be a variable of type SEQOF
_
,
inner
,
_
=
expression
(
each
)
result
+=
'{}.Length'
.
format
(
inner
)
return
result
def
find_basic_type
(
a_type
):
def
find_basic_type
(
a_type
):
''' Return the ASN.1 basic type of a_type '''
''' Return the ASN.1 basic type of a_type '''
basic_type
=
a_type
basic_type
=
a_type
...
...
ogParser.py
View file @
b3055210
...
@@ -590,6 +590,7 @@ def check_type_compatibility(primary, type_ref, context):
...
@@ -590,6 +590,7 @@ def check_type_compatibility(primary, type_ref, context):
'''
'''
assert
type_ref
is
not
None
assert
type_ref
is
not
None
if
type_ref
is
UNKNOWN_TYPE
:
if
type_ref
is
UNKNOWN_TYPE
:
#print traceback.print_stack()
raise
TypeError
(
'Type reference is unknown'
)
raise
TypeError
(
'Type reference is unknown'
)
basic_type
=
find_basic_type
(
type_ref
)
basic_type
=
find_basic_type
(
type_ref
)
...
@@ -650,7 +651,8 @@ def check_type_compatibility(primary, type_ref, context):
...
@@ -650,7 +651,8 @@ def check_type_compatibility(primary, type_ref, context):
+
basic_type
.
Min
+
')'
)
+
basic_type
.
Min
+
')'
)
elif
isinstance
(
primary
,
ogAST
.
PrimSequenceOf
)
\
elif
isinstance
(
primary
,
ogAST
.
PrimSequenceOf
)
\
and
basic_type
.
kind
==
'SequenceOfType'
:
and
basic_type
.
kind
==
'SequenceOfType'
:
if
(
len
(
primary
.
value
)
<
int
(
basic_type
.
Min
)
or
if
type_ref
.
__name__
!=
'Apnd'
and
\
(
len
(
primary
.
value
)
<
int
(
basic_type
.
Min
)
or
len
(
primary
.
value
)
>
int
(
basic_type
.
Max
)):
len
(
primary
.
value
)
>
int
(
basic_type
.
Max
)):
raise
TypeError
(
str
(
len
(
primary
.
value
))
+
raise
TypeError
(
str
(
len
(
primary
.
value
))
+
' elements in SEQUENCE OF, while constraint is ['
+
' elements in SEQUENCE OF, while constraint is ['
+
...
@@ -782,11 +784,20 @@ def compare_types(type_a, type_b):
...
@@ -782,11 +784,20 @@ def compare_types(type_a, type_b):
if
type_a
.
kind
==
type_b
.
kind
:
if
type_a
.
kind
==
type_b
.
kind
:
if
type_a
.
kind
==
'SequenceOfType'
:
if
type_a
.
kind
==
'SequenceOfType'
:
if
type_a
.
Min
==
type_b
.
Min
and
type_a
.
Max
==
type_b
.
Max
:
if
type_a
.
Min
==
type_a
.
Max
:
if
type_a
.
Min
==
type_b
.
Min
==
type_b
.
Max
:
compare_types
(
type_a
.
type
,
type_b
.
type
)
return
else
:
raise
TypeError
(
'Incompatible sizes - size of {} can vary'
.
format
(
type_name
(
type_b
)))
elif
(
int
(
type_b
.
Min
)
>=
int
(
type_a
.
Min
)
and
int
(
type_b
.
Max
)
<=
int
(
type_a
.
Max
)):
compare_types
(
type_a
.
type
,
type_b
.
type
)
compare_types
(
type_a
.
type
,
type_b
.
type
)
return
return
else
:
else
:
raise
TypeError
(
'Incompatible arrays'
)
compare_types
(
type_a
.
type
,
type_b
.
type
)
raise
Warning
(
'Size constraints mismatch - risk of overflow'
)
# TODO: Check that OctetString types have compatible range
# TODO: Check that OctetString types have compatible range
return
return
elif
is_string
(
type_a
)
and
is_string
(
type_b
):
elif
is_string
(
type_a
)
and
is_string
(
type_b
):
...
@@ -862,20 +873,6 @@ def fix_expression_types(expr, context):
...
@@ -862,20 +873,6 @@ def fix_expression_types(expr, context):
fix_enumerated_and_choice
(
expr
,
context
)
fix_enumerated_and_choice
(
expr
,
context
)
expr
.
right
,
expr
.
left
=
expr
.
left
,
expr
.
right
expr
.
right
,
expr
.
left
=
expr
.
left
,
expr
.
right
# for side in permutations(('left', 'right')):