Age | Commit message (Collapse) | Author |
|
|
|
|
|
As currently implemented, there is one call to asn1db:dbget() and
asn1db:dbput() for each type/value definitions in an ASN.1 specification.
If we check for duplicate definitions locally, we can send all
definitions in a single call.
|
|
Three fields ('type','value', and 'vname') are almost unused. They
are set, but almost never read. Eliminate the last remaining uses
and the fields themselves.
|
|
|
|
And while we are at it cleanup and rewrite code to use try catch.
|
|
|
|
|
|
Errors were reported using a throw like this:
throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
[got,get_token(hd(Tokens)),expected,typereference]}}).
The attempt to tell the user what was expected was often mis-leading.
It is time-consuming and non-trival to provide correct information
of what is expected. Therefore, we will not even try. Instead we will
spend more effort to report the token where the error was discovered.
We will replace each throw with a function call:
parse_error(Tokens).
Also add the syntax_SUITE test suite to test error reporting and to
cover all error reporting code. Remove the old c_syntax/1 test case.
Also remove all out-commented code.
|
|
To keep the error reporting code in asn1ct_parser2 simple, we
only want to handle pure syntactic errors. Therefore, move the check
that UNIQUE and DEFAULT are not applied to the same field to
asn1ct_check.
|
|
|
|
|
|
While we are at it, also remove an unreachable (too many extensions)
error case.
|
|
|
|
|
|
|
|
Clean up the checking of ENUMERATED and modernize the error reporting.
Also eliminate the unused constraints argument for check_enumerated().
|
|
|
|
|
|
get_unique_fieldname/2 would throw an exception that *all* callers
would catch and handle. Since all callers catch the exception, it
is much easier to return a special return value.
Also use the new error reporting style.
While we are at it, remove all catches of {asn1,Error} which
are no longer thrown.
|
|
Split the test case duplicate_tags/1 into two parts. Do the
error checking test in error_SUITE. Keep the SeqOptional2
specification and compile it from the per/1 and ber_other/1
test cases (for coverage).
|
|
|
|
Change to new error handling system and cover with tests.
|
|
All errors were not reported. Furthermore, get_referenced_type/2
will report errors if any module is missing, so the attempt to
report additional errors in chained_import/4 would not find any
errors.
|
|
The internal representation for constraints (and object sets)
as produced by the parser was awkward, making further processing
convoluted. Here follows some examples of the old representation
for INTEGER constraints.
The constraint 1..2 is represented as:
{'ValueRange',{1,2}}
If we extend the constraint like this:
1..2, ...,
or like this:
1..2, ..., 3
the representation would be:
{{'ValueRange',{1,2}},[]}
and
{{'ValueRange',{1,2}},{'SingleValue',3}}
respectively. Note that the pattern {A,B} will match all these
constraints.
When combining constraints using set operators:
1..2 | 3..4 ^ 5..6
the representation will no longer be a tuple but a list:
[{'ValueRange',{1..2}} union
{'ValueRange',{3..4}} intersection
{'ValueRange',{5..6}}]
The parse has full knowledge of the operator precedence; unfortunately,
the following pass (asn1ct_check) must also have the same knowledge
in order to correctly evaluate the constraints.
If we would change the order of the evaulation with round brackets:
(1..2 | 3..4) ^ 5..6
there would be a nested listed in the representation:
[[{'ValueRange',{1..2}} union {'ValueRange',{3..4}}]
intersection {'ValueRange',{5..6}}]
We will change the representation to make it more explicit.
At the outer level, a constraint is always represented as
{element_set,Root,Extension}
Extension will be 'none' if there is no extension, and 'empty' if
there is an empty extension. Root may also be 'empty' in an object set
if there are no objects in the root. Thus the constraints:
1..2
1..2, ...
1..2, ..., 3
will be represented as:
{element_set,{'ValueRange',{1,2}},none}
{element_set,{'ValueRange',{1,2}},empty}
{element_set,{'ValueRange',{1,2}},{'SingleValue',3}}
We will change the set operators too. This constraint:
1..2 | 3..4 ^ 5..6
will be represented as:
{element_set,
{union,
{'ValueRange',{1,2}},
{intersection,
{'ValueRange',{3,4}},
{'ValueRange',{5,6}}},
none}}
which is trivial to understand and evaluate. Similarly:
(1..2 | 3..4) ^ 5..6
will be represented as:
{element_set,
{intersection,
{union,{'ValueRange',{1,2}},{'ValueRange',{3,4}}},
{'ValueRange',{5,6}}},
none}
|
|
Fixes needed to avoid a compiling asn1 files in order.
For example the x420 directory in test now compiles with
erlc *.asn
Do not save class records without module information in asn1db files.
Use recursive get_referenced_type in get_objclass_fields/2
|
|
|
|
|
|
The ObjectSetFromObjects construct is implemented using
the object_set_from_objects() function, which is similar
to get_fieldname_element(). Rewrite the ObjectSetFromObjects
handling to use get_fieldname_element() to share more code.
|
|
|
|
|
|
a1260b2ffa60581ce3af0728320b593cca3fd7b0 fixed a problem with
expansion of parameterized types, but it didn't go all the way.
The compiler would still crash if we attempted to define a value
using the instantiated type.
|
|
Introduce match_parameter/2 for matching a single parameter and
match_parameters/2 for matching all of them.
|
|
The constraint_member/2 function is used for looking up 'simpletable'
and 'componentrelation' constraints. Both parts of its name are
misleading. The "constraint" part makes you think that it is a general
function for constraints, but it is not - it can only search for
'simpletable' and 'componentrelation'. The "member" part makes you
think that it would return a boolean, but it returns either
{true,Tuple} or false, making it more similar to lists:keysearch/3.
Use lists:keyfind/3 (or lists:keymember/3) instead of
constraint_member/2. Also use lists:keyfind/3 in one place where
there was a direct matching of a 'simpletable' constraint.
|
|
|
|
There is no reason to handle tags differently depending on the
back-end. The PER back-end will simply ignore tags.
There is also a bug in tags the ABSTRACT-SYNTAX and TYPE-IDENTIFIER
pre-defined classes. So far it has not caused problems, but it could
do in a future commit, such as the next commit...
|
|
|
|
To be sure that indirect references to classes are solved.
|
|
|
|
The parser handled the builtin ABSTRACT-SYNTAX and TYPE-IDENTIFIER
classes specially, which caused problems. It turns out that there
is no longer any need to handle those classes specially.
|
|
|
|
An optional group must not contain mandatory class fields. All
mandatory fields must be included in the simplified syntax.
|
|
|
|
Besides simplifying the code and doing better error checking
and error reporting, fix the following bugs:
Support retrieving an OBJECT IDENTIFIER/RELATIVE-OID from an
object. Example:
oid OBJECT IDENTIFIER ::= some-object.&some-field
Allow an integer constant first in an OBJECT IDENTIFIER:
integer INTEGER ::= 0
oid OBJECT IDENTIFIER ::= {integer 1}
|
|
Wrong fields in the record where checked when sorting, which caused
duplicate objects to exist in constructed object sets and later caused
an error.
|
|
|
|
Also add proper error handling.
|
|
File names and line number information was not reliable available
when producing error messages. Some items have embedded line number
information, and sometimes the S#state.type and/or S#state.value
could be used to retrieve the line number information.
To make sure that we can always retrieve at least an approximate
error location, store the top-level construct being checked in
S#state.error_context. Example of top-level constructs:
Seq ::= SEQUENCE {...}
i INTEGER ::= 42
This is a short-term solution. In the long term, we would want the
parser to include line number information in all items.
|
|
Rewrite the confusing and buggy matching of an object definition
against the simplified syntax.
While we are at it, we will also add proper error handling.
|
|
When the parser sees:
something SOMETHING ::= {}
it has no way of knowing whether 'something' is an value or an
object. It depends on how SOMETHING is defined. For example:
SOMETHING ::= SEQUENCE {}
or
SOMETHING ::= CLASS { &id OPTIONAL }
Because of that ambiguity, there is no way to avoid a special case
when we check an object definition. However, there is no need to
invent an entire new checking function for this special case. It is
much easier to just pretend that the parser gave us
{object,defaultsyntax,[]} and let check_objectdefn/3 check it in the
usual way.
|