asn1: Expand decoration w/ C types
This commits allows `heim_object_t` as a type and causes the generated code to use the `heim_retain()` and `heim_release()` functions for copying and releasing values of such types. Also, now one can have more than one decoration per-type.
This commit is contained in:
@@ -28,6 +28,7 @@ libasn1_la_LIBADD = \
|
|||||||
libasn1template_la_LIBADD = \
|
libasn1template_la_LIBADD = \
|
||||||
libasn1base.la \
|
libasn1base.la \
|
||||||
@LIB_com_err@ \
|
@LIB_com_err@ \
|
||||||
|
$(LIB_heimbase) \
|
||||||
$(LIBADD_roken)
|
$(LIBADD_roken)
|
||||||
|
|
||||||
BUILT_SOURCES = \
|
BUILT_SOURCES = \
|
||||||
@@ -188,10 +189,12 @@ check_timegm_LDADD = $(check_der_LDADD)
|
|||||||
|
|
||||||
check_gen_template_LDADD = \
|
check_gen_template_LDADD = \
|
||||||
libasn1template.la \
|
libasn1template.la \
|
||||||
|
$(LIB_heimbase) \
|
||||||
$(LIB_roken)
|
$(LIB_roken)
|
||||||
|
|
||||||
check_gen_LDADD = \
|
check_gen_LDADD = \
|
||||||
libasn1template.la \
|
libasn1template.la \
|
||||||
|
$(LIB_heimbase) \
|
||||||
$(LIB_roken)
|
$(LIB_roken)
|
||||||
|
|
||||||
check_ber_LDADD = $(check_gen_LDADD)
|
check_ber_LDADD = $(check_gen_LDADD)
|
||||||
|
@@ -14,7 +14,7 @@ annotations](/lib/asn1/README-X681.md).
|
|||||||
5. [Limitations](#Limitations)
|
5. [Limitations](#Limitations)
|
||||||
6. [Compiler Usage](#Compiler-usage)
|
6. [Compiler Usage](#Compiler-usage)
|
||||||
7. [APIs Generated by the Compiler](#APIs-generated-by-the-compiler)
|
7. [APIs Generated by the Compiler](#APIs-generated-by-the-compiler)
|
||||||
8. [asn1_print Usage](#asn1_print-usage)
|
8. [`asn1_print` Usage](#asn1_print-usage)
|
||||||
9. [Implementation](#implementation)
|
9. [Implementation](#implementation)
|
||||||
10. [Moving From C](#moving-from-c)
|
10. [Moving From C](#moving-from-c)
|
||||||
|
|
||||||
@@ -166,11 +166,14 @@ In recent times the following features have been added:
|
|||||||
- Automatic open type traversal, using a subset of X.681/X.682/X.683 for
|
- Automatic open type traversal, using a subset of X.681/X.682/X.683 for
|
||||||
expressing the requisite metadata.
|
expressing the requisite metadata.
|
||||||
|
|
||||||
|
- Decoration of ASN.1 types with "hidden" fields (ones that don't get encoded
|
||||||
|
or decoded) of ASN.1 or C types.
|
||||||
|
|
||||||
## Futures
|
## Futures
|
||||||
|
|
||||||
- JER support?
|
- JER support?
|
||||||
|
|
||||||
- XDR/OER support?
|
- XDR/NDR/OER support?
|
||||||
|
|
||||||
- Generate comparators? (lib/hx509 has a half-baked Certificate comparator)
|
- Generate comparators? (lib/hx509 has a half-baked Certificate comparator)
|
||||||
|
|
||||||
@@ -181,6 +184,10 @@ 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
|
||||||
|
not stable yet). This enables analysis using, e.g., `jq` or similar, and
|
||||||
|
even construction of alternative compilers using `jq` or similar.
|
||||||
|
|
||||||
- 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:
|
||||||
|
|
||||||
@@ -781,9 +788,9 @@ In recent times the following features have been added:
|
|||||||
We'll fix this eventually.)
|
We'll fix this eventually.)
|
||||||
|
|
||||||
- Unconstrained integer types have a large integer representation in C that is
|
- Unconstrained integer types have a large integer representation in C that is
|
||||||
not terribly useful in common cases. Range constraints on integer types
|
not terribly useful in common cases. Range and member constraints on
|
||||||
cause the compiler to use `int32_t`, `int64_t`, `uint32_t`, and/or
|
integer types cause the compiler to use `int`, `int64_t`, `unsigned int`,
|
||||||
`uint64_t`.
|
and/or `uint64_t` as appropriate.
|
||||||
|
|
||||||
- The Heimdal ASN.1 compiler currently handles a large subset of X.680, and
|
- 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
|
(in a branch) a small subset of X.681, X.682, and X.683, which manifests as
|
||||||
@@ -800,7 +807,7 @@ In recent times the following features have been added:
|
|||||||
JER this will have the side-effect of printing the wrong type names in some
|
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.)
|
cases because two or more types have the same templates and get deduped.)
|
||||||
|
|
||||||
- There is an _experimental_ ASN.1 -> JSON feature in the compiler. It
|
- 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
|
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
|
definitions. Even for types, it is not complete, and the JSON schema used
|
||||||
is subject to change *WITHOUT NOTICE*.
|
is subject to change *WITHOUT NOTICE*.
|
||||||
@@ -813,7 +820,8 @@ In recent times the following features have been added:
|
|||||||
|
|
||||||
## Limitations
|
## Limitations
|
||||||
|
|
||||||
- `asn1_print`'s JSON support is not X.697 (JER) compatible.
|
- `libasn1`'s and, therefore, `asn1_print`'s JSON support is not X.697 (JER)
|
||||||
|
compatible.
|
||||||
|
|
||||||
- Control over C types generated is very limited, mainly only for integer
|
- Control over C types generated is very limited, mainly only for integer
|
||||||
types.
|
types.
|
||||||
@@ -839,6 +847,12 @@ In recent times the following features have been added:
|
|||||||
values of `SET`, `SEQUENCE`, `SET OF`, and `SEQUENCE OF`), is not supported.
|
values of `SET`, `SEQUENCE`, `SET OF`, and `SEQUENCE OF`), is not supported.
|
||||||
Values of `CHOICE` types are also not supported.
|
Values of `CHOICE` types are also not supported.
|
||||||
|
|
||||||
|
- There is no way to substitute object sets at run-time. This means that
|
||||||
|
automatic decoding through open types will spend more CPU cycles than the
|
||||||
|
application might want, by decoding more types than the application might
|
||||||
|
care about. The ability to substitute object sets at run-time would require
|
||||||
|
a change to the APIs generated.
|
||||||
|
|
||||||
- ...
|
- ...
|
||||||
|
|
||||||
## Compiler Usage
|
## Compiler Usage
|
||||||
@@ -871,11 +885,8 @@ SYNOPSIS
|
|||||||
asn1_compile [--template] [--prefix-enum] [--enum-prefix=PREFIX]
|
asn1_compile [--template] [--prefix-enum] [--enum-prefix=PREFIX]
|
||||||
[--encode-rfc1510-bit-string] [--decode-dce-ber]
|
[--encode-rfc1510-bit-string] [--decode-dce-ber]
|
||||||
[--support-ber] [--preserve-binary=TYPE] [--sequence=TYPE]
|
[--support-ber] [--preserve-binary=TYPE] [--sequence=TYPE]
|
||||||
[--decorate=TYPE:FTYPE:fname[?]]
|
[--decorate=DECORATION] [--one-code-file] [--gen-name=NAME]
|
||||||
[--decorate=TYPE:void:fname:::]
|
[--option-file=FILE] [--original-order] [--no-parse-units]
|
||||||
[--decorate=TYPE:FTYPE:fname[?]:[copyfn]:[freefn]:header]
|
|
||||||
[--one-code-file] [--gen-name=NAME] [--option-file=FILE]
|
|
||||||
[--original-order] [--no-parse-units]
|
|
||||||
[--type-file=C-HEADER-FILE] [--version] [--help]
|
[--type-file=C-HEADER-FILE] [--version] [--help]
|
||||||
[FILE.asn1 [NAME]]
|
[FILE.asn1 [NAME]]
|
||||||
|
|
||||||
@@ -883,19 +894,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.
|
||||||
|
|
||||||
@@ -907,7 +918,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.
|
||||||
|
|
||||||
@@ -934,7 +945,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.
|
||||||
@@ -956,19 +967,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
|
||||||
@@ -1000,54 +1011,48 @@ DESCRIPTION
|
|||||||
Generate add/remove functions for the named ASN.1 TYPE which must
|
Generate add/remove functions for the named ASN.1 TYPE which must
|
||||||
be a ‘SET OF’ or ‘SEQUENCE OF’ type.
|
be a ‘SET OF’ or ‘SEQUENCE OF’ type.
|
||||||
|
|
||||||
--decorate=TYPE:FTYPE:fname[?]
|
--decorate=ASN1-TYPE:FIELD-ASN1-TYPE:fname[?]
|
||||||
Add to the C struct generated for the given ASN.1 type named TYPE
|
Add to the C struct generated for the given ASN.1 SET or SEQUENCE
|
||||||
a “hidden” field named fname of the given ASN.1 type FTYPE, but
|
type named ASN1-TYPE a “hidden” field named fname of the given
|
||||||
do not encode or decode it. The TYPE must be a SET or SEQUENCE
|
ASN.1 type FIELD-ASN1-TYPE, but do not encode or decode it. If
|
||||||
type. If the fname ends in a question mark, then treat the field
|
the fname ends in a question mark, then treat the field as OP-
|
||||||
as OPTIONAL.
|
TIONAL.
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
--decorate=TYPE:void:fname:::
|
--decorate=ASN1-TYPE:heim_object_t:fname
|
||||||
Add to the C struct generated for the given ASN.1 type named TYPE
|
Add to the C struct generated for the given ASN.1 SET or SEQUENCE
|
||||||
a “hidden” field named fname of type ‘void *’ (but do not encode
|
type named ASN1-TYPE a “hidden” field named fname of C type
|
||||||
or decode it.
|
‘heim_object_t’ values of which will be copied and released with
|
||||||
|
‘heim_release()’ and ‘heim_retain()’ respectively.
|
||||||
|
|
||||||
|
--decorate=ASN1-TYPE:void*:fname
|
||||||
|
Add to the C struct generated for the given ASN.1 SET or SEQUENCE
|
||||||
|
type named ASN1-TYPE a “hidden” field named fname of 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 TYPE will set this field to the ‘NULL’ pointer.
|
compiler for ASN1-TYPE will set this field to the ‘NULL’ pointer.
|
||||||
|
|
||||||
This is useful for adding fields to existing types that can be
|
--decorate=ASN1-TYPE:FIELD-C-TYPE:fname[?]:[copyfn]:[freefn]:header
|
||||||
used for internal bookkeeping but which do not affect interoper‐
|
Add to the C struct generated for the given ASN.1 SET or SEQUENCE
|
||||||
ability because they are neither encoded nor decoded. For exam‐
|
type named ASN1-TYPE a “hidden” field named fname of the given
|
||||||
ple, one might decorate a request type with state needed during
|
external C type FIELD-C-TYPE, declared in the given header but do
|
||||||
processing of the request.
|
not encode or decode this field. If the fname ends in a question
|
||||||
|
mark, then treat the field as OPTIONAL.
|
||||||
--decorate=TYPE:FTYPE:fname[?]:copyfn:freefn:header
|
|
||||||
Add to the C struct generated for the given ASN.1 type named TYPE
|
|
||||||
a “hidden” field named fname of the given external C type FTYPE,
|
|
||||||
declared in the given header but do not encode or decode this
|
|
||||||
field. The TYPE must be a SET or SEQUENCE type. If the fname
|
|
||||||
ends in a question mark, then treat the field as OPTIONAL.
|
|
||||||
|
|
||||||
This is useful for adding fields to existing types that can be
|
|
||||||
used for internal bookkeeping but which do not affect interoper‐
|
|
||||||
ability because they are neither encoded nor decoded. For exam‐
|
|
||||||
ple, one might decorate a request type with state needed during
|
|
||||||
processing of the request.
|
|
||||||
|
|
||||||
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).
|
||||||
|
|
||||||
@@ -1069,7 +1074,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
|
||||||
@@ -1085,9 +1090,7 @@ DESCRIPTION
|
|||||||
--help
|
--help
|
||||||
|
|
||||||
NOTES
|
NOTES
|
||||||
Note that only one decoration per-SET/SEQUENCE type may be specified.
|
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.
|
||||||
|
|
||||||
@@ -1303,13 +1306,19 @@ See:
|
|||||||
|
|
||||||
- Add JER support so we can convert between JER and DER?
|
- Add JER support so we can convert between JER and DER?
|
||||||
|
|
||||||
- Add XDR support?
|
- Add XDR support? There are no ASN.1 Encoding Rules based on XDR, but it is
|
||||||
|
trivial to construct such for at least that subset of ASN.1 for which the
|
||||||
|
XDR syntax has equivalent semantics.
|
||||||
|
|
||||||
- Add OER support?
|
- Add OER support?
|
||||||
|
|
||||||
- Add NDR support?
|
- Add NDR support? There are no ASN.1 Encoding Rules based on NDR, but it is
|
||||||
|
trivial to construct such for at least that subset of ASN.1 for which the
|
||||||
|
IDL syntax has equivalent semantics.
|
||||||
|
|
||||||
- Perhaps third parties will contribute more control over generate types?
|
- Perhaps third parties will contribute more control over generated types?
|
||||||
|
This may require separate publication of the Heimdal ASN.1 compiler from the
|
||||||
|
rest of Heimdal.
|
||||||
|
|
||||||
## Moving From C
|
## Moving From C
|
||||||
|
|
||||||
|
@@ -150,6 +150,7 @@
|
|||||||
#define A1_FLAG_OPTIONAL (0x01000000)
|
#define A1_FLAG_OPTIONAL (0x01000000)
|
||||||
#define A1_FLAG_IMPLICIT (0x02000000)
|
#define A1_FLAG_IMPLICIT (0x02000000)
|
||||||
#define A1_FLAG_DEFAULT (0x04000000)
|
#define A1_FLAG_DEFAULT (0x04000000)
|
||||||
|
#define A1_FLAG_HEIM_OBJ (0x08000000)
|
||||||
|
|
||||||
#define A1_TAG_T(CLASS,TYPE,TAG) ((A1_OP_TAG) | (((CLASS) << 22) | ((TYPE) << 21) | (TAG)))
|
#define A1_TAG_T(CLASS,TYPE,TAG) ((A1_OP_TAG) | (((CLASS) << 22) | ((TYPE) << 21) | (TAG)))
|
||||||
#define A1_TAG_CLASS(x) (((x) >> 22) & 0x3)
|
#define A1_TAG_CLASS(x) (((x) >> 22) & 0x3)
|
||||||
|
@@ -48,9 +48,7 @@
|
|||||||
.Op Fl Fl support-ber
|
.Op Fl Fl support-ber
|
||||||
.Op Fl Fl preserve-binary=TYPE
|
.Op Fl Fl preserve-binary=TYPE
|
||||||
.Op Fl Fl sequence=TYPE
|
.Op Fl Fl sequence=TYPE
|
||||||
.Op Fl Fl decorate=TYPE:FTYPE:fname[?]
|
.Op Fl Fl decorate=DECORATION
|
||||||
.Op Fl Fl decorate=TYPE:void:fname:::
|
|
||||||
.Op Fl Fl decorate=TYPE:FTYPE:fname[?]:[copyfn]:[freefn]:header
|
|
||||||
.Op Fl Fl one-code-file
|
.Op Fl Fl one-code-file
|
||||||
.Op Fl Fl gen-name=NAME
|
.Op Fl Fl gen-name=NAME
|
||||||
.Op Fl Fl option-file=FILE
|
.Op Fl Fl option-file=FILE
|
||||||
@@ -240,19 +238,17 @@ which must be a
|
|||||||
or
|
or
|
||||||
.Sq SEQUENCE OF
|
.Sq SEQUENCE OF
|
||||||
type.
|
type.
|
||||||
.It Fl Fl decorate=TYPE:FTYPE:fname[?]
|
.It Fl Fl decorate=ASN1-TYPE:FIELD-ASN1-TYPE:fname[?]
|
||||||
Add to the C struct generated for the given ASN.1 type named
|
Add to the C struct generated for the given ASN.1 SET or SEQUENCE type
|
||||||
.Ar TYPE
|
named
|
||||||
|
.Ar ASN1-TYPE
|
||||||
a
|
a
|
||||||
.Dq hidden
|
.Dq hidden
|
||||||
field named
|
field named
|
||||||
.Ar fname
|
.Ar fname
|
||||||
of the given ASN.1 type
|
of the given ASN.1 type
|
||||||
.Ar FTYPE ,
|
.Ar FIELD-ASN1-TYPE ,
|
||||||
but do not encode or decode it.
|
but do not encode or decode it.
|
||||||
The
|
|
||||||
.Ar TYPE
|
|
||||||
must be a SET or SEQUENCE type.
|
|
||||||
If the
|
If the
|
||||||
.Ar fname
|
.Ar fname
|
||||||
ends in a question mark, then treat the field as OPTIONAL.
|
ends in a question mark, then treat the field as OPTIONAL.
|
||||||
@@ -262,9 +258,25 @@ used for internal bookkeeping but which do not affect
|
|||||||
interoperability because they are neither encoded nor decoded.
|
interoperability because they are neither encoded nor decoded.
|
||||||
For example, one might decorate a request type with state needed
|
For example, one might decorate a request type with state needed
|
||||||
during processing of the request.
|
during processing of the request.
|
||||||
.It Fl Fl decorate=TYPE:void:fname:::
|
.It Fl Fl decorate=ASN1-TYPE:heim_object_t:fname
|
||||||
Add to the C struct generated for the given ASN.1 type named
|
Add to the C struct generated for the given ASN.1 SET or SEQUENCE type
|
||||||
.Ar TYPE
|
named
|
||||||
|
.Ar ASN1-TYPE
|
||||||
|
a
|
||||||
|
.Dq hidden
|
||||||
|
field named
|
||||||
|
.Ar fname
|
||||||
|
of C type
|
||||||
|
.Sq heim_object_t
|
||||||
|
values of which will be copied and released with
|
||||||
|
.Sq heim_retain()
|
||||||
|
and
|
||||||
|
.Sq heim_release()
|
||||||
|
respectively.
|
||||||
|
.It Fl Fl decorate=ASN1-TYPE:void*:fname
|
||||||
|
Add to the C struct generated for the given ASN.1 SET or SEQUENCE type
|
||||||
|
named
|
||||||
|
.Ar ASN1-TYPE
|
||||||
a
|
a
|
||||||
.Dq hidden
|
.Dq hidden
|
||||||
field named
|
field named
|
||||||
@@ -275,41 +287,27 @@ of type
|
|||||||
.Pp
|
.Pp
|
||||||
The destructor and copy constructor functions generated by this
|
The destructor and copy constructor functions generated by this
|
||||||
compiler for
|
compiler for
|
||||||
.Ar TYPE
|
.Ar ASN1-TYPE
|
||||||
will set this field to the
|
will set this field to the
|
||||||
.Sq NULL
|
.Sq NULL
|
||||||
pointer.
|
pointer.
|
||||||
.Pp
|
.It Fl Fl decorate=ASN1-TYPE:FIELD-C-TYPE:fname[?]:[copyfn]:[freefn]:header
|
||||||
This is useful for adding fields to existing types that can be
|
Add to the C struct generated for the given ASN.1 SET or SEQUENCE type
|
||||||
used for internal bookkeeping but which do not affect
|
named
|
||||||
interoperability because they are neither encoded nor decoded.
|
.Ar ASN1-TYPE
|
||||||
For example, one might decorate a request type with state needed
|
|
||||||
during processing of the request.
|
|
||||||
.It Fl Fl decorate=TYPE:FTYPE:fname[?]:copyfn:freefn:header
|
|
||||||
Add to the C struct generated for the given ASN.1 type named
|
|
||||||
.Ar TYPE
|
|
||||||
a
|
a
|
||||||
.Dq hidden
|
.Dq hidden
|
||||||
field named
|
field named
|
||||||
.Ar fname
|
.Ar fname
|
||||||
of the given external C type
|
of the given external C type
|
||||||
.Ar FTYPE ,
|
.Ar FIELD-C-TYPE ,
|
||||||
declared in the given
|
declared in the given
|
||||||
.Ar header
|
.Ar header
|
||||||
but do not encode or decode this field.
|
but do not encode or decode this field.
|
||||||
The
|
|
||||||
.Ar TYPE
|
|
||||||
must be a SET or SEQUENCE type.
|
|
||||||
If the
|
If the
|
||||||
.Ar fname
|
.Ar fname
|
||||||
ends in a question mark, then treat the field as OPTIONAL.
|
ends in a question mark, then treat the field as OPTIONAL.
|
||||||
.Pp
|
.Pp
|
||||||
This is useful for adding fields to existing types that can be
|
|
||||||
used for internal bookkeeping but which do not affect
|
|
||||||
interoperability because they are neither encoded nor decoded.
|
|
||||||
For example, one might decorate a request type with state needed
|
|
||||||
during processing of the request.
|
|
||||||
.Pp
|
|
||||||
The
|
The
|
||||||
.Ar header
|
.Ar header
|
||||||
must include double quotes or angle brackets.
|
must include double quotes or angle brackets.
|
||||||
@@ -364,9 +362,6 @@ for common type defintions.
|
|||||||
.It Fl Fl help
|
.It Fl Fl help
|
||||||
.El
|
.El
|
||||||
.Sh NOTES
|
.Sh NOTES
|
||||||
Note that only one decoration per-SET/SEQUENCE type may be
|
|
||||||
specified.
|
|
||||||
.Pp
|
|
||||||
Currently only the template backend supports automatic encoding
|
Currently only the template backend supports automatic encoding
|
||||||
and decoding of open types via the ASN.1 Information Object
|
and decoding of open types via the ASN.1 Information Object
|
||||||
System and X.681/X.682/X.683 annotations.
|
System and X.681/X.682/X.683 annotations.
|
||||||
|
@@ -1039,18 +1039,18 @@ static int
|
|||||||
test_decorated(void)
|
test_decorated(void)
|
||||||
{
|
{
|
||||||
TESTNotDecorated tnd;
|
TESTNotDecorated tnd;
|
||||||
TESTDecorated3 td3, td3_copy;
|
|
||||||
TESTDecorated2 td2, td2_copy;
|
|
||||||
TESTDecorated td, td_copy;
|
TESTDecorated td, td_copy;
|
||||||
size_t len, size;
|
size_t len, size;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
memset(&td, 0, sizeof(td));
|
memset(&td, 0, sizeof(td));
|
||||||
memset(&td2, 0, sizeof(td2));
|
|
||||||
memset(&tnd, 0, sizeof(tnd));
|
memset(&tnd, 0, sizeof(tnd));
|
||||||
|
|
||||||
td.version = 3;
|
td.version = 3;
|
||||||
|
td.version3.v = 5;
|
||||||
|
td.privthing = &td;
|
||||||
|
td.privobj = heim_string_create("foo");
|
||||||
if ((td.version2 = malloc(sizeof(*td.version2))) == NULL)
|
if ((td.version2 = malloc(sizeof(*td.version2))) == NULL)
|
||||||
errx(1, "out of memory");
|
errx(1, "out of memory");
|
||||||
*td.version2 = 5;
|
*td.version2 = 5;
|
||||||
@@ -1085,90 +1085,35 @@ 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) {
|
||||||
|
warnx("copy_TESTDecorated() did not work correctly (3)");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (td_copy.privthing != 0) {
|
||||||
|
warnx("copy_TESTDecorated() did not work correctly (4)");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (td_copy.privobj != td.privobj) {
|
||||||
|
warnx("copy_TESTDecorated() did not work correctly (5)");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
free_TESTDecorated(&td_copy);
|
free_TESTDecorated(&td_copy);
|
||||||
free_TESTDecorated(&td);
|
free_TESTDecorated(&td);
|
||||||
if (td.version2) {
|
if (td.version2) {
|
||||||
warnx("free_TESTDecorated() did not work correctly");
|
warnx("free_TESTDecorated() did not work correctly (1)");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
if (td.version3.v != 0 || my_free_vers_called != 2) {
|
||||||
td2.version = 3;
|
warnx("free_TESTDecorated() did not work correctly (2)");
|
||||||
td2.version2.v = 5;
|
|
||||||
ASN1_MALLOC_ENCODE(TESTDecorated2, ptr, len, &td2, &size, ret);
|
|
||||||
if (ret) {
|
|
||||||
warnx("could not encode a TESTDecorated2 struct");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
ret = decode_TESTNotDecorated(ptr, len, &tnd, &size);
|
if (td.privthing != 0) {
|
||||||
if (ret) {
|
warnx("free_TESTDecorated() did not work correctly (3)");
|
||||||
warnx("could not decode a TESTDecorated2 struct as TESTNotDecorated2");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
free(ptr);
|
if (td.privobj != 0) {
|
||||||
if (size != len) {
|
warnx("free_TESTDecorated() did not work correctly (4)");
|
||||||
warnx("TESTDecorated2 encoded size mismatch");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (td2.version != tnd.version) {
|
|
||||||
warnx("TESTDecorated2 did not decode as a TESTNotDecorated correctly");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (copy_TESTDecorated2(&td2, &td2_copy)) {
|
|
||||||
warnx("copy_TESTDecorated2() failed");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (td2.version != td2_copy.version || !my_copy_vers_called) {
|
|
||||||
warnx("copy_TESTDecorated2() did not work correctly (1)");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (td2.version2.v != td2_copy.version2.v) {
|
|
||||||
warnx("copy_TESTDecorated2() did not work correctly (2)");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
free_TESTDecorated2(&td2_copy);
|
|
||||||
free_TESTDecorated2(&td2);
|
|
||||||
if (td2.version2.v != 0 || my_free_vers_called != 2) {
|
|
||||||
warnx("free_TESTDecorated2() did not work correctly");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
td3.version = 3;
|
|
||||||
td3.privthing = &td;
|
|
||||||
ASN1_MALLOC_ENCODE(TESTDecorated3, ptr, len, &td3, &size, ret);
|
|
||||||
if (ret) {
|
|
||||||
warnx("could not encode a TESTDecorated3 struct");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
ret = decode_TESTNotDecorated(ptr, len, &tnd, &size);
|
|
||||||
if (ret) {
|
|
||||||
warnx("could not decode a TESTDecorated3 struct as TESTNotDecorated3");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
free(ptr);
|
|
||||||
if (size != len) {
|
|
||||||
warnx("TESTDecorated3 encoded size mismatch");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (td3.version != tnd.version) {
|
|
||||||
warnx("TESTDecorated3 did not decode as a TESTNotDecorated correctly");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (copy_TESTDecorated3(&td3, &td3_copy)) {
|
|
||||||
warnx("copy_TESTDecorated3() failed");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (td3.version != td3_copy.version) {
|
|
||||||
warnx("copy_TESTDecorated3() did not work correctly (1)");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (td3_copy.privthing != 0) {
|
|
||||||
warnx("copy_TESTDecorated3() did not work correctly (2)");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
free_TESTDecorated3(&td3_copy);
|
|
||||||
free_TESTDecorated3(&td3);
|
|
||||||
if (td3.privthing != 0) {
|
|
||||||
warnx("free_TESTDecorated3() did not work correctly");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@@ -1366,12 +1366,13 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t
|
|||||||
case TSequence: {
|
case TSequence: {
|
||||||
Member *m;
|
Member *m;
|
||||||
struct decoration deco;
|
struct decoration deco;
|
||||||
|
ssize_t more_deco = -1;
|
||||||
|
int decorated = 0;
|
||||||
|
|
||||||
getnewbasename(&newbasename, typedefp || level == 0, basename, name);
|
getnewbasename(&newbasename, typedefp || level == 0, basename, name);
|
||||||
|
|
||||||
space(level);
|
space(level);
|
||||||
|
|
||||||
(void) decorate_type(newbasename, &deco);
|
|
||||||
fprintf (headerfile, "struct %s {\n", newbasename);
|
fprintf (headerfile, "struct %s {\n", newbasename);
|
||||||
fprintf(jsonfile, "\"ttype\":\"%s\",\"extensible\":%s,"
|
fprintf(jsonfile, "\"ttype\":\"%s\",\"extensible\":%s,"
|
||||||
"\"ctype\":\"struct %s\"",
|
"\"ctype\":\"struct %s\"",
|
||||||
@@ -1408,19 +1409,34 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t
|
|||||||
fprintf(jsonfile, ",\"opentype\":");
|
fprintf(jsonfile, ",\"opentype\":");
|
||||||
define_open_type(level, newbasename, name, basename, t, t);
|
define_open_type(level, newbasename, name, basename, t, t);
|
||||||
}
|
}
|
||||||
if (deco.decorated) {
|
while (decorate_type(newbasename, &deco, &more_deco)) {
|
||||||
|
decorated++;
|
||||||
space(level + 1);
|
space(level + 1);
|
||||||
fprintf(headerfile, "%s %s%s;\n", deco.field_type,
|
fprintf(headerfile, "%s %s%s;\n", deco.field_type,
|
||||||
deco.opt ? "*" : "", deco.field_name);
|
deco.opt ? "*" : "", deco.field_name);
|
||||||
fprintf(jsonfile, ",\"decorate\":{"
|
if (deco.first)
|
||||||
|
fprintf(jsonfile, ",\"decorate\":[");
|
||||||
|
fprintf(jsonfile, "%s{"
|
||||||
"\"type\":\"%s\",\"name\":\"%s\",\"optional\":%s,"
|
"\"type\":\"%s\",\"name\":\"%s\",\"optional\":%s,"
|
||||||
"\"external\":%s,\"copy_function\":\"%s\","
|
"\"external\":%s,\"pointer\":%s,\"void_star\":%s,"
|
||||||
"\"free_function\":\"%s\",\"header_name\":\"%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.field_type, deco.field_name,
|
||||||
deco.opt ? "true" : "false", deco.ext ? "true" : "false",
|
deco.opt ? "true" : "false", deco.ext ? "true" : "false",
|
||||||
deco.copy_function_name, deco.free_function_name,
|
deco.ptr ? "true" : "false", deco.void_star ? "true" : "false",
|
||||||
deco.header_name);
|
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);
|
||||||
free(deco.field_type);
|
free(deco.field_type);
|
||||||
@@ -1637,13 +1653,13 @@ declare_type(const Symbol *s, Type *t, int typedefp)
|
|||||||
case TSet:
|
case TSet:
|
||||||
case TSequence: {
|
case TSequence: {
|
||||||
struct decoration deco;
|
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);
|
||||||
if (decorate_type(newbasename, &deco) && deco.header_name
|
while (decorate_type(newbasename, &deco, &more_deco)) {
|
||||||
&& !deco.void_star
|
if (deco.header_name)
|
||||||
&& deco.header_name[0]) {
|
fprintf(headerfile, "#include %s\n", deco.header_name);
|
||||||
fprintf(headerfile, "#include %s\n", deco.header_name);
|
|
||||||
free(deco.field_type);
|
free(deco.field_type);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1782,6 +1798,7 @@ static void
|
|||||||
generate_type_header (const Symbol *s)
|
generate_type_header (const Symbol *s)
|
||||||
{
|
{
|
||||||
Type *t = s->type;
|
Type *t = s->type;
|
||||||
|
|
||||||
if (!s->type)
|
if (!s->type)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -1850,6 +1867,7 @@ generate_type_header (const Symbol *s)
|
|||||||
if (is_export(s->name))
|
if (is_export(s->name))
|
||||||
fprintf(symsfile, "ASN1_SYM_TYPE(\"%s\", \"%s\", %s)\n",
|
fprintf(symsfile, "ASN1_SYM_TYPE(\"%s\", \"%s\", %s)\n",
|
||||||
s->name, s->gen_name, s->gen_name);
|
s->name, s->gen_name, s->gen_name);
|
||||||
|
|
||||||
fprintf(headerfile, "typedef ");
|
fprintf(headerfile, "typedef ");
|
||||||
define_type(0, s->gen_name, s->gen_name, NULL, s->type, TRUE,
|
define_type(0, s->gen_name, s->gen_name, NULL, s->type, TRUE,
|
||||||
preserve_type(s->name) ? TRUE : FALSE);
|
preserve_type(s->name) ? TRUE : FALSE);
|
||||||
|
@@ -229,6 +229,7 @@ void
|
|||||||
generate_type_copy (const Symbol *s)
|
generate_type_copy (const Symbol *s)
|
||||||
{
|
{
|
||||||
struct decoration deco;
|
struct decoration deco;
|
||||||
|
ssize_t more_deco = -1;
|
||||||
int preserve = preserve_type(s->name) ? TRUE : FALSE;
|
int preserve = preserve_type(s->name) ? TRUE : FALSE;
|
||||||
int save_used_fail = used_fail;
|
int save_used_fail = used_fail;
|
||||||
|
|
||||||
@@ -240,19 +241,20 @@ generate_type_copy (const Symbol *s)
|
|||||||
"memset(to, 0, sizeof(*to));\n",
|
"memset(to, 0, sizeof(*to));\n",
|
||||||
s->gen_name, s->gen_name, s->gen_name);
|
s->gen_name, s->gen_name, s->gen_name);
|
||||||
copy_type ("from", "to", s->type, preserve);
|
copy_type ("from", "to", s->type, preserve);
|
||||||
if (decorate_type(s->gen_name, &deco)) {
|
while (decorate_type(s->gen_name, &deco, &more_deco)) {
|
||||||
if (deco.ext &&
|
if (deco.heim_object) {
|
||||||
(deco.copy_function_name == NULL ||
|
fprintf(codefile, "(to)->%s = heim_retain((from)->%s);\n",
|
||||||
deco.copy_function_name[0] == '\0')) {
|
deco.field_name, deco.field_name);
|
||||||
|
} else if (deco.ext && deco.copy_function_name == NULL) {
|
||||||
/* Decorated with field of external type but no copy function */
|
/* Decorated with field of external type but no copy function */
|
||||||
if (deco.opt || deco.void_star)
|
if (deco.ptr)
|
||||||
fprintf(codefile, "(to)->%s = 0;\n", deco.field_name);
|
fprintf(codefile, "(to)->%s = 0;\n", deco.field_name);
|
||||||
else
|
else
|
||||||
fprintf(codefile, "memset(&(to)->%s, 0, sizeof((to)->%s));\n",
|
fprintf(codefile, "memset(&(to)->%s, 0, sizeof((to)->%s));\n",
|
||||||
deco.field_name, deco.field_name);
|
deco.field_name, deco.field_name);
|
||||||
} else if (deco.ext) {
|
} else if (deco.ext) {
|
||||||
/* Decorated with field of external type w/ copy function */
|
/* Decorated with field of external type w/ copy function */
|
||||||
if (deco.opt) {
|
if (deco.ptr) {
|
||||||
fprintf(codefile, "if (from->%s) {\n", deco.field_name);
|
fprintf(codefile, "if (from->%s) {\n", deco.field_name);
|
||||||
fprintf(codefile, "(to)->%s = malloc(sizeof(*(to)->%s));\n",
|
fprintf(codefile, "(to)->%s = malloc(sizeof(*(to)->%s));\n",
|
||||||
deco.field_name, deco.field_name);
|
deco.field_name, deco.field_name);
|
||||||
|
@@ -179,6 +179,7 @@ void
|
|||||||
generate_type_free (const Symbol *s)
|
generate_type_free (const Symbol *s)
|
||||||
{
|
{
|
||||||
struct decoration deco;
|
struct decoration deco;
|
||||||
|
ssize_t more_deco = -1;
|
||||||
int preserve = preserve_type(s->name) ? TRUE : FALSE;
|
int preserve = preserve_type(s->name) ? TRUE : FALSE;
|
||||||
|
|
||||||
fprintf (codefile, "void ASN1CALL\n"
|
fprintf (codefile, "void ASN1CALL\n"
|
||||||
@@ -187,12 +188,13 @@ generate_type_free (const Symbol *s)
|
|||||||
s->gen_name, s->gen_name);
|
s->gen_name, s->gen_name);
|
||||||
|
|
||||||
free_type ("data", s->type, preserve);
|
free_type ("data", s->type, preserve);
|
||||||
if (decorate_type(s->gen_name, &deco)) {
|
while (decorate_type(s->gen_name, &deco, &more_deco)) {
|
||||||
if (deco.ext &&
|
if (deco.heim_object) {
|
||||||
(deco.free_function_name == NULL ||
|
fprintf(codefile, "heim_retain((data)->%s);\n", deco.field_name);
|
||||||
deco.free_function_name[0] == '\0')) {
|
fprintf(codefile, "(data)->%s = 0;\n", deco.field_name);
|
||||||
|
} else if (deco.ext && deco.free_function_name == NULL) {
|
||||||
/* Decorated with field of external type but no free function */
|
/* Decorated with field of external type but no free function */
|
||||||
if (deco.opt || deco.void_star)
|
if (deco.ptr)
|
||||||
fprintf(codefile, "(data)->%s = 0;\n", deco.field_name);
|
fprintf(codefile, "(data)->%s = 0;\n", deco.field_name);
|
||||||
else
|
else
|
||||||
fprintf(codefile,
|
fprintf(codefile,
|
||||||
@@ -200,7 +202,7 @@ generate_type_free (const Symbol *s)
|
|||||||
deco.field_name, deco.field_name);
|
deco.field_name, deco.field_name);
|
||||||
} else if (deco.ext) {
|
} else if (deco.ext) {
|
||||||
/* Decorated with field of external type w/ free function */
|
/* Decorated with field of external type w/ free function */
|
||||||
if (deco.opt) {
|
if (deco.ptr) {
|
||||||
fprintf(codefile, "if ((data)->%s) {\n", deco.field_name);
|
fprintf(codefile, "if ((data)->%s) {\n", deco.field_name);
|
||||||
fprintf(codefile, "%s((data)->%s);\n",
|
fprintf(codefile, "%s((data)->%s);\n",
|
||||||
deco.free_function_name, deco.field_name);
|
deco.free_function_name, deco.field_name);
|
||||||
|
@@ -152,11 +152,15 @@ struct decoration {
|
|||||||
char *free_function_name; /* destructor function name */
|
char *free_function_name; /* destructor function name */
|
||||||
char *header_name; /* header name */
|
char *header_name; /* header name */
|
||||||
unsigned int decorated:1;
|
unsigned int decorated:1;
|
||||||
|
unsigned int first:1; /* optional */
|
||||||
unsigned int opt:1; /* optional */
|
unsigned int opt:1; /* optional */
|
||||||
unsigned int ext:1; /* external */
|
unsigned int ext:1; /* external */
|
||||||
|
unsigned int ptr:1; /* external, pointer */
|
||||||
unsigned int void_star:1; /* external, void * */
|
unsigned int void_star:1; /* external, void * */
|
||||||
|
unsigned int struct_star:1; /* external, struct foo * */
|
||||||
|
unsigned int heim_object:1; /* external, heim_object_t */
|
||||||
};
|
};
|
||||||
int decorate_type(const char *, struct decoration *);
|
int decorate_type(const char *, struct decoration *, ssize_t *);
|
||||||
|
|
||||||
void generate_header_of_codefile(const char *);
|
void generate_header_of_codefile(const char *);
|
||||||
void close_codefile(void);
|
void close_codefile(void);
|
||||||
|
@@ -459,7 +459,7 @@ add_line_pointer(struct templatehead *t,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add an entry to a template where the pointer firled is a string literal.
|
* Add an entry to a template where the pointer field is a string literal.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
add_line_string(struct templatehead *t,
|
add_line_string(struct templatehead *t,
|
||||||
@@ -1065,6 +1065,7 @@ template_members(struct templatehead *temp,
|
|||||||
Field *typeidfield = NULL;
|
Field *typeidfield = NULL;
|
||||||
Member *m;
|
Member *m;
|
||||||
struct decoration deco;
|
struct decoration deco;
|
||||||
|
ssize_t more_deco = -1;
|
||||||
size_t i = 0, typeididx = 0, opentypeidx = 0;
|
size_t i = 0, typeididx = 0, opentypeidx = 0;
|
||||||
int is_array_of_open_type = 0;
|
int is_array_of_open_type = 0;
|
||||||
|
|
||||||
@@ -1106,21 +1107,24 @@ template_members(struct templatehead *temp,
|
|||||||
typeidfield, opentypefield, opentypemember,
|
typeidfield, opentypefield, opentypemember,
|
||||||
is_array_of_open_type);
|
is_array_of_open_type);
|
||||||
|
|
||||||
if (decorate_type(basetype, &deco)) {
|
while (decorate_type(basetype, &deco, &more_deco)) {
|
||||||
char *poffset2;
|
char *poffset2;
|
||||||
|
|
||||||
poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct);
|
poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct);
|
||||||
|
|
||||||
if (deco.ext) {
|
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;
|
char *ptr = NULL;
|
||||||
|
|
||||||
/* Decorated with external C type */
|
/* Decorated with external C type */
|
||||||
if (asprintf(&ptr, "&asn1_extern_%s_%s",
|
if (asprintf(&ptr, "&asn1_extern_%s_%s",
|
||||||
basetype, deco.field_type) == -1 || ptr == NULL)
|
basetype, deco.field_name) == -1 || ptr == NULL)
|
||||||
err(1, "out of memory");
|
err(1, "out of memory");
|
||||||
add_line_pointer(temp, ptr, poffset2,
|
add_line_pointer(temp, ptr, poffset2,
|
||||||
"A1_OP_TYPE_DECORATE_EXTERN %s",
|
"A1_OP_TYPE_DECORATE_EXTERN %s",
|
||||||
deco.opt && !deco.void_star ? "|A1_FLAG_OPTIONAL" : "");
|
deco.opt ? "|A1_FLAG_OPTIONAL" : "");
|
||||||
free(ptr);
|
free(ptr);
|
||||||
} else
|
} else
|
||||||
/* Decorated with a templated ASN.1 type */
|
/* Decorated with a templated ASN.1 type */
|
||||||
@@ -1142,6 +1146,7 @@ template_members(struct templatehead *temp,
|
|||||||
Field *typeidfield = NULL;
|
Field *typeidfield = NULL;
|
||||||
Member *m;
|
Member *m;
|
||||||
struct decoration deco;
|
struct decoration deco;
|
||||||
|
ssize_t more_deco = -1;
|
||||||
size_t i = 0, typeididx = 0, opentypeidx = 0;
|
size_t i = 0, typeididx = 0, opentypeidx = 0;
|
||||||
int is_array_of_open_type = 0;
|
int is_array_of_open_type = 0;
|
||||||
|
|
||||||
@@ -1183,21 +1188,24 @@ template_members(struct templatehead *temp,
|
|||||||
typeidfield, opentypefield, opentypemember,
|
typeidfield, opentypefield, opentypemember,
|
||||||
is_array_of_open_type);
|
is_array_of_open_type);
|
||||||
|
|
||||||
if (decorate_type(basetype, &deco)) {
|
while (decorate_type(basetype, &deco, &more_deco)) {
|
||||||
char *poffset2;
|
char *poffset2;
|
||||||
|
|
||||||
poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct);
|
poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct);
|
||||||
|
|
||||||
if (deco.ext) {
|
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;
|
char *ptr = NULL;
|
||||||
|
|
||||||
/* Decorated with external C type */
|
/* Decorated with external C type */
|
||||||
if (asprintf(&ptr, "&asn1_extern_%s_%s",
|
if (asprintf(&ptr, "&asn1_extern_%s_%s",
|
||||||
basetype, deco.field_type) == -1 || ptr == NULL)
|
basetype, deco.field_name) == -1 || ptr == NULL)
|
||||||
err(1, "out of memory");
|
err(1, "out of memory");
|
||||||
add_line_pointer(temp, ptr, poffset2,
|
add_line_pointer(temp, ptr, poffset2,
|
||||||
"A1_OP_TYPE_DECORATE_EXTERN %s",
|
"A1_OP_TYPE_DECORATE_EXTERN %s",
|
||||||
deco.opt && !deco.void_star ? "|A1_FLAG_OPTIONAL" : "");
|
deco.opt ? "|A1_FLAG_OPTIONAL" : "");
|
||||||
free(ptr);
|
free(ptr);
|
||||||
} else
|
} else
|
||||||
/* Decorated with a templated ASN.1 type */
|
/* Decorated with a templated ASN.1 type */
|
||||||
@@ -1521,28 +1529,36 @@ generate_template(const Symbol *s)
|
|||||||
FILE *f = get_code_file();
|
FILE *f = get_code_file();
|
||||||
const char *dupname;
|
const char *dupname;
|
||||||
struct decoration deco;
|
struct decoration deco;
|
||||||
|
ssize_t more_deco = -1;
|
||||||
|
|
||||||
if (use_extern(s)) {
|
if (use_extern(s)) {
|
||||||
gen_extern_stubs(f, s->gen_name);
|
gen_extern_stubs(f, s->gen_name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decorate_type(s->gen_name, &deco) && deco.ext) {
|
while (decorate_type(s->gen_name, &deco, &more_deco)) {
|
||||||
if (deco.void_star && deco.header_name[0])
|
if (!deco.ext)
|
||||||
|
continue;
|
||||||
|
if (deco.heim_object)
|
||||||
|
fprintf(f, "#include <heimbase.h>\n");
|
||||||
|
else if (deco.void_star && deco.header_name)
|
||||||
fprintf(f, "#include %s\n", deco.header_name);
|
fprintf(f, "#include %s\n", deco.header_name);
|
||||||
fprintf(f,
|
if (!deco.heim_object)
|
||||||
"static const struct asn1_type_func asn1_extern_%s_%s = {\n"
|
fprintf(f,
|
||||||
"\t(asn1_type_encode)0,\n"
|
"static const struct asn1_type_func asn1_extern_%s_%s = {\n"
|
||||||
"\t(asn1_type_decode)0,\n"
|
"\t(asn1_type_encode)0,\n"
|
||||||
"\t(asn1_type_length)0,\n"
|
"\t(asn1_type_decode)0,\n"
|
||||||
"\t(asn1_type_copy)%s,\n"
|
"\t(asn1_type_length)0,\n"
|
||||||
"\t(asn1_type_release)%s,\n"
|
"\t(asn1_type_copy)%s,\n"
|
||||||
"\t(asn1_type_print)0,\n"
|
"\t(asn1_type_release)%s,\n"
|
||||||
"\tsizeof(%s)\n"
|
"\t(asn1_type_print)0,\n"
|
||||||
"};\n", s->gen_name, deco.field_type,
|
"\tsizeof(%s)\n"
|
||||||
deco.copy_function_name && deco.copy_function_name[0] ? deco.copy_function_name : "0",
|
"};\n", s->gen_name, deco.field_name,
|
||||||
deco.free_function_name && deco.free_function_name[0] ? deco.free_function_name : "0",
|
deco.copy_function_name && deco.copy_function_name[0] ?
|
||||||
deco.void_star ? "void *" : deco.field_type);
|
deco.copy_function_name : "0",
|
||||||
|
deco.free_function_name && deco.free_function_name[0] ?
|
||||||
|
deco.free_function_name : "0",
|
||||||
|
deco.void_star ? "void *" : deco.field_type);
|
||||||
free(deco.field_type);
|
free(deco.field_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
130
lib/asn1/main.c
130
lib/asn1/main.c
@@ -42,38 +42,86 @@ static getarg_strings seq;
|
|||||||
static getarg_strings decorate;
|
static getarg_strings decorate;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
strcmp4qsort(const void *ap, const void *bp)
|
strcmp4mergesort_r(const void *ap, const void *bp, void *d)
|
||||||
{
|
{
|
||||||
return strcmp(*(const char **)ap, *(const char **)bp);
|
const char *a = *(const char **)ap;
|
||||||
|
const char *b = *(const char **)bp;
|
||||||
|
char sep = *(const char *)d;
|
||||||
|
int cmp;
|
||||||
|
|
||||||
|
if (sep) {
|
||||||
|
const char *sepa = strchr(a, sep);
|
||||||
|
const char *sepb = strchr(b, sep);
|
||||||
|
size_t alen, blen;
|
||||||
|
|
||||||
|
if (sepa == NULL) sepa = a + strlen(a);
|
||||||
|
if (sepb == NULL) sepb = b + strlen(b);
|
||||||
|
alen = sepa - a;
|
||||||
|
blen = sepb - b;
|
||||||
|
cmp = strncmp(a, b, alen > blen ? alen : blen);
|
||||||
|
if (cmp == 0)
|
||||||
|
cmp = alen - blen;
|
||||||
|
} else
|
||||||
|
cmp = strcmp(a, b);
|
||||||
|
if (cmp == 0)
|
||||||
|
return (uintptr_t)ap - (uintptr_t)bp; /* stable sort */
|
||||||
|
return cmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
prefix_check(const char *s, const char *p, size_t plen, char sep, int *cmp)
|
||||||
|
{
|
||||||
|
if ((*cmp = strncmp(p, s, plen)) == 0 && s[plen] == sep)
|
||||||
|
return 1;
|
||||||
|
if (*cmp == 0)
|
||||||
|
*cmp = 1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
bsearch_strings(struct getarg_strings *strs, const char *s,
|
bsearch_strings(struct getarg_strings *strs, const char *p,
|
||||||
size_t prefix_len, char sep)
|
char sep, ssize_t *more)
|
||||||
{
|
{
|
||||||
ssize_t right = (ssize_t)strs->num_strings - 1;
|
ssize_t right = (ssize_t)strs->num_strings - 1;
|
||||||
ssize_t left = 0;
|
ssize_t left = 0;
|
||||||
|
ssize_t plen = 0;
|
||||||
|
int cmp;
|
||||||
|
|
||||||
|
if (sep)
|
||||||
|
plen = strlen(p);
|
||||||
|
|
||||||
if (strs->num_strings == 0)
|
if (strs->num_strings == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (sep && more && *more > -1) {
|
||||||
|
/* If *more > -1 we're continuing an iteration */
|
||||||
|
if (*more > right)
|
||||||
|
return -1;
|
||||||
|
if (prefix_check(strs->strings[*more], p, plen, sep, &cmp))
|
||||||
|
return (*more)++;
|
||||||
|
(*more)++;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
while (left <= right) {
|
while (left <= right) {
|
||||||
ssize_t mid = left + (right - left) / 2;
|
ssize_t mid = left + (right - left) / 2;
|
||||||
int cmp;
|
|
||||||
|
|
||||||
if (prefix_len) {
|
if (sep) {
|
||||||
cmp = strncmp(s, strs->strings[mid], prefix_len);
|
int cmp2;
|
||||||
if (cmp == 0 && sep) {
|
|
||||||
if (strs->strings[mid][prefix_len] == sep)
|
while (prefix_check(strs->strings[mid], p, plen, sep, &cmp) &&
|
||||||
return mid;
|
mid > 0 &&
|
||||||
cmp = strncmp(&sep, &strs->strings[mid][prefix_len], 1);
|
prefix_check(strs->strings[mid - 1], p, plen, sep, &cmp2))
|
||||||
}
|
mid--;
|
||||||
} else
|
} else
|
||||||
cmp = strcmp(s, strs->strings[mid]);
|
cmp = strcmp(p, strs->strings[mid]);
|
||||||
if (cmp == 0)
|
if (cmp == 0) {
|
||||||
|
if (more)
|
||||||
|
*more = mid + 1;
|
||||||
return mid;
|
return mid;
|
||||||
|
}
|
||||||
if (cmp < 0)
|
if (cmp < 0)
|
||||||
right = mid - 1; /* -1 if `s' is smaller than smallest in strs */
|
right = mid - 1; /* -1 if `p' is smaller than smallest in strs */
|
||||||
else
|
else
|
||||||
left = mid + 1;
|
left = mid + 1;
|
||||||
}
|
}
|
||||||
@@ -83,13 +131,13 @@ bsearch_strings(struct getarg_strings *strs, const char *s,
|
|||||||
int
|
int
|
||||||
preserve_type(const char *p)
|
preserve_type(const char *p)
|
||||||
{
|
{
|
||||||
return bsearch_strings(&preserve, p, 0, '\0') > -1;
|
return bsearch_strings(&preserve, p, '\0', 0) > -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
seq_type(const char *p)
|
seq_type(const char *p)
|
||||||
{
|
{
|
||||||
return bsearch_strings(&seq, p, 0, '\0') > -1;
|
return bsearch_strings(&seq, p, '\0', 0) > -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -126,23 +174,22 @@ split_str(const char *s, char sep, char ***fs)
|
|||||||
* functions to copy and free values of that type.
|
* functions to copy and free values of that type.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
decorate_type(const char *p,
|
decorate_type(const char *p, struct decoration *deco, ssize_t *more)
|
||||||
struct decoration *deco)
|
|
||||||
{
|
{
|
||||||
ssize_t i;
|
ssize_t i;
|
||||||
size_t plen = strlen(p);
|
|
||||||
char **s[7];
|
char **s[7];
|
||||||
char *junk = NULL;
|
char *junk = NULL;
|
||||||
char *cp;
|
char *cp;
|
||||||
|
|
||||||
|
deco->first = *more == -1;
|
||||||
deco->decorated = 0;
|
deco->decorated = 0;
|
||||||
deco->field_type = NULL;
|
deco->field_type = NULL;
|
||||||
if ((i = bsearch_strings(&decorate, p, plen, ':')) == -1)
|
if ((i = bsearch_strings(&decorate, p, ':', more)) == -1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
deco->decorated = 1;
|
deco->decorated = 1;
|
||||||
deco->opt = 0;
|
deco->opt = deco->ext = deco->ptr = 0;
|
||||||
deco->ext = 0;
|
deco->void_star = deco->struct_star = deco->heim_object = 0;
|
||||||
deco->field_name = deco->copy_function_name = deco->free_function_name =
|
deco->field_name = deco->copy_function_name = deco->free_function_name =
|
||||||
deco->header_name = NULL;
|
deco->header_name = NULL;
|
||||||
|
|
||||||
@@ -153,7 +200,7 @@ decorate_type(const char *p,
|
|||||||
s[4] = &deco->header_name;
|
s[4] = &deco->header_name;
|
||||||
s[5] = &junk;
|
s[5] = &junk;
|
||||||
s[6] = NULL;
|
s[6] = NULL;
|
||||||
split_str(decorate.strings[i] + plen + 1, ':', s);
|
split_str(decorate.strings[i] + strlen(p) + 1, ':', s);
|
||||||
|
|
||||||
if (junk || deco->field_type[0] == '\0' || !deco->field_name ||
|
if (junk || deco->field_type[0] == '\0' || !deco->field_name ||
|
||||||
deco->field_name[0] == '\0' || deco->field_name[0] == '?') {
|
deco->field_name[0] == '\0' || deco->field_name[0] == '?') {
|
||||||
@@ -164,10 +211,27 @@ decorate_type(const char *p,
|
|||||||
deco->opt = 1;
|
deco->opt = 1;
|
||||||
*cp = '\0';
|
*cp = '\0';
|
||||||
}
|
}
|
||||||
if (deco->copy_function_name)
|
if (strcmp(deco->field_type, "void*") == 0 ||
|
||||||
|
strcmp(deco->field_type, "void *") == 0) {
|
||||||
|
deco->ext = deco->ptr = deco->void_star = 1;
|
||||||
|
deco->opt = 1;
|
||||||
|
deco->header_name = NULL;
|
||||||
|
} else if (strcmp(deco->field_type, "heim_object_t") == 0) {
|
||||||
|
deco->ptr = deco->heim_object = 1;
|
||||||
|
deco->header_name = "<heimbase.h>";
|
||||||
|
} else if (strncmp(deco->field_type, "struct ", sizeof("struct ") - 1) == 0 &&
|
||||||
|
deco->field_type[strlen(deco->field_type) - 1] == '*')
|
||||||
|
deco->ptr = deco->struct_star = 1;
|
||||||
|
if (deco->ptr || deco->copy_function_name)
|
||||||
deco->ext = 1;
|
deco->ext = 1;
|
||||||
if (deco->ext && strcmp(deco->field_type, "void") == 0)
|
if (deco->ext && deco->copy_function_name && !deco->copy_function_name[0])
|
||||||
deco->opt = deco->void_star = 1;
|
deco->copy_function_name = NULL;
|
||||||
|
if (deco->ext && deco->free_function_name && !deco->free_function_name[0])
|
||||||
|
deco->free_function_name = NULL;
|
||||||
|
if (deco->header_name && !deco->header_name[0])
|
||||||
|
deco->header_name = NULL;
|
||||||
|
if (deco->ptr)
|
||||||
|
deco->opt = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -389,14 +453,14 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (preserve.num_strings)
|
if (preserve.num_strings)
|
||||||
qsort(preserve.strings, preserve.num_strings, sizeof(preserve.strings[0]),
|
mergesort_r(preserve.strings, preserve.num_strings,
|
||||||
(int (*)(const void *, const void *))strcmp4qsort);
|
sizeof(preserve.strings[0]), strcmp4mergesort_r, "");
|
||||||
if (seq.num_strings)
|
if (seq.num_strings)
|
||||||
qsort(seq.strings, seq.num_strings, sizeof(seq.strings),
|
mergesort_r(seq.strings, seq.num_strings, sizeof(seq.strings),
|
||||||
(int (*)(const void *, const void *))strcmp4qsort);
|
strcmp4mergesort_r, "");
|
||||||
if (decorate.num_strings)
|
if (decorate.num_strings)
|
||||||
qsort(decorate.strings, decorate.num_strings, sizeof(decorate.strings[0]),
|
mergesort_r(decorate.strings, decorate.num_strings,
|
||||||
(int (*)(const void *, const void *))strcmp4qsort);
|
sizeof(decorate.strings[0]), strcmp4mergesort_r, ":");
|
||||||
|
|
||||||
init_generate(file, name);
|
init_generate(file, name);
|
||||||
|
|
||||||
|
@@ -37,6 +37,7 @@
|
|||||||
#include <com_err.h>
|
#include <com_err.h>
|
||||||
#include <vis.h>
|
#include <vis.h>
|
||||||
#include <vis-extras.h>
|
#include <vis-extras.h>
|
||||||
|
#include <heimbase.h>
|
||||||
|
|
||||||
#ifndef ENOTSUP
|
#ifndef ENOTSUP
|
||||||
/* Very old MSVC CRTs don't have ENOTSUP */
|
/* Very old MSVC CRTs don't have ENOTSUP */
|
||||||
@@ -2278,8 +2279,13 @@ _asn1_free(const struct asn1_template *t, void *data)
|
|||||||
const struct asn1_type_func *f = t->ptr;
|
const struct asn1_type_func *f = t->ptr;
|
||||||
(f->release)(el);
|
(f->release)(el);
|
||||||
} else {
|
} else {
|
||||||
|
/* A1_OP_TYPE_DECORATE_EXTERN */
|
||||||
const struct asn1_type_func *f = t->ptr;
|
const struct asn1_type_func *f = t->ptr;
|
||||||
if (f->release)
|
|
||||||
|
if (t->tt & A1_FLAG_HEIM_OBJ) {
|
||||||
|
heim_release(*(void **)el);
|
||||||
|
*(void **)el = 0;
|
||||||
|
} else if (f && f->release)
|
||||||
(f->release)(el);
|
(f->release)(el);
|
||||||
else
|
else
|
||||||
memset(el, 0, f->size);
|
memset(el, 0, f->size);
|
||||||
@@ -2910,7 +2916,11 @@ _asn1_copy(const struct asn1_template *t, const void *from, void *to)
|
|||||||
ret = (f->copy)(fel, tel);
|
ret = (f->copy)(fel, tel);
|
||||||
} else {
|
} else {
|
||||||
const struct asn1_type_func *f = t->ptr;
|
const struct asn1_type_func *f = t->ptr;
|
||||||
if (f->copy)
|
|
||||||
|
/* A1_OP_TYPE_DECORATE_EXTERN */
|
||||||
|
if (t->tt & A1_FLAG_HEIM_OBJ)
|
||||||
|
*(heim_object_t *)tel = heim_retain(*(void **)fel);
|
||||||
|
else if (f->copy)
|
||||||
ret = (f->copy)(fel, tel);
|
ret = (f->copy)(fel, tel);
|
||||||
else
|
else
|
||||||
memset(tel, 0, f->size);
|
memset(tel, 0, f->size);
|
||||||
|
@@ -288,23 +288,12 @@ TESTExtensible ::= SEQUENCE {
|
|||||||
|
|
||||||
TESTDecorated ::= SEQUENCE {
|
TESTDecorated ::= SEQUENCE {
|
||||||
version TESTuint32
|
version TESTuint32
|
||||||
-- gets decorated with an ASN.1 type (see test.opt)
|
-- gets decorated with varius fields (see test.opt)
|
||||||
}
|
|
||||||
|
|
||||||
TESTDecorated2 ::= SEQUENCE {
|
|
||||||
version TESTuint32
|
|
||||||
-- gets decorated with a C type (see test.opt)
|
|
||||||
}
|
|
||||||
|
|
||||||
TESTDecorated3 ::= SEQUENCE {
|
|
||||||
version TESTuint32
|
|
||||||
-- gets decorated with a void * field (see test.opt)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TESTNotDecorated ::= SEQUENCE {
|
TESTNotDecorated ::= SEQUENCE {
|
||||||
version TESTuint32
|
version TESTuint32
|
||||||
-- should have the same encoding as TESTDecorated, TESTDecorated2, and
|
-- should have the same encoding as TESTDecorated
|
||||||
-- TESTDecorated3
|
|
||||||
}
|
}
|
||||||
|
|
||||||
END
|
END
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
--sequence=TESTSeqOf
|
--sequence=TESTSeqOf
|
||||||
--decorate=TESTDecorated:TESTuint32:version2?
|
--decorate=TESTDecorated:TESTuint32:version2?
|
||||||
--decorate=TESTDecorated2:my_vers:version2:my_copy_vers:my_free_vers:"check-gen.h"
|
--decorate=TESTDecorated:my_vers:version3:my_copy_vers:my_free_vers:"check-gen.h"
|
||||||
--decorate=TESTDecorated3:void:privthing?:::
|
--decorate=TESTDecorated:void *:privthing
|
||||||
|
--decorate=TESTDecorated:heim_object_t:privobj
|
||||||
|
Reference in New Issue
Block a user