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 = \
|
||||
libasn1base.la \
|
||||
@LIB_com_err@ \
|
||||
$(LIB_heimbase) \
|
||||
$(LIBADD_roken)
|
||||
|
||||
BUILT_SOURCES = \
|
||||
@@ -188,10 +189,12 @@ check_timegm_LDADD = $(check_der_LDADD)
|
||||
|
||||
check_gen_template_LDADD = \
|
||||
libasn1template.la \
|
||||
$(LIB_heimbase) \
|
||||
$(LIB_roken)
|
||||
|
||||
check_gen_LDADD = \
|
||||
libasn1template.la \
|
||||
$(LIB_heimbase) \
|
||||
$(LIB_roken)
|
||||
|
||||
check_ber_LDADD = $(check_gen_LDADD)
|
||||
|
@@ -14,7 +14,7 @@ annotations](/lib/asn1/README-X681.md).
|
||||
5. [Limitations](#Limitations)
|
||||
6. [Compiler Usage](#Compiler-usage)
|
||||
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)
|
||||
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
|
||||
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
|
||||
|
||||
- JER support?
|
||||
|
||||
- XDR/OER support?
|
||||
- XDR/NDR/OER support?
|
||||
|
||||
- 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
|
||||
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
|
||||
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.)
|
||||
|
||||
- Unconstrained integer types have a large integer representation in C that is
|
||||
not terribly useful in common cases. Range constraints on integer types
|
||||
cause the compiler to use `int32_t`, `int64_t`, `uint32_t`, and/or
|
||||
`uint64_t`.
|
||||
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
|
||||
@@ -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
|
||||
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
|
||||
definitions. Even for types, it is not complete, and the JSON schema used
|
||||
is subject to change *WITHOUT NOTICE*.
|
||||
@@ -813,7 +820,8 @@ In recent times the following features have been added:
|
||||
|
||||
## 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
|
||||
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 `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
|
||||
@@ -871,11 +885,8 @@ SYNOPSIS
|
||||
asn1_compile [--template] [--prefix-enum] [--enum-prefix=PREFIX]
|
||||
[--encode-rfc1510-bit-string] [--decode-dce-ber]
|
||||
[--support-ber] [--preserve-binary=TYPE] [--sequence=TYPE]
|
||||
[--decorate=TYPE:FTYPE:fname[?]]
|
||||
[--decorate=TYPE:void:fname:::]
|
||||
[--decorate=TYPE:FTYPE:fname[?]:[copyfn]:[freefn]:header]
|
||||
[--one-code-file] [--gen-name=NAME] [--option-file=FILE]
|
||||
[--original-order] [--no-parse-units]
|
||||
[--decorate=DECORATION] [--one-code-file] [--gen-name=NAME]
|
||||
[--option-file=FILE] [--original-order] [--no-parse-units]
|
||||
[--type-file=C-HEADER-FILE] [--version] [--help]
|
||||
[FILE.asn1 [NAME]]
|
||||
|
||||
@@ -883,19 +894,19 @@ DESCRIPTION
|
||||
asn1_compile compiles an ASN.1 module into C source code and header
|
||||
files.
|
||||
|
||||
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‐
|
||||
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-
|
||||
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).
|
||||
|
||||
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.
|
||||
|
||||
The Information Object System support includes automatic codec support
|
||||
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‐
|
||||
mation Object System via X.681/X.682/X.683 annotations. See the com‐
|
||||
“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-
|
||||
piler's README files for more information on ASN.1 Information Object
|
||||
System support.
|
||||
|
||||
@@ -907,7 +918,7 @@ DESCRIPTION
|
||||
• enable saving of as-received encodings of specific types
|
||||
for the purpose of signature validation;
|
||||
• 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;
|
||||
etc.
|
||||
|
||||
@@ -934,7 +945,7 @@ DESCRIPTION
|
||||
• The REAL type is not supported.
|
||||
• The EmbeddedPDV 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.
|
||||
• All supported non-octet strings are treated as like the
|
||||
UTF8String type.
|
||||
@@ -956,19 +967,19 @@ DESCRIPTION
|
||||
The codegen backend generates C code for all functions directly,
|
||||
with no template interpretation.
|
||||
|
||||
The template backend scales better than the codegen backend be‐
|
||||
cause as we add support for more encoding rules and more opera‐
|
||||
The template backend scales better than the codegen backend be-
|
||||
cause as we add support for more encoding rules and more opera-
|
||||
tions (we may add value comparators) the templates stay mostly
|
||||
the same, thus scaling linearly with size of module. Whereas the
|
||||
codegen backend scales linear with the product of module size and
|
||||
number of encoding rules supported.
|
||||
|
||||
--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.
|
||||
|
||||
--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.
|
||||
|
||||
--encode-rfc1510-bit-string
|
||||
@@ -1000,54 +1011,48 @@ DESCRIPTION
|
||||
Generate add/remove functions for the named ASN.1 TYPE which must
|
||||
be a ‘SET OF’ or ‘SEQUENCE OF’ type.
|
||||
|
||||
--decorate=TYPE:FTYPE:fname[?]
|
||||
Add to the C struct generated for the given ASN.1 type named TYPE
|
||||
a “hidden” field named fname of the given ASN.1 type FTYPE, but
|
||||
do not encode or decode it. The TYPE must be a SET or SEQUENCE
|
||||
type. If the fname ends in a question mark, then treat the field
|
||||
as OPTIONAL.
|
||||
--decorate=ASN1-TYPE:FIELD-ASN1-TYPE: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 the given
|
||||
ASN.1 type FIELD-ASN1-TYPE, but do not encode or decode it. If
|
||||
the fname ends in a question mark, then treat the field as OP-
|
||||
TIONAL.
|
||||
|
||||
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‐
|
||||
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.
|
||||
|
||||
--decorate=TYPE:void:fname:::
|
||||
Add to the C struct generated for the given ASN.1 type named TYPE
|
||||
a “hidden” field named fname of type ‘void *’ (but do not encode
|
||||
or decode it.
|
||||
--decorate=ASN1-TYPE:heim_object_t: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 C type
|
||||
‘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
|
||||
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
|
||||
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.
|
||||
|
||||
--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.
|
||||
--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 named ASN1-TYPE a “hidden” field named fname of the given
|
||||
external C type FIELD-C-TYPE, declared in the given header but do
|
||||
not encode or decode this field. If the fname ends in a question
|
||||
mark, then treat the field as OPTIONAL.
|
||||
|
||||
The header must include double quotes or angle brackets. The
|
||||
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
|
||||
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
|
||||
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
|
||||
also reset the value to a pristine state (such as all zeros).
|
||||
|
||||
@@ -1069,7 +1074,7 @@ DESCRIPTION
|
||||
|
||||
--original-order
|
||||
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.
|
||||
|
||||
--no-parse-units
|
||||
@@ -1085,9 +1090,7 @@ DESCRIPTION
|
||||
--help
|
||||
|
||||
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
|
||||
X.681/X.682/X.683 annotations.
|
||||
|
||||
@@ -1303,13 +1306,19 @@ See:
|
||||
|
||||
- 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 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
|
||||
|
||||
|
@@ -150,6 +150,7 @@
|
||||
#define A1_FLAG_OPTIONAL (0x01000000)
|
||||
#define A1_FLAG_IMPLICIT (0x02000000)
|
||||
#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_CLASS(x) (((x) >> 22) & 0x3)
|
||||
|
@@ -48,9 +48,7 @@
|
||||
.Op Fl Fl support-ber
|
||||
.Op Fl Fl preserve-binary=TYPE
|
||||
.Op Fl Fl sequence=TYPE
|
||||
.Op Fl Fl decorate=TYPE:FTYPE:fname[?]
|
||||
.Op Fl Fl decorate=TYPE:void:fname:::
|
||||
.Op Fl Fl decorate=TYPE:FTYPE:fname[?]:[copyfn]:[freefn]:header
|
||||
.Op Fl Fl decorate=DECORATION
|
||||
.Op Fl Fl one-code-file
|
||||
.Op Fl Fl gen-name=NAME
|
||||
.Op Fl Fl option-file=FILE
|
||||
@@ -240,19 +238,17 @@ which must be a
|
||||
or
|
||||
.Sq SEQUENCE OF
|
||||
type.
|
||||
.It Fl Fl decorate=TYPE:FTYPE:fname[?]
|
||||
Add to the C struct generated for the given ASN.1 type named
|
||||
.Ar TYPE
|
||||
.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
|
||||
named
|
||||
.Ar ASN1-TYPE
|
||||
a
|
||||
.Dq hidden
|
||||
field named
|
||||
.Ar fname
|
||||
of the given ASN.1 type
|
||||
.Ar FTYPE ,
|
||||
.Ar FIELD-ASN1-TYPE ,
|
||||
but do not encode or decode it.
|
||||
The
|
||||
.Ar TYPE
|
||||
must be a SET or SEQUENCE type.
|
||||
If the
|
||||
.Ar fname
|
||||
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.
|
||||
For example, one might decorate a request type with state needed
|
||||
during processing of the request.
|
||||
.It Fl Fl decorate=TYPE:void:fname:::
|
||||
Add to the C struct generated for the given ASN.1 type named
|
||||
.Ar TYPE
|
||||
.It Fl Fl decorate=ASN1-TYPE:heim_object_t:fname
|
||||
Add to the C struct generated for the given ASN.1 SET or SEQUENCE 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
|
||||
.Dq hidden
|
||||
field named
|
||||
@@ -275,41 +287,27 @@ of type
|
||||
.Pp
|
||||
The destructor and copy constructor functions generated by this
|
||||
compiler for
|
||||
.Ar TYPE
|
||||
.Ar ASN1-TYPE
|
||||
will set this field to the
|
||||
.Sq NULL
|
||||
pointer.
|
||||
.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.
|
||||
.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
|
||||
.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
|
||||
named
|
||||
.Ar ASN1-TYPE
|
||||
a
|
||||
.Dq hidden
|
||||
field named
|
||||
.Ar fname
|
||||
of the given external C type
|
||||
.Ar FTYPE ,
|
||||
.Ar FIELD-C-TYPE ,
|
||||
declared in the given
|
||||
.Ar header
|
||||
but do not encode or decode this field.
|
||||
The
|
||||
.Ar TYPE
|
||||
must be a SET or SEQUENCE type.
|
||||
If the
|
||||
.Ar fname
|
||||
ends in a question mark, then treat the field as OPTIONAL.
|
||||
.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
|
||||
.Ar header
|
||||
must include double quotes or angle brackets.
|
||||
@@ -364,9 +362,6 @@ for common type defintions.
|
||||
.It Fl Fl help
|
||||
.El
|
||||
.Sh NOTES
|
||||
Note that only one decoration per-SET/SEQUENCE type may be
|
||||
specified.
|
||||
.Pp
|
||||
Currently only the template backend supports automatic encoding
|
||||
and decoding of open types via the ASN.1 Information Object
|
||||
System and X.681/X.682/X.683 annotations.
|
||||
|
@@ -1039,18 +1039,18 @@ static int
|
||||
test_decorated(void)
|
||||
{
|
||||
TESTNotDecorated tnd;
|
||||
TESTDecorated3 td3, td3_copy;
|
||||
TESTDecorated2 td2, td2_copy;
|
||||
TESTDecorated td, td_copy;
|
||||
size_t len, size;
|
||||
void *ptr;
|
||||
int ret;
|
||||
|
||||
memset(&td, 0, sizeof(td));
|
||||
memset(&td2, 0, sizeof(td2));
|
||||
memset(&tnd, 0, sizeof(tnd));
|
||||
|
||||
td.version = 3;
|
||||
td.version3.v = 5;
|
||||
td.privthing = &td;
|
||||
td.privobj = heim_string_create("foo");
|
||||
if ((td.version2 = malloc(sizeof(*td.version2))) == NULL)
|
||||
errx(1, "out of memory");
|
||||
*td.version2 = 5;
|
||||
@@ -1085,90 +1085,35 @@ test_decorated(void)
|
||||
warnx("copy_TESTDecorated() did not work correctly (2)");
|
||||
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);
|
||||
if (td.version2) {
|
||||
warnx("free_TESTDecorated() did not work correctly");
|
||||
warnx("free_TESTDecorated() did not work correctly (1)");
|
||||
return 1;
|
||||
}
|
||||
|
||||
td2.version = 3;
|
||||
td2.version2.v = 5;
|
||||
ASN1_MALLOC_ENCODE(TESTDecorated2, ptr, len, &td2, &size, ret);
|
||||
if (ret) {
|
||||
warnx("could not encode a TESTDecorated2 struct");
|
||||
if (td.version3.v != 0 || my_free_vers_called != 2) {
|
||||
warnx("free_TESTDecorated() did not work correctly (2)");
|
||||
return 1;
|
||||
}
|
||||
ret = decode_TESTNotDecorated(ptr, len, &tnd, &size);
|
||||
if (ret) {
|
||||
warnx("could not decode a TESTDecorated2 struct as TESTNotDecorated2");
|
||||
if (td.privthing != 0) {
|
||||
warnx("free_TESTDecorated() did not work correctly (3)");
|
||||
return 1;
|
||||
}
|
||||
free(ptr);
|
||||
if (size != len) {
|
||||
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");
|
||||
if (td.privobj != 0) {
|
||||
warnx("free_TESTDecorated() did not work correctly (4)");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
@@ -1366,12 +1366,13 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t
|
||||
case TSequence: {
|
||||
Member *m;
|
||||
struct decoration deco;
|
||||
ssize_t more_deco = -1;
|
||||
int decorated = 0;
|
||||
|
||||
getnewbasename(&newbasename, typedefp || level == 0, basename, name);
|
||||
|
||||
space(level);
|
||||
|
||||
(void) decorate_type(newbasename, &deco);
|
||||
fprintf (headerfile, "struct %s {\n", newbasename);
|
||||
fprintf(jsonfile, "\"ttype\":\"%s\",\"extensible\":%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\":");
|
||||
define_open_type(level, newbasename, name, basename, t, t);
|
||||
}
|
||||
if (deco.decorated) {
|
||||
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);
|
||||
fprintf(jsonfile, ",\"decorate\":{"
|
||||
if (deco.first)
|
||||
fprintf(jsonfile, ",\"decorate\":[");
|
||||
fprintf(jsonfile, "%s{"
|
||||
"\"type\":\"%s\",\"name\":\"%s\",\"optional\":%s,"
|
||||
"\"external\":%s,\"copy_function\":\"%s\","
|
||||
"\"free_function\":\"%s\",\"header_name\":\"%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.copy_function_name, deco.free_function_name,
|
||||
deco.header_name);
|
||||
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);
|
||||
fprintf (headerfile, "} %s;\n", name);
|
||||
free(deco.field_type);
|
||||
@@ -1637,13 +1653,13 @@ declare_type(const Symbol *s, Type *t, int typedefp)
|
||||
case TSet:
|
||||
case TSequence: {
|
||||
struct decoration deco;
|
||||
ssize_t more_deco = -1;
|
||||
|
||||
getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
|
||||
fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
|
||||
if (decorate_type(newbasename, &deco) && deco.header_name
|
||||
&& !deco.void_star
|
||||
&& deco.header_name[0]) {
|
||||
fprintf(headerfile, "#include %s\n", deco.header_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;
|
||||
@@ -1782,6 +1798,7 @@ static void
|
||||
generate_type_header (const Symbol *s)
|
||||
{
|
||||
Type *t = s->type;
|
||||
|
||||
if (!s->type)
|
||||
return;
|
||||
|
||||
@@ -1850,6 +1867,7 @@ generate_type_header (const Symbol *s)
|
||||
if (is_export(s->name))
|
||||
fprintf(symsfile, "ASN1_SYM_TYPE(\"%s\", \"%s\", %s)\n",
|
||||
s->name, s->gen_name, s->gen_name);
|
||||
|
||||
fprintf(headerfile, "typedef ");
|
||||
define_type(0, s->gen_name, s->gen_name, NULL, s->type, TRUE,
|
||||
preserve_type(s->name) ? TRUE : FALSE);
|
||||
|
@@ -229,6 +229,7 @@ void
|
||||
generate_type_copy (const Symbol *s)
|
||||
{
|
||||
struct decoration deco;
|
||||
ssize_t more_deco = -1;
|
||||
int preserve = preserve_type(s->name) ? TRUE : FALSE;
|
||||
int save_used_fail = used_fail;
|
||||
|
||||
@@ -240,19 +241,20 @@ generate_type_copy (const Symbol *s)
|
||||
"memset(to, 0, sizeof(*to));\n",
|
||||
s->gen_name, s->gen_name, s->gen_name);
|
||||
copy_type ("from", "to", s->type, preserve);
|
||||
if (decorate_type(s->gen_name, &deco)) {
|
||||
if (deco.ext &&
|
||||
(deco.copy_function_name == NULL ||
|
||||
deco.copy_function_name[0] == '\0')) {
|
||||
while (decorate_type(s->gen_name, &deco, &more_deco)) {
|
||||
if (deco.heim_object) {
|
||||
fprintf(codefile, "(to)->%s = heim_retain((from)->%s);\n",
|
||||
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 */
|
||||
if (deco.opt || deco.void_star)
|
||||
if (deco.ptr)
|
||||
fprintf(codefile, "(to)->%s = 0;\n", deco.field_name);
|
||||
else
|
||||
fprintf(codefile, "memset(&(to)->%s, 0, sizeof((to)->%s));\n",
|
||||
deco.field_name, deco.field_name);
|
||||
} else if (deco.ext) {
|
||||
/* 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, "(to)->%s = malloc(sizeof(*(to)->%s));\n",
|
||||
deco.field_name, deco.field_name);
|
||||
|
@@ -179,6 +179,7 @@ void
|
||||
generate_type_free (const Symbol *s)
|
||||
{
|
||||
struct decoration deco;
|
||||
ssize_t more_deco = -1;
|
||||
int preserve = preserve_type(s->name) ? TRUE : FALSE;
|
||||
|
||||
fprintf (codefile, "void ASN1CALL\n"
|
||||
@@ -187,12 +188,13 @@ generate_type_free (const Symbol *s)
|
||||
s->gen_name, s->gen_name);
|
||||
|
||||
free_type ("data", s->type, preserve);
|
||||
if (decorate_type(s->gen_name, &deco)) {
|
||||
if (deco.ext &&
|
||||
(deco.free_function_name == NULL ||
|
||||
deco.free_function_name[0] == '\0')) {
|
||||
while (decorate_type(s->gen_name, &deco, &more_deco)) {
|
||||
if (deco.heim_object) {
|
||||
fprintf(codefile, "heim_retain((data)->%s);\n", deco.field_name);
|
||||
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 */
|
||||
if (deco.opt || deco.void_star)
|
||||
if (deco.ptr)
|
||||
fprintf(codefile, "(data)->%s = 0;\n", deco.field_name);
|
||||
else
|
||||
fprintf(codefile,
|
||||
@@ -200,7 +202,7 @@ generate_type_free (const Symbol *s)
|
||||
deco.field_name, deco.field_name);
|
||||
} else if (deco.ext) {
|
||||
/* 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, "%s((data)->%s);\n",
|
||||
deco.free_function_name, deco.field_name);
|
||||
|
@@ -152,11 +152,15 @@ struct decoration {
|
||||
char *free_function_name; /* destructor function name */
|
||||
char *header_name; /* header name */
|
||||
unsigned int decorated:1;
|
||||
unsigned int first:1; /* optional */
|
||||
unsigned int opt:1; /* optional */
|
||||
unsigned int ext:1; /* external */
|
||||
unsigned int ptr:1; /* external, pointer */
|
||||
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 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
|
||||
add_line_string(struct templatehead *t,
|
||||
@@ -1065,6 +1065,7 @@ template_members(struct templatehead *temp,
|
||||
Field *typeidfield = NULL;
|
||||
Member *m;
|
||||
struct decoration deco;
|
||||
ssize_t more_deco = -1;
|
||||
size_t i = 0, typeididx = 0, opentypeidx = 0;
|
||||
int is_array_of_open_type = 0;
|
||||
|
||||
@@ -1106,21 +1107,24 @@ template_members(struct templatehead *temp,
|
||||
typeidfield, opentypefield, opentypemember,
|
||||
is_array_of_open_type);
|
||||
|
||||
if (decorate_type(basetype, &deco)) {
|
||||
while (decorate_type(basetype, &deco, &more_deco)) {
|
||||
char *poffset2;
|
||||
|
||||
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;
|
||||
|
||||
/* Decorated with external C type */
|
||||
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");
|
||||
add_line_pointer(temp, ptr, poffset2,
|
||||
"A1_OP_TYPE_DECORATE_EXTERN %s",
|
||||
deco.opt && !deco.void_star ? "|A1_FLAG_OPTIONAL" : "");
|
||||
deco.opt ? "|A1_FLAG_OPTIONAL" : "");
|
||||
free(ptr);
|
||||
} else
|
||||
/* Decorated with a templated ASN.1 type */
|
||||
@@ -1142,6 +1146,7 @@ template_members(struct templatehead *temp,
|
||||
Field *typeidfield = NULL;
|
||||
Member *m;
|
||||
struct decoration deco;
|
||||
ssize_t more_deco = -1;
|
||||
size_t i = 0, typeididx = 0, opentypeidx = 0;
|
||||
int is_array_of_open_type = 0;
|
||||
|
||||
@@ -1183,21 +1188,24 @@ template_members(struct templatehead *temp,
|
||||
typeidfield, opentypefield, opentypemember,
|
||||
is_array_of_open_type);
|
||||
|
||||
if (decorate_type(basetype, &deco)) {
|
||||
while (decorate_type(basetype, &deco, &more_deco)) {
|
||||
char *poffset2;
|
||||
|
||||
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;
|
||||
|
||||
/* Decorated with external C type */
|
||||
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");
|
||||
add_line_pointer(temp, ptr, poffset2,
|
||||
"A1_OP_TYPE_DECORATE_EXTERN %s",
|
||||
deco.opt && !deco.void_star ? "|A1_FLAG_OPTIONAL" : "");
|
||||
deco.opt ? "|A1_FLAG_OPTIONAL" : "");
|
||||
free(ptr);
|
||||
} else
|
||||
/* Decorated with a templated ASN.1 type */
|
||||
@@ -1521,28 +1529,36 @@ generate_template(const Symbol *s)
|
||||
FILE *f = get_code_file();
|
||||
const char *dupname;
|
||||
struct decoration deco;
|
||||
ssize_t more_deco = -1;
|
||||
|
||||
if (use_extern(s)) {
|
||||
gen_extern_stubs(f, s->gen_name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (decorate_type(s->gen_name, &deco) && deco.ext) {
|
||||
if (deco.void_star && deco.header_name[0])
|
||||
while (decorate_type(s->gen_name, &deco, &more_deco)) {
|
||||
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,
|
||||
"static const struct asn1_type_func asn1_extern_%s_%s = {\n"
|
||||
"\t(asn1_type_encode)0,\n"
|
||||
"\t(asn1_type_decode)0,\n"
|
||||
"\t(asn1_type_length)0,\n"
|
||||
"\t(asn1_type_copy)%s,\n"
|
||||
"\t(asn1_type_release)%s,\n"
|
||||
"\t(asn1_type_print)0,\n"
|
||||
"\tsizeof(%s)\n"
|
||||
"};\n", s->gen_name, deco.field_type,
|
||||
deco.copy_function_name && deco.copy_function_name[0] ? 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);
|
||||
if (!deco.heim_object)
|
||||
fprintf(f,
|
||||
"static const struct asn1_type_func asn1_extern_%s_%s = {\n"
|
||||
"\t(asn1_type_encode)0,\n"
|
||||
"\t(asn1_type_decode)0,\n"
|
||||
"\t(asn1_type_length)0,\n"
|
||||
"\t(asn1_type_copy)%s,\n"
|
||||
"\t(asn1_type_release)%s,\n"
|
||||
"\t(asn1_type_print)0,\n"
|
||||
"\tsizeof(%s)\n"
|
||||
"};\n", s->gen_name, deco.field_name,
|
||||
deco.copy_function_name && deco.copy_function_name[0] ?
|
||||
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);
|
||||
}
|
||||
|
||||
|
130
lib/asn1/main.c
130
lib/asn1/main.c
@@ -42,38 +42,86 @@ static getarg_strings seq;
|
||||
static getarg_strings decorate;
|
||||
|
||||
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
|
||||
bsearch_strings(struct getarg_strings *strs, const char *s,
|
||||
size_t prefix_len, char sep)
|
||||
bsearch_strings(struct getarg_strings *strs, const char *p,
|
||||
char sep, ssize_t *more)
|
||||
{
|
||||
ssize_t right = (ssize_t)strs->num_strings - 1;
|
||||
ssize_t left = 0;
|
||||
ssize_t plen = 0;
|
||||
int cmp;
|
||||
|
||||
if (sep)
|
||||
plen = strlen(p);
|
||||
|
||||
if (strs->num_strings == 0)
|
||||
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) {
|
||||
ssize_t mid = left + (right - left) / 2;
|
||||
int cmp;
|
||||
|
||||
if (prefix_len) {
|
||||
cmp = strncmp(s, strs->strings[mid], prefix_len);
|
||||
if (cmp == 0 && sep) {
|
||||
if (strs->strings[mid][prefix_len] == sep)
|
||||
return mid;
|
||||
cmp = strncmp(&sep, &strs->strings[mid][prefix_len], 1);
|
||||
}
|
||||
if (sep) {
|
||||
int cmp2;
|
||||
|
||||
while (prefix_check(strs->strings[mid], p, plen, sep, &cmp) &&
|
||||
mid > 0 &&
|
||||
prefix_check(strs->strings[mid - 1], p, plen, sep, &cmp2))
|
||||
mid--;
|
||||
} else
|
||||
cmp = strcmp(s, strs->strings[mid]);
|
||||
if (cmp == 0)
|
||||
cmp = strcmp(p, strs->strings[mid]);
|
||||
if (cmp == 0) {
|
||||
if (more)
|
||||
*more = mid + 1;
|
||||
return mid;
|
||||
}
|
||||
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
|
||||
left = mid + 1;
|
||||
}
|
||||
@@ -83,13 +131,13 @@ bsearch_strings(struct getarg_strings *strs, const char *s,
|
||||
int
|
||||
preserve_type(const char *p)
|
||||
{
|
||||
return bsearch_strings(&preserve, p, 0, '\0') > -1;
|
||||
return bsearch_strings(&preserve, p, '\0', 0) > -1;
|
||||
}
|
||||
|
||||
int
|
||||
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.
|
||||
*/
|
||||
int
|
||||
decorate_type(const char *p,
|
||||
struct decoration *deco)
|
||||
decorate_type(const char *p, struct decoration *deco, ssize_t *more)
|
||||
{
|
||||
ssize_t i;
|
||||
size_t plen = strlen(p);
|
||||
char **s[7];
|
||||
char *junk = NULL;
|
||||
char *cp;
|
||||
|
||||
deco->first = *more == -1;
|
||||
deco->decorated = 0;
|
||||
deco->field_type = NULL;
|
||||
if ((i = bsearch_strings(&decorate, p, plen, ':')) == -1)
|
||||
if ((i = bsearch_strings(&decorate, p, ':', more)) == -1)
|
||||
return 0;
|
||||
|
||||
deco->decorated = 1;
|
||||
deco->opt = 0;
|
||||
deco->ext = 0;
|
||||
deco->opt = deco->ext = deco->ptr = 0;
|
||||
deco->void_star = deco->struct_star = deco->heim_object = 0;
|
||||
deco->field_name = deco->copy_function_name = deco->free_function_name =
|
||||
deco->header_name = NULL;
|
||||
|
||||
@@ -153,7 +200,7 @@ decorate_type(const char *p,
|
||||
s[4] = &deco->header_name;
|
||||
s[5] = &junk;
|
||||
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 ||
|
||||
deco->field_name[0] == '\0' || deco->field_name[0] == '?') {
|
||||
@@ -164,10 +211,27 @@ decorate_type(const char *p,
|
||||
deco->opt = 1;
|
||||
*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;
|
||||
if (deco->ext && strcmp(deco->field_type, "void") == 0)
|
||||
deco->opt = deco->void_star = 1;
|
||||
if (deco->ext && deco->copy_function_name && !deco->copy_function_name[0])
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -389,14 +453,14 @@ main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (preserve.num_strings)
|
||||
qsort(preserve.strings, preserve.num_strings, sizeof(preserve.strings[0]),
|
||||
(int (*)(const void *, const void *))strcmp4qsort);
|
||||
mergesort_r(preserve.strings, preserve.num_strings,
|
||||
sizeof(preserve.strings[0]), strcmp4mergesort_r, "");
|
||||
if (seq.num_strings)
|
||||
qsort(seq.strings, seq.num_strings, sizeof(seq.strings),
|
||||
(int (*)(const void *, const void *))strcmp4qsort);
|
||||
mergesort_r(seq.strings, seq.num_strings, sizeof(seq.strings),
|
||||
strcmp4mergesort_r, "");
|
||||
if (decorate.num_strings)
|
||||
qsort(decorate.strings, decorate.num_strings, sizeof(decorate.strings[0]),
|
||||
(int (*)(const void *, const void *))strcmp4qsort);
|
||||
mergesort_r(decorate.strings, decorate.num_strings,
|
||||
sizeof(decorate.strings[0]), strcmp4mergesort_r, ":");
|
||||
|
||||
init_generate(file, name);
|
||||
|
||||
|
@@ -37,6 +37,7 @@
|
||||
#include <com_err.h>
|
||||
#include <vis.h>
|
||||
#include <vis-extras.h>
|
||||
#include <heimbase.h>
|
||||
|
||||
#ifndef 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;
|
||||
(f->release)(el);
|
||||
} else {
|
||||
/* A1_OP_TYPE_DECORATE_EXTERN */
|
||||
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);
|
||||
else
|
||||
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);
|
||||
} else {
|
||||
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);
|
||||
else
|
||||
memset(tel, 0, f->size);
|
||||
|
@@ -288,23 +288,12 @@ TESTExtensible ::= SEQUENCE {
|
||||
|
||||
TESTDecorated ::= SEQUENCE {
|
||||
version TESTuint32
|
||||
-- gets decorated with an ASN.1 type (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)
|
||||
-- gets decorated with varius fields (see test.opt)
|
||||
}
|
||||
|
||||
TESTNotDecorated ::= SEQUENCE {
|
||||
version TESTuint32
|
||||
-- should have the same encoding as TESTDecorated, TESTDecorated2, and
|
||||
-- TESTDecorated3
|
||||
-- should have the same encoding as TESTDecorated
|
||||
}
|
||||
|
||||
END
|
||||
|
@@ -1,4 +1,5 @@
|
||||
--sequence=TESTSeqOf
|
||||
--decorate=TESTDecorated:TESTuint32:version2?
|
||||
--decorate=TESTDecorated2:my_vers:version2:my_copy_vers:my_free_vers:"check-gen.h"
|
||||
--decorate=TESTDecorated3:void:privthing?:::
|
||||
--decorate=TESTDecorated:my_vers:version3:my_copy_vers:my_free_vers:"check-gen.h"
|
||||
--decorate=TESTDecorated:void *:privthing
|
||||
--decorate=TESTDecorated:heim_object_t:privobj
|
||||
|
Reference in New Issue
Block a user