asn1: Allow CHOICEs to be decorated too
Prior to this commit only those C structs for SET and SEQUENCE types could be decorated. Now those for CHOICE types also can be decorated. We could further extend this to SET OF and SEQUENCE OF types if it proves useful.
This commit is contained in:
@@ -184,9 +184,42 @@ In recent times the following features have been added:
|
|||||||
- Most of X.690 is supported for decoding, with only DER supported for
|
- Most of X.690 is supported for decoding, with only DER supported for
|
||||||
encoding.
|
encoding.
|
||||||
|
|
||||||
- Dumping of ASN.1 modules as JSON (note: the JSON schema for ASN.1 modules is
|
- For cryptographic applications there is a `--preserve-binary=TYPE` compiler
|
||||||
not stable yet). This enables analysis using, e.g., `jq` or similar, and
|
option that causes the `TYPE`'s C `struct` to gain a `_save` field where the
|
||||||
even construction of alternative compilers using `jq` or similar.
|
original encoding of the `TYPE` is preserved by the decoder. This allows
|
||||||
|
cryptographic applications to validate signatures, MACs, authenticated
|
||||||
|
decryption tags, checksums, etc., without having to re-encode the `TYPE`
|
||||||
|
(which wouldn't even work if the encoding received were BER and BER were
|
||||||
|
permitted for that `TYPE`).
|
||||||
|
|
||||||
|
- Unconstrained integer types have a large integer representation in C that is
|
||||||
|
not terribly useful in common cases. Range and member constraints on
|
||||||
|
integer types cause the compiler to use `int`, `int64_t`, `unsigned int`,
|
||||||
|
and/or `uint64_t` as appropriate.
|
||||||
|
|
||||||
|
- The Heimdal ASN.1 compiler currently handles a large subset of X.680, and
|
||||||
|
(in a branch) a small subset of X.681, X.682, and X.683, which manifests as
|
||||||
|
automatic handling of all open types contained in `SET`/`SEQUENCE` types
|
||||||
|
that are parameterized with information object sets. This allows all open
|
||||||
|
types in PKIX certificates, for example, to get decoded automatically no
|
||||||
|
matter how deeply nested. We use a TCG EK certificate that has eight
|
||||||
|
certificate extensions, including subject alternative names and subject
|
||||||
|
directory attributes where the attribute values are not string types, and
|
||||||
|
all of these things get decoded automatically.
|
||||||
|
|
||||||
|
- The template backend dedups templates to save space. This is an O(N^2) kind
|
||||||
|
of feature that we need to make optional, but it works. (When we implement
|
||||||
|
JER this will have the side-effect of printing the wrong type names in some
|
||||||
|
cases because two or more types have the same templates and get deduped.)
|
||||||
|
|
||||||
|
- There is an _experimental_ ASN.1 module -> JSON feature in the compiler. It
|
||||||
|
currently dumps type and value definitions, but not class, or object set
|
||||||
|
definitions. Even for types, it is not complete, and the JSON schema used
|
||||||
|
is subject to change *WITHOUT NOTICE*.
|
||||||
|
|
||||||
|
Perhaps eventually we can re-write the compiler as a C-coded ASN.1 -> JSON
|
||||||
|
stage followed by a jq-coded code and template generator state, which would
|
||||||
|
make it much easier to extend the compiler.
|
||||||
|
|
||||||
- We have an `asn1_print` program that can decode DER from any exported types
|
- We have an `asn1_print` program that can decode DER from any exported types
|
||||||
from any ASN.1 modules committed in Heimdal:
|
from any ASN.1 modules committed in Heimdal:
|
||||||
@@ -787,35 +820,6 @@ In recent times the following features have been added:
|
|||||||
slightly different names in the ASN.1 modules in Heimdal's source tree.
|
slightly different names in the ASN.1 modules in Heimdal's source tree.
|
||||||
We'll fix this eventually.)
|
We'll fix this eventually.)
|
||||||
|
|
||||||
- Unconstrained integer types have a large integer representation in C that is
|
|
||||||
not terribly useful in common cases. Range and member constraints on
|
|
||||||
integer types cause the compiler to use `int`, `int64_t`, `unsigned int`,
|
|
||||||
and/or `uint64_t` as appropriate.
|
|
||||||
|
|
||||||
- The Heimdal ASN.1 compiler currently handles a large subset of X.680, and
|
|
||||||
(in a branch) a small subset of X.681, X.682, and X.683, which manifests as
|
|
||||||
automatic handling of all open types contained in `SET`/`SEQUENCE` types
|
|
||||||
that are parameterized with information object sets. This allows all open
|
|
||||||
types in PKIX certificates, for example, to get decoded automatically no
|
|
||||||
matter how deeply nested. We use a TCG EK certificate that has eight
|
|
||||||
certificate extensions, including subject alternative names and subject
|
|
||||||
directory attributes where the attribute values are not string types, and
|
|
||||||
all of these things get decoded automatically.
|
|
||||||
|
|
||||||
- The template backend dedups templates to save space. This is an O(N^2) kind
|
|
||||||
of feature that we need to make optional, but it works. (When we implement
|
|
||||||
JER this will have the side-effect of printing the wrong type names in some
|
|
||||||
cases because two or more types have the same templates and get deduped.)
|
|
||||||
|
|
||||||
- There is an _experimental_ ASN.1 module -> JSON feature in the compiler. It
|
|
||||||
currently dumps type and value definitions, but not class, or object set
|
|
||||||
definitions. Even for types, it is not complete, and the JSON schema used
|
|
||||||
is subject to change *WITHOUT NOTICE*.
|
|
||||||
|
|
||||||
Perhaps eventually we can re-write the compiler as a C-coded ASN.1 -> JSON
|
|
||||||
stage followed by a jq-coded code and template generator state, which would
|
|
||||||
make it much easier to extend the compiler.
|
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
## Limitations
|
## Limitations
|
||||||
@@ -894,19 +898,19 @@ DESCRIPTION
|
|||||||
asn1_compile compiles an ASN.1 module into C source code and header
|
asn1_compile compiles an ASN.1 module into C source code and header
|
||||||
files.
|
files.
|
||||||
|
|
||||||
A fairly large subset of ASN.1 as specified in X.680, and the ASN.1 In-
|
A fairly large subset of ASN.1 as specified in X.680, and the ASN.1 In‐
|
||||||
formation Object System as specified in X.681, X.682, and X.683 is sup-
|
formation Object System as specified in X.681, X.682, and X.683 is sup‐
|
||||||
ported, with support for the Distinguished Encoding Rules (DER), partial
|
ported, with support for the Distinguished Encoding Rules (DER), partial
|
||||||
Basic Encoding Rules (BER) support, and experimental JSON support (encod-
|
Basic Encoding Rules (BER) support, and experimental JSON support (encod‐
|
||||||
ing only at this time).
|
ing only at this time).
|
||||||
|
|
||||||
See the compiler's README files for details about the C code and inter-
|
See the compiler's README files for details about the C code and inter‐
|
||||||
faces it generates.
|
faces it generates.
|
||||||
|
|
||||||
The Information Object System support includes automatic codec support
|
The Information Object System support includes automatic codec support
|
||||||
for encoding and decoding through “open types” which are also known as
|
for encoding and decoding through “open types” which are also known as
|
||||||
“typed holes”. See RFC 5912 for examples of how to use the ASN.1 Infor-
|
“typed holes”. See RFC 5912 for examples of how to use the ASN.1 Infor‐
|
||||||
mation Object System via X.681/X.682/X.683 annotations. See the com-
|
mation Object System via X.681/X.682/X.683 annotations. See the com‐
|
||||||
piler's README files for more information on ASN.1 Information Object
|
piler's README files for more information on ASN.1 Information Object
|
||||||
System support.
|
System support.
|
||||||
|
|
||||||
@@ -918,7 +922,7 @@ DESCRIPTION
|
|||||||
• enable saving of as-received encodings of specific types
|
• enable saving of as-received encodings of specific types
|
||||||
for the purpose of signature validation;
|
for the purpose of signature validation;
|
||||||
• generate add/remove utility functions for array types;
|
• generate add/remove utility functions for array types;
|
||||||
• decorate generated ‘struct’ types with fields that are nei-
|
• decorate generated ‘struct’ types with fields that are nei‐
|
||||||
ther encoded nor decoded;
|
ther encoded nor decoded;
|
||||||
etc.
|
etc.
|
||||||
|
|
||||||
@@ -945,7 +949,7 @@ DESCRIPTION
|
|||||||
• The REAL type is not supported.
|
• The REAL type is not supported.
|
||||||
• The EmbeddedPDV type is not supported.
|
• The EmbeddedPDV type is not supported.
|
||||||
• The BMPString type is not supported.
|
• The BMPString type is not supported.
|
||||||
• The IA5String is not properly supported, as it's essen-
|
• The IA5String is not properly supported, as it's essen‐
|
||||||
tially treated as a UTF8String with a different tag.
|
tially treated as a UTF8String with a different tag.
|
||||||
• All supported non-octet strings are treated as like the
|
• All supported non-octet strings are treated as like the
|
||||||
UTF8String type.
|
UTF8String type.
|
||||||
@@ -967,19 +971,19 @@ DESCRIPTION
|
|||||||
The codegen backend generates C code for all functions directly,
|
The codegen backend generates C code for all functions directly,
|
||||||
with no template interpretation.
|
with no template interpretation.
|
||||||
|
|
||||||
The template backend scales better than the codegen backend be-
|
The template backend scales better than the codegen backend be‐
|
||||||
cause as we add support for more encoding rules and more opera-
|
cause as we add support for more encoding rules and more opera‐
|
||||||
tions (we may add value comparators) the templates stay mostly
|
tions (we may add value comparators) the templates stay mostly
|
||||||
the same, thus scaling linearly with size of module. Whereas the
|
the same, thus scaling linearly with size of module. Whereas the
|
||||||
codegen backend scales linear with the product of module size and
|
codegen backend scales linear with the product of module size and
|
||||||
number of encoding rules supported.
|
number of encoding rules supported.
|
||||||
|
|
||||||
--prefix-enum
|
--prefix-enum
|
||||||
This option should be removed because ENUMERATED types should al-
|
This option should be removed because ENUMERATED types should al‐
|
||||||
ways have their labels prefixed.
|
ways have their labels prefixed.
|
||||||
|
|
||||||
--enum-prefix=PREFIX
|
--enum-prefix=PREFIX
|
||||||
This option should be removed because ENUMERATED types should al-
|
This option should be removed because ENUMERATED types should al‐
|
||||||
ways have their labels prefixed.
|
ways have their labels prefixed.
|
||||||
|
|
||||||
--encode-rfc1510-bit-string
|
--encode-rfc1510-bit-string
|
||||||
@@ -1012,15 +1016,15 @@ DESCRIPTION
|
|||||||
be a ‘SET OF’ or ‘SEQUENCE OF’ type.
|
be a ‘SET OF’ or ‘SEQUENCE OF’ type.
|
||||||
|
|
||||||
--decorate=ASN1-TYPE:FIELD-ASN1-TYPE:fname[?]
|
--decorate=ASN1-TYPE:FIELD-ASN1-TYPE:fname[?]
|
||||||
Add to the C struct generated for the given ASN.1 SET or SEQUENCE
|
Add to the C struct generated for the given ASN.1 SET, SEQUENCE,
|
||||||
type named ASN1-TYPE a “hidden” field named fname of the given
|
or CHOICE type named ASN1-TYPE a “hidden” field named fname of
|
||||||
ASN.1 type FIELD-ASN1-TYPE, but do not encode or decode it. If
|
the given ASN.1 type FIELD-ASN1-TYPE, but do not encode or decode
|
||||||
the fname ends in a question mark, then treat the field as OP-
|
it. If the fname ends in a question mark, then treat the field
|
||||||
TIONAL.
|
as OPTIONAL.
|
||||||
|
|
||||||
This is useful for adding fields to existing types that can be
|
This is useful for adding fields to existing types that can be
|
||||||
used for internal bookkeeping but which do not affect interoper-
|
used for internal bookkeeping but which do not affect interoper‐
|
||||||
ability because they are neither encoded nor decoded. For exam-
|
ability because they are neither encoded nor decoded. For exam‐
|
||||||
ple, one might decorate a request type with state needed during
|
ple, one might decorate a request type with state needed during
|
||||||
processing of the request.
|
processing of the request.
|
||||||
|
|
||||||
@@ -1028,31 +1032,31 @@ DESCRIPTION
|
|||||||
Add to the C struct generated for the given ASN.1 SET or SEQUENCE
|
Add to the C struct generated for the given ASN.1 SET or SEQUENCE
|
||||||
type named ASN1-TYPE a “hidden” field named fname of C type
|
type named ASN1-TYPE a “hidden” field named fname of C type
|
||||||
‘heim_object_t’ values of which will be copied and released with
|
‘heim_object_t’ values of which will be copied and released with
|
||||||
‘heim_release()’ and ‘heim_retain()’ respectively.
|
‘heim_retain()’ and ‘heim_release()’ respectively.
|
||||||
|
|
||||||
--decorate=ASN1-TYPE:void*:fname
|
--decorate=ASN1-TYPE:void*:fname
|
||||||
Add to the C struct generated for the given ASN.1 SET or SEQUENCE
|
Add to the C struct generated for the given ASN.1 SET, SEQUENCE,
|
||||||
type named ASN1-TYPE a “hidden” field named fname of type ‘void
|
or CHOICE type named ASN1-TYPE a “hidden” field named fname of
|
||||||
*’ (but do not encode or decode it.
|
type ‘void *’ (but do not encode or decode it.
|
||||||
|
|
||||||
The destructor and copy constructor functions generated by this
|
The destructor and copy constructor functions generated by this
|
||||||
compiler for ASN1-TYPE will set this field to the ‘NULL’ pointer.
|
compiler for ASN1-TYPE will set this field to the ‘NULL’ pointer.
|
||||||
|
|
||||||
--decorate=ASN1-TYPE:FIELD-C-TYPE:fname[?]:[copyfn]:[freefn]:header
|
--decorate=ASN1-TYPE:FIELD-C-TYPE:fname[?]:[copyfn]:[freefn]:header
|
||||||
Add to the C struct generated for the given ASN.1 SET or SEQUENCE
|
Add to the C struct generated for the given ASN.1 SET, SEQUENCE,
|
||||||
type named ASN1-TYPE a “hidden” field named fname of the given
|
or CHOICE type named ASN1-TYPE a “hidden” field named fname of
|
||||||
external C type FIELD-C-TYPE, declared in the given header but do
|
the given external C type FIELD-C-TYPE, declared in the given
|
||||||
not encode or decode this field. If the fname ends in a question
|
header but do not encode or decode this field. If the fname ends
|
||||||
mark, then treat the field as OPTIONAL.
|
in a question mark, then treat the field as OPTIONAL.
|
||||||
|
|
||||||
The header must include double quotes or angle brackets. The
|
The header must include double quotes or angle brackets. The
|
||||||
copyfn must be the name of a copy constructor function that takes
|
copyfn must be the name of a copy constructor function that takes
|
||||||
a pointer to a source value of the type, and a pointer to a des-
|
a pointer to a source value of the type, and a pointer to a des‐
|
||||||
tination value of the type, in that order, and which returns zero
|
tination value of the type, in that order, and which returns zero
|
||||||
on success or else a system error code on failure. The freefn
|
on success or else a system error code on failure. The freefn
|
||||||
must be the name of a destructor function that takes a pointer to
|
must be the name of a destructor function that takes a pointer to
|
||||||
a value of the type and which releases resources referenced by
|
a value of the type and which releases resources referenced by
|
||||||
that value, but does not free the value itself (the run-time al-
|
that value, but does not free the value itself (the run-time al‐
|
||||||
locates this value as needed from the C heap). The freefn should
|
locates this value as needed from the C heap). The freefn should
|
||||||
also reset the value to a pristine state (such as all zeros).
|
also reset the value to a pristine state (such as all zeros).
|
||||||
|
|
||||||
@@ -1060,8 +1064,6 @@ DESCRIPTION
|
|||||||
field will neither be copied nor freed by the functions generated
|
field will neither be copied nor freed by the functions generated
|
||||||
for the TYPE.
|
for the TYPE.
|
||||||
|
|
||||||
NOTE: At this time only one decoration may be specified per type.
|
|
||||||
|
|
||||||
--one-code-file
|
--one-code-file
|
||||||
Generate a single source code file. Otherwise a separate code
|
Generate a single source code file. Otherwise a separate code
|
||||||
file will be generated for every type.
|
file will be generated for every type.
|
||||||
@@ -1074,7 +1076,7 @@ DESCRIPTION
|
|||||||
|
|
||||||
--original-order
|
--original-order
|
||||||
Attempt to preserve the original order of type definition in the
|
Attempt to preserve the original order of type definition in the
|
||||||
ASN.1 module. By default the compiler generates types in a topo-
|
ASN.1 module. By default the compiler generates types in a topo‐
|
||||||
logical sort order.
|
logical sort order.
|
||||||
|
|
||||||
--no-parse-units
|
--no-parse-units
|
||||||
@@ -1090,7 +1092,7 @@ DESCRIPTION
|
|||||||
--help
|
--help
|
||||||
|
|
||||||
NOTES
|
NOTES
|
||||||
Currently only the template backend supports automatic encoding and de-
|
Currently only the template backend supports automatic encoding and de‐
|
||||||
coding of open types via the ASN.1 Information Object System and
|
coding of open types via the ASN.1 Information Object System and
|
||||||
X.681/X.682/X.683 annotations.
|
X.681/X.682/X.683 annotations.
|
||||||
|
|
||||||
|
@@ -239,8 +239,8 @@ or
|
|||||||
.Sq SEQUENCE OF
|
.Sq SEQUENCE OF
|
||||||
type.
|
type.
|
||||||
.It Fl Fl decorate=ASN1-TYPE:FIELD-ASN1-TYPE:fname[?]
|
.It Fl Fl decorate=ASN1-TYPE:FIELD-ASN1-TYPE:fname[?]
|
||||||
Add to the C struct generated for the given ASN.1 SET or SEQUENCE type
|
Add to the C struct generated for the given ASN.1 SET, SEQUENCE, or
|
||||||
named
|
CHOICE type named
|
||||||
.Ar ASN1-TYPE
|
.Ar ASN1-TYPE
|
||||||
a
|
a
|
||||||
.Dq hidden
|
.Dq hidden
|
||||||
@@ -274,8 +274,8 @@ and
|
|||||||
.Sq heim_release()
|
.Sq heim_release()
|
||||||
respectively.
|
respectively.
|
||||||
.It Fl Fl decorate=ASN1-TYPE:void*:fname
|
.It Fl Fl decorate=ASN1-TYPE:void*:fname
|
||||||
Add to the C struct generated for the given ASN.1 SET or SEQUENCE type
|
Add to the C struct generated for the given ASN.1 SET, SEQUENCE, or
|
||||||
named
|
CHOICE type named
|
||||||
.Ar ASN1-TYPE
|
.Ar ASN1-TYPE
|
||||||
a
|
a
|
||||||
.Dq hidden
|
.Dq hidden
|
||||||
@@ -292,8 +292,8 @@ will set this field to the
|
|||||||
.Sq NULL
|
.Sq NULL
|
||||||
pointer.
|
pointer.
|
||||||
.It Fl Fl decorate=ASN1-TYPE:FIELD-C-TYPE:fname[?]:[copyfn]:[freefn]:header
|
.It Fl Fl decorate=ASN1-TYPE:FIELD-C-TYPE:fname[?]:[copyfn]:[freefn]:header
|
||||||
Add to the C struct generated for the given ASN.1 SET or SEQUENCE type
|
Add to the C struct generated for the given ASN.1 SET, SEQUENCE, or
|
||||||
named
|
CHOICE type named
|
||||||
.Ar ASN1-TYPE
|
.Ar ASN1-TYPE
|
||||||
a
|
a
|
||||||
.Dq hidden
|
.Dq hidden
|
||||||
@@ -335,8 +335,6 @@ and
|
|||||||
are empty strings, then the decoration field will neither be
|
are empty strings, then the decoration field will neither be
|
||||||
copied nor freed by the functions generated for the
|
copied nor freed by the functions generated for the
|
||||||
.Ar TYPE .
|
.Ar TYPE .
|
||||||
.Pp
|
|
||||||
NOTE: At this time only one decoration may be specified per type.
|
|
||||||
.It Fl Fl one-code-file
|
.It Fl Fl one-code-file
|
||||||
Generate a single source code file.
|
Generate a single source code file.
|
||||||
Otherwise a separate code file will be generated for every type.
|
Otherwise a separate code file will be generated for every type.
|
||||||
|
@@ -1047,6 +1047,9 @@ test_decorated(void)
|
|||||||
memset(&td, 0, sizeof(td));
|
memset(&td, 0, sizeof(td));
|
||||||
memset(&tnd, 0, sizeof(tnd));
|
memset(&tnd, 0, sizeof(tnd));
|
||||||
|
|
||||||
|
my_copy_vers_called = 0;
|
||||||
|
my_free_vers_called = 0;
|
||||||
|
|
||||||
td.version = 3;
|
td.version = 3;
|
||||||
td.version3.v = 5;
|
td.version3.v = 5;
|
||||||
td.privthing = &td;
|
td.privthing = &td;
|
||||||
@@ -1085,7 +1088,8 @@ test_decorated(void)
|
|||||||
warnx("copy_TESTDecorated() did not work correctly (2)");
|
warnx("copy_TESTDecorated() did not work correctly (2)");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (td.version3.v != td_copy.version3.v) {
|
if (td.version3.v != td_copy.version3.v ||
|
||||||
|
my_copy_vers_called != 1) {
|
||||||
warnx("copy_TESTDecorated() did not work correctly (3)");
|
warnx("copy_TESTDecorated() did not work correctly (3)");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -1119,6 +1123,97 @@ test_decorated(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
test_decorated_choice(void)
|
||||||
|
{
|
||||||
|
TESTNotDecoratedChoice tndc;
|
||||||
|
TESTDecoratedChoice tdc, tdc_copy;
|
||||||
|
size_t len, size;
|
||||||
|
void *ptr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
memset(&tdc, 0, sizeof(tdc));
|
||||||
|
memset(&tndc, 0, sizeof(tndc));
|
||||||
|
|
||||||
|
my_copy_vers_called = 0;
|
||||||
|
my_free_vers_called = 0;
|
||||||
|
|
||||||
|
tdc.element = choice_TESTDecoratedChoice_version;
|
||||||
|
tdc.u.version = 3;
|
||||||
|
tdc.version3.v = 5;
|
||||||
|
tdc.privthing = &tdc;
|
||||||
|
tdc.privobj = heim_string_create("foo");
|
||||||
|
if ((tdc.version2 = malloc(sizeof(*tdc.version2))) == NULL)
|
||||||
|
errx(1, "out of memory");
|
||||||
|
*tdc.version2 = 5;
|
||||||
|
ASN1_MALLOC_ENCODE(TESTDecoratedChoice, ptr, len, &tdc, &size, ret);
|
||||||
|
if (ret) {
|
||||||
|
warnx("could not encode a TESTDecoratedChoice struct");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
ret = decode_TESTNotDecoratedChoice(ptr, len, &tndc, &size);
|
||||||
|
if (ret) {
|
||||||
|
warnx("could not decode a TESTDecoratedChoice struct as TESTNotDecoratedChoice");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
free(ptr);
|
||||||
|
if (size != len) {
|
||||||
|
warnx("TESTDecoratedChoice encoded size mismatch");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ((int)tdc.element != (int)tndc.element ||
|
||||||
|
tdc.u.version != tndc.u.version) {
|
||||||
|
warnx("TESTDecoratedChoice did not decode as a TESTNotDecoratedChoice correctly");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (copy_TESTDecoratedChoice(&tdc, &tdc_copy)) {
|
||||||
|
warnx("copy_TESTDecoratedChoice() failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ((int)tdc.element != (int)tdc_copy.element ||
|
||||||
|
tdc.u.version != tdc_copy.u.version) {
|
||||||
|
warnx("copy_TESTDecoratedChoice() did not work correctly (1)");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (tdc_copy.version2 == NULL || *tdc.version2 != *tdc_copy.version2) {
|
||||||
|
warnx("copy_TESTDecoratedChoice() did not work correctly (2)");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (tdc.version3.v != tdc_copy.version3.v ||
|
||||||
|
my_copy_vers_called != 1) {
|
||||||
|
warnx("copy_TESTDecoratedChoice() did not work correctly (3)");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (tdc_copy.privthing != 0) {
|
||||||
|
warnx("copy_TESTDecoratedChoice() did not work correctly (4)");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (tdc_copy.privobj != tdc.privobj) {
|
||||||
|
warnx("copy_TESTDecoratedChoice() did not work correctly (5)");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
free_TESTDecoratedChoice(&tdc_copy);
|
||||||
|
free_TESTDecoratedChoice(&tdc);
|
||||||
|
if (tdc.version2) {
|
||||||
|
warnx("free_TESTDecoratedChoice() did not work correctly (1)");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (tdc.version3.v != 0 || my_free_vers_called != 2) {
|
||||||
|
warnx("free_TESTDecoratedChoice() did not work correctly (2)");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (tdc.privthing != 0) {
|
||||||
|
warnx("free_TESTDecoratedChoice() did not work correctly (3)");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (tdc.privobj != 0) {
|
||||||
|
warnx("free_TESTDecoratedChoice() did not work correctly (4)");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cmp_TESTImplicit (void *a, void *b)
|
cmp_TESTImplicit (void *a, void *b)
|
||||||
@@ -2597,6 +2692,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
DO_ONE(test_default);
|
DO_ONE(test_default);
|
||||||
|
|
||||||
|
DO_ONE(test_decorated_choice);
|
||||||
DO_ONE(test_decorated);
|
DO_ONE(test_decorated);
|
||||||
|
|
||||||
#if ASN1_IOS_SUPPORTED
|
#if ASN1_IOS_SUPPORTED
|
||||||
|
@@ -1488,6 +1488,9 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t
|
|||||||
define_type(level, name, basename, t, t->subtype, typedefp, preservep);
|
define_type(level, name, basename, t, t->subtype, typedefp, preservep);
|
||||||
break;
|
break;
|
||||||
case TChoice: {
|
case TChoice: {
|
||||||
|
struct decoration deco;
|
||||||
|
ssize_t more_deco = -1;
|
||||||
|
int decorated = 0;
|
||||||
int first = 1;
|
int first = 1;
|
||||||
Member *m;
|
Member *m;
|
||||||
|
|
||||||
@@ -1546,9 +1549,39 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t
|
|||||||
}
|
}
|
||||||
space(level + 1);
|
space(level + 1);
|
||||||
fprintf (headerfile, "} u;\n");
|
fprintf (headerfile, "} u;\n");
|
||||||
|
fprintf(jsonfile, "]");
|
||||||
|
|
||||||
|
while (decorate_type(newbasename, &deco, &more_deco)) {
|
||||||
|
decorated++;
|
||||||
|
space(level + 1);
|
||||||
|
fprintf(headerfile, "%s %s%s;\n", deco.field_type,
|
||||||
|
deco.opt ? "*" : "", deco.field_name);
|
||||||
|
if (deco.first)
|
||||||
|
fprintf(jsonfile, ",\"decorate\":[");
|
||||||
|
fprintf(jsonfile, "%s{"
|
||||||
|
"\"type\":\"%s\",\"name\":\"%s\",\"optional\":%s,"
|
||||||
|
"\"external\":%s,\"pointer\":%s,\"void_star\":%s,"
|
||||||
|
"\"struct_star\":%s,\"heim_object\":%s,"
|
||||||
|
"\"copy_function\":\"%s\","
|
||||||
|
"\"free_function\":\"%s\",\"header_name\":%s%s%s"
|
||||||
|
"}",
|
||||||
|
deco.first ? "" : ",",
|
||||||
|
deco.field_type, deco.field_name,
|
||||||
|
deco.opt ? "true" : "false", deco.ext ? "true" : "false",
|
||||||
|
deco.ptr ? "true" : "false", deco.void_star ? "true" : "false",
|
||||||
|
deco.struct_star ? "true" : "false", deco.heim_object ? "true" : "false",
|
||||||
|
deco.copy_function_name ? deco.copy_function_name : "",
|
||||||
|
deco.free_function_name ? deco.free_function_name : "",
|
||||||
|
deco.header_name && deco.header_name[0] == '"' ? "" : "\"",
|
||||||
|
deco.header_name ? deco.header_name : "",
|
||||||
|
deco.header_name && deco.header_name[0] == '"' ? "" : "\""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (decorated)
|
||||||
|
fprintf(jsonfile, "]");
|
||||||
|
|
||||||
space(level);
|
space(level);
|
||||||
fprintf (headerfile, "} %s;\n", name);
|
fprintf (headerfile, "} %s;\n", name);
|
||||||
fprintf(jsonfile, "]");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TUTCTime:
|
case TUTCTime:
|
||||||
@@ -1669,10 +1702,19 @@ declare_type(const Symbol *s, Type *t, int typedefp)
|
|||||||
getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
|
getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
|
||||||
fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
|
fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
|
||||||
break;
|
break;
|
||||||
case TChoice:
|
case TChoice: {
|
||||||
|
struct decoration deco;
|
||||||
|
ssize_t more_deco = -1;
|
||||||
|
|
||||||
getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
|
getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
|
||||||
fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
|
fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
|
||||||
|
while (decorate_type(newbasename, &deco, &more_deco)) {
|
||||||
|
if (deco.header_name)
|
||||||
|
fprintf(headerfile, "#include %s\n", deco.header_name);
|
||||||
|
free(deco.field_type);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
abort ();
|
abort ();
|
||||||
}
|
}
|
||||||
|
@@ -1317,6 +1317,8 @@ template_members(struct templatehead *temp,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TChoice: {
|
case TChoice: {
|
||||||
|
struct decoration deco;
|
||||||
|
ssize_t more_deco = -1;
|
||||||
struct templatehead template;
|
struct templatehead template;
|
||||||
struct template *q;
|
struct template *q;
|
||||||
size_t count = 0, i;
|
size_t count = 0, i;
|
||||||
@@ -1398,6 +1400,34 @@ template_members(struct templatehead *temp,
|
|||||||
|
|
||||||
add_line(temp, "{ A1_OP_CHOICE, %s, %s }", poffset, tname);
|
add_line(temp, "{ A1_OP_CHOICE, %s, %s }", poffset, tname);
|
||||||
|
|
||||||
|
while (decorate_type(basetype, &deco, &more_deco)) {
|
||||||
|
char *poffset2;
|
||||||
|
|
||||||
|
poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct);
|
||||||
|
|
||||||
|
if (deco.ext && deco.heim_object) {
|
||||||
|
add_line_string(temp, "0", poffset2,
|
||||||
|
"A1_OP_TYPE_DECORATE_EXTERN |A1_FLAG_HEIM_OBJ");
|
||||||
|
} else if (deco.ext) {
|
||||||
|
char *ptr = NULL;
|
||||||
|
|
||||||
|
/* Decorated with external C type */
|
||||||
|
if (asprintf(&ptr, "&asn1_extern_%s_%s",
|
||||||
|
basetype, deco.field_name) == -1 || ptr == NULL)
|
||||||
|
err(1, "out of memory");
|
||||||
|
add_line_pointer(temp, ptr, poffset2,
|
||||||
|
"A1_OP_TYPE_DECORATE_EXTERN %s",
|
||||||
|
deco.opt ? "|A1_FLAG_OPTIONAL" : "");
|
||||||
|
free(ptr);
|
||||||
|
} else
|
||||||
|
/* Decorated with a templated ASN.1 type */
|
||||||
|
add_line_pointer(temp, deco.field_type, poffset2,
|
||||||
|
"A1_OP_TYPE_DECORATE %s",
|
||||||
|
deco.opt ? "|A1_FLAG_OPTIONAL" : "");
|
||||||
|
free(poffset2);
|
||||||
|
free(deco.field_type);
|
||||||
|
}
|
||||||
|
|
||||||
free(e);
|
free(e);
|
||||||
free(tname);
|
free(tname);
|
||||||
break;
|
break;
|
||||||
|
@@ -296,4 +296,14 @@ TESTNotDecorated ::= SEQUENCE {
|
|||||||
-- should have the same encoding as TESTDecorated
|
-- should have the same encoding as TESTDecorated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TESTDecoratedChoice ::= CHOICE {
|
||||||
|
version TESTuint32
|
||||||
|
-- gets decorated with varius fields (see test.opt)
|
||||||
|
}
|
||||||
|
|
||||||
|
TESTNotDecoratedChoice ::= CHOICE {
|
||||||
|
version TESTuint32
|
||||||
|
-- should have the same encoding as TESTDecoratedChoice
|
||||||
|
}
|
||||||
|
|
||||||
END
|
END
|
||||||
|
@@ -3,3 +3,7 @@
|
|||||||
--decorate=TESTDecorated:my_vers:version3:my_copy_vers:my_free_vers:"check-gen.h"
|
--decorate=TESTDecorated:my_vers:version3:my_copy_vers:my_free_vers:"check-gen.h"
|
||||||
--decorate=TESTDecorated:void *:privthing
|
--decorate=TESTDecorated:void *:privthing
|
||||||
--decorate=TESTDecorated:heim_object_t:privobj
|
--decorate=TESTDecorated:heim_object_t:privobj
|
||||||
|
--decorate=TESTDecoratedChoice:TESTuint32:version2?
|
||||||
|
--decorate=TESTDecoratedChoice:my_vers:version3:my_copy_vers:my_free_vers:"check-gen.h"
|
||||||
|
--decorate=TESTDecoratedChoice:void *:privthing
|
||||||
|
--decorate=TESTDecoratedChoice:heim_object_t:privobj
|
||||||
|
Reference in New Issue
Block a user