Age | Commit message (Collapse) | Author |
|
* bjorn/asn1/rfc-5912/OTP-12395: (79 commits)
Remove the old unused yecc-based parser
Improve error handling for illegal object definitions
Reimplement storeindb/2 to avoid excessive process communication
Remove useless fields in #state{}
Remove vestiges of obsolete {TypeName,Value} notation
Remove old error handling
Modernize the remaining cases
Further improve error handling for instatiation of parameterized types
asn1ct_tok: Clean up
Add a test case for EXTENSIBILITY IMPLIED
asn1ct_parser2: Remove expensive lookahead_assignment/1 function
asn1ct_parser2: Clean up error handling and reporting
asn1ct, asn1ct_parser2: Refactor the upper levels of error handling
asn1ct_parser2: Eliminate all uses of old-style 'catch'
asn1ct_parser2: Clean up parse_or/3 and parse_or_tag/3
asn1ct_parser2: Correct extraction of line number from token
asn1ct_parser2: Throw an {asn1_error,...} for *all* parse errors
asn1ct_parser2: Simplify parse_Type/1
asn1ct_parser2: Remove unsuccessful parsing of ValueSetFromObjects
Move checking of UNIQUE & DEFAULT error to asn1ct_check
...
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
In the parsing of a value assignment, such as:
value INTEGER ::= 42
there is call to a function called lookahead_assignment/1 that
will ensure that the sequence of tokens that follows the value
is a valid assignment. The problem is that if the next assignment
is a value assignment, that too will look ahead to the next
assignment. That means that the complexity will be quadratic
if there are many value assignments following each other.
The reason for the test in the first place is unclear; my guess
is that it was an attempt to provide better error reporting.
|
|
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.
|
|
Responsibilities for parse error handling were split between
asn1ct and asn1ct_parser2 in a confusing way. Let asn1ct_parser2
return structured_error tuples in the same way as the check
pass.
|
|
Most uses of 'catch' are not necessary. For example,
parse_or/2 is typically called like this:
case catch parse_or(Tokens, Flist) of
{'EXIT',Reason} ->
exit(Reason);
{asn1_error,_}=AsnErr ->
throw(AsnErr);
Result ->
Result
end.
Since {asn1_error,_} is always thrown (never returned) and
a successful is always returned (never thrown), the 'case' and
the 'catch' are not necessary. The code can be simplified too:
parse_or(Tokens, Flist)
In a few cases, we will need to replace the 'catch' with
'try'...'catch'.
|
|
Use try...catch instead of catch.
|
|
The first position in a token tuple is always an atom, the second
the line number. The code tested the third position.
|
|
In a future commit, we want to tighten what we catch. Therefore,
legitimate parsing errors should always throw a controlled exception,
instead of arbitrarily crashing.
|
|
The parse_Type/1 calls various type parse functions. Most of those
functions return a #type record, but not all of them. If a #type{}
record is not returned, parse_Type/1 will wrap the return value in a
We can simplify the code in parse_Type/1 if we make sure that the
type parsing functions called by parse_Type/1 always return
a #type{} record.
|
|
The TypeFromObject and ValueSetFromObjects grammar productions cannot
be distinguished by the parser without the help of type information
(which the parser does not have). Since the parser attempts to
parse TypeFromObject before ValueSetFromObjects, the parsing of
ValueSetFromObjects will always fail.
|
|
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.
|
|
asn1ct_gen_check.erl was added in 7df687d6.
|
|
"SET OF id < Type" was not tested. Also make sure that all of
assigned values are correct.
|
|
|
|
|
|
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().
|
|
The ASN.1 compiler would go into an infinite loop if a value
in an ENUMERATED was negative.
|
|
|
|
|
|
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}
|
|
Instead of only compiling to the abstract format using 'abs',
also compile to each of the back-ends.
|
|
The warnings in the ASN.1 are being eliminated one by one and
replaced with errors. Therefore, it is no longer possible to test
warnings_as_errors. We will reimplement this test case in the future
if we will introduce some new sensible warnings.
|
|
NeedRest was introduced in df7bb30f, for unknown reasons (my guess
is that the argument was needed at some point during the development
of the commit).
Found by dialyzer.
|
|
Changed the following from the original copies:
PKCS-5 (renamed from PKCS-v21)
PKCS-9 Import from CryptographicMessageSyntax-2009 instead
of CryptographicMessageSyntax
Since most of the files from the x420 directory are needed,
copy all of them into the rfcs directory and remove the
x420 directory and test case. Copy the test of OTP-7759 to
the testRfcs test case.
|
|
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.
|