asn1: Add --decorate=... for internal bookkeeping
This option, `--decorate=TYPE-NAME:FIELD-TYPE:field-name[?]` allows one to add a field to any struct generated by the ASN.1 compiler for any SET or SEQUENCE type such that: - the field will be freed by the `free_TYPE_NAME()` function - the field will be copied by the `copy_TYPE_NAME()` function - the field will not be printed by the `print_TYPE_NAME()` function - the field will NOT be encoded or decoded This is useful for internal bookkeeping. The first use of this may well be for adding an optional field to `Principal` where information about name attributes will be stored, which will then allow us to have GSS name attributes for the krb5 mechanism w/o having to refactor the mechanism to use a different structure for representing `gss_name_t` mechnames than the one currently used (`Principal`; `krb5_principal` happens to be a typedef alias of `Principal *`). So w/o massive rototilling of the GSS krb5 mechanism we can have name attributes, _and_ we'll also be able to have those in the krb5 API as well w/o any massive rototilling there either.
This commit is contained in:
@@ -390,7 +390,10 @@ crmf_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/crmf.asn1 $(srcdir)/cr
|
|||||||
$(ASN1_COMPILE) --one-code-file --template --option-file=$(srcdir)/crmf.opt $(srcdir)/crmf.asn1 crmf_template_asn1 || (rm -f crmf_template_asn1_files ; exit 1)
|
$(ASN1_COMPILE) --one-code-file --template --option-file=$(srcdir)/crmf.opt $(srcdir)/crmf.asn1 crmf_template_asn1 || (rm -f crmf_template_asn1_files ; exit 1)
|
||||||
|
|
||||||
krb5_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/krb5.asn1 $(srcdir)/krb5.opt
|
krb5_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/krb5.asn1 $(srcdir)/krb5.opt
|
||||||
$(ASN1_COMPILE) --one-code-file --template --option-file=$(srcdir)/krb5.opt $(srcdir)/krb5.asn1 krb5_template_asn1 || (rm -f krb5_template_asn1_files ; exit 1)
|
$(ASN1_COMPILE) --one-code-file --template \
|
||||||
|
--option-file=$(srcdir)/krb5.opt \
|
||||||
|
--decorate='Principal:PrincipalNameAttrs:nameattrs?' \
|
||||||
|
$(srcdir)/krb5.asn1 krb5_template_asn1 || (rm -f krb5_template_asn1_files ; exit 1)
|
||||||
|
|
||||||
ocsp_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/ocsp.asn1
|
ocsp_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/ocsp.asn1
|
||||||
$(ASN1_COMPILE) --one-code-file --template --option-file=$(srcdir)/ocsp.opt $(srcdir)/ocsp.asn1 ocsp_template_asn1 || (rm -f ocsp_template_asn1_files ; exit 1)
|
$(ASN1_COMPILE) --one-code-file --template --option-file=$(srcdir)/ocsp.opt $(srcdir)/ocsp.asn1 ocsp_template_asn1 || (rm -f ocsp_template_asn1_files ; exit 1)
|
||||||
@@ -429,7 +432,10 @@ crmf_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/crmf.asn1 $(srcdir)/crmf.opt
|
|||||||
$(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) --option-file=$(srcdir)/crmf.opt $(srcdir)/crmf.asn1 crmf_asn1 || (rm -f crmf_asn1_files ; exit 1)
|
$(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) --option-file=$(srcdir)/crmf.opt $(srcdir)/crmf.asn1 crmf_asn1 || (rm -f crmf_asn1_files ; exit 1)
|
||||||
|
|
||||||
krb5_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/krb5.asn1 $(srcdir)/krb5.opt
|
krb5_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/krb5.asn1 $(srcdir)/krb5.opt
|
||||||
$(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) --option-file=$(srcdir)/krb5.opt $(srcdir)/krb5.asn1 krb5_asn1 || (rm -f krb5_asn1_files ; exit 1)
|
$(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) \
|
||||||
|
--option-file=$(srcdir)/krb5.opt \
|
||||||
|
--decorate='Principal:PrincipalNameAttrs:nameattrs?' \
|
||||||
|
$(srcdir)/krb5.asn1 krb5_asn1 || (rm -f krb5_asn1_files ; exit 1)
|
||||||
|
|
||||||
ocsp_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/ocsp.asn1
|
ocsp_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/ocsp.asn1
|
||||||
$(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) --option-file=$(srcdir)/ocsp.opt $(srcdir)/ocsp.asn1 ocsp_asn1 || (rm -f ocsp_asn1_files ; exit 1)
|
$(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) --option-file=$(srcdir)/ocsp.opt $(srcdir)/ocsp.asn1 ocsp_asn1 || (rm -f ocsp_asn1_files ; exit 1)
|
||||||
@@ -462,10 +468,17 @@ x690sample_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/x690sample.asn1
|
|||||||
$(ASN1_COMPILE) --one-code-file $(srcdir)/x690sample.asn1 x690sample_asn1 || (rm -f x690sample_asn1_files ; exit 1)
|
$(ASN1_COMPILE) --one-code-file $(srcdir)/x690sample.asn1 x690sample_asn1 || (rm -f x690sample_asn1_files ; exit 1)
|
||||||
|
|
||||||
test_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/test.asn1
|
test_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/test.asn1
|
||||||
$(ASN1_COMPILE) --one-code-file --template --sequence=TESTSeqOf $(srcdir)/test.asn1 test_template_asn1 || (rm -f test_template_asn1_files ; exit 1)
|
$(ASN1_COMPILE) --one-code-file \
|
||||||
|
--template \
|
||||||
|
--sequence=TESTSeqOf \
|
||||||
|
--decorate='TESTDecorated:TESTuint32:version2?' \
|
||||||
|
$(srcdir)/test.asn1 test_template_asn1 || (rm -f test_template_asn1_files ; exit 1)
|
||||||
|
|
||||||
test_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/test.asn1
|
test_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/test.asn1
|
||||||
$(ASN1_COMPILE) --one-code-file --sequence=TESTSeqOf $(srcdir)/test.asn1 test_asn1 || (rm -f test_asn1_files ; exit 1)
|
$(ASN1_COMPILE) --one-code-file \
|
||||||
|
--decorate='TESTDecorated:TESTuint32:version2?' \
|
||||||
|
--sequence=TESTSeqOf \
|
||||||
|
$(srcdir)/test.asn1 test_asn1 || (rm -f test_asn1_files ; exit 1)
|
||||||
|
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
|
@@ -202,6 +202,7 @@ $(gen_files_krb5) $(OBJ)\krb5_asn1.hx: $(BINDIR)\asn1_compile.exe krb5.asn1 krb5
|
|||||||
$(BINDIR)\asn1_compile.exe \
|
$(BINDIR)\asn1_compile.exe \
|
||||||
--template \
|
--template \
|
||||||
--one-code-file \
|
--one-code-file \
|
||||||
|
--decorate="Principal:PrincipalNameAttrs:nameattrs?" \
|
||||||
--option-file=$(SRCDIR)\krb5.opt \
|
--option-file=$(SRCDIR)\krb5.opt \
|
||||||
$(SRCDIR)\krb5.asn1 krb5_asn1 \
|
$(SRCDIR)\krb5.asn1 krb5_asn1 \
|
||||||
|| ($(RM) $(OBJ)\krb5_asn1.h ; exit /b 1)
|
|| ($(RM) $(OBJ)\krb5_asn1.h ; exit /b 1)
|
||||||
@@ -315,6 +316,7 @@ $(gen_files_test) $(OBJ)\test_asn1.hx: $(BINDIR)\asn1_compile.exe test.asn1
|
|||||||
cd $(OBJ)
|
cd $(OBJ)
|
||||||
$(BINDIR)\asn1_compile.exe \
|
$(BINDIR)\asn1_compile.exe \
|
||||||
--template \
|
--template \
|
||||||
|
--decorate='TESTDecorated:TESTuint32:version2?' \
|
||||||
--one-code-file --sequence=TESTSeqOf \
|
--one-code-file --sequence=TESTSeqOf \
|
||||||
$(SRCDIR)\test.asn1 test_asn1 \
|
$(SRCDIR)\test.asn1 test_asn1 \
|
||||||
|| ($(RM) $(OBJ)\test_asn1.h ; exit /b 1)
|
|| ($(RM) $(OBJ)\test_asn1.h ; exit /b 1)
|
||||||
@@ -324,7 +326,8 @@ $(gen_files_test_template) $(OBJ)\test_template_asn1.hx: $(BINDIR)\asn1_compile.
|
|||||||
cd $(OBJ)
|
cd $(OBJ)
|
||||||
$(BINDIR)\asn1_compile.exe \
|
$(BINDIR)\asn1_compile.exe \
|
||||||
--template \
|
--template \
|
||||||
--one-code-file --template \
|
--decorate='TESTDecorated:TESTuint32:version2?' \
|
||||||
|
--one-code-file \
|
||||||
--sequence=TESTSeqOf \
|
--sequence=TESTSeqOf \
|
||||||
$(SRCDIR)\test.asn1 test_template_asn1 \
|
$(SRCDIR)\test.asn1 test_template_asn1 \
|
||||||
|| ($(RM) $(OBJ)\test_template_asn1.h ; exit /b 1)
|
|| ($(RM) $(OBJ)\test_template_asn1.h ; exit /b 1)
|
||||||
|
@@ -843,7 +843,23 @@ In recent times the following features have been added:
|
|||||||
|
|
||||||
## Compiler Usage
|
## Compiler Usage
|
||||||
|
|
||||||
First, see the manual page `asn1_compile.1`:
|
The various options for the Heimdal ASN.1 compiler are described in its manual
|
||||||
|
page, which is included below.
|
||||||
|
|
||||||
|
The `--option-file=FILE` option is particularly useful, as it allows additional
|
||||||
|
compiler options to be read from a file.
|
||||||
|
|
||||||
|
The `--preserve-binary=TYPE-NAME` option is critical for signature validation
|
||||||
|
as it causes the decoder to save the encoding of the given type so that
|
||||||
|
signature validation code can easily find the original encoding and thus avoid
|
||||||
|
having to re-encode or resort to other hacks. E.g., we use this for preserving
|
||||||
|
the original encoding of the `tbsCertificate` field of `Certificate`.
|
||||||
|
|
||||||
|
The `--sequence=TYPE-NAME` causes the compiler to generate additional utility
|
||||||
|
functions for adding or removing items from the named type when it is a
|
||||||
|
`SEQUENCE OF` or `SET OF` type.
|
||||||
|
|
||||||
|
See the manual page `asn1_compile.1`:
|
||||||
|
|
||||||
```
|
```
|
||||||
ASN1_COMPILE(1) HEIMDAL General Commands Manual ASN1_COMPILE(1)
|
ASN1_COMPILE(1) HEIMDAL General Commands Manual ASN1_COMPILE(1)
|
||||||
@@ -856,6 +872,7 @@ SYNOPSIS
|
|||||||
[--encode-rfc1510-bit-string] [--decode-dce-ber]
|
[--encode-rfc1510-bit-string] [--decode-dce-ber]
|
||||||
[--support-ber] [--preserve-binary=TYPE-NAME]
|
[--support-ber] [--preserve-binary=TYPE-NAME]
|
||||||
[--sequence=TYPE-NAME] [--one-code-file] [--gen-name=NAME]
|
[--sequence=TYPE-NAME] [--one-code-file] [--gen-name=NAME]
|
||||||
|
[--decorate=TYPE-NAME:FIELD-TYPE:field-name[?]]
|
||||||
[--option-file=FILE] [--original-order] [--no-parse-units]
|
[--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]]
|
||||||
@@ -870,7 +887,7 @@ DESCRIPTION
|
|||||||
Use the “template” backend instead of the “codegen” backend
|
Use the “template” backend instead of the “codegen” backend
|
||||||
(which is the default backend). The template backend generates
|
(which is the default backend). The template backend generates
|
||||||
“templates” which are akin to bytecode, and which are interpreted
|
“templates” which are akin to bytecode, and which are interpreted
|
||||||
at run-time. The codegen backend generates C code for all func‐
|
at run-time. The codegen backend generates C code for all func-
|
||||||
tions directly, with no template interpretation. The template
|
tions directly, with no template interpretation. The template
|
||||||
backend scales better than the codegen backend because as we add
|
backend scales better than the codegen backend because as we add
|
||||||
support for more encoding rules the templates stay mostly the
|
support for more encoding rules the templates stay mostly the
|
||||||
@@ -897,13 +914,22 @@ DESCRIPTION
|
|||||||
--preserve-binary=TYPE-NAME
|
--preserve-binary=TYPE-NAME
|
||||||
Generate ‘_save’ fields in structs to preserve the original
|
Generate ‘_save’ fields in structs to preserve the original
|
||||||
encoding of some sub-value. This is useful for cryptographic
|
encoding of some sub-value. This is useful for cryptographic
|
||||||
applications to avoid having to re-encode values to check signa‐
|
applications to avoid having to re-encode values to check signa-
|
||||||
tures, etc.
|
tures, etc.
|
||||||
|
|
||||||
--sequence=TYPE-NAME
|
--sequence=TYPE-NAME
|
||||||
Generate add/remove functions for ‘SET OF’ and ‘SEQUENCE OF’
|
Generate add/remove functions for ‘SET OF’ and ‘SEQUENCE OF’
|
||||||
types.
|
types.
|
||||||
|
|
||||||
|
--decorate=TYPE-NAME:FIELD-TYPE:field-name[?]
|
||||||
|
Add to the TYPE-NAME SET or SEQUENCE type a field of the given
|
||||||
|
FIELD-TYPE and field-name, but do not encode or decode this
|
||||||
|
field. If the field-name ends in a question mark, then treat the
|
||||||
|
field as OPTIONAL for the purposes of copy/free function stubs.
|
||||||
|
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 not encoded.
|
||||||
|
|
||||||
--one-code-file
|
--one-code-file
|
||||||
Generate a single source code file. Otherwise a separate code
|
Generate a single source code file. Otherwise a separate code
|
||||||
file will be generated for every type.
|
file will be generated for every type.
|
||||||
@@ -916,7 +942,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
|
||||||
@@ -1065,9 +1091,9 @@ SYNOPSIS
|
|||||||
[-l -v | --version] [-l -h | --help] [FILE [TypeName...]]
|
[-l -v | --version] [-l -h | --help] [FILE [TypeName...]]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
asn1_print Dumps ASN.1 DER-encoded values. If one or more TypeName argu‐
|
asn1_print Dumps ASN.1 DER-encoded values. If one or more TypeName argu-
|
||||||
ments are given, then asn1_print will print the value in a JSON-like for‐
|
ments are given, then asn1_print will print the value in a JSON-like for-
|
||||||
mat using its knowledge of the ASN.1 modules defining those types, stop‐
|
mat using its knowledge of the ASN.1 modules defining those types, stop-
|
||||||
ping at the first type for which it can successfully decode the value.
|
ping at the first type for which it can successfully decode the value.
|
||||||
If TypeNames are given, they must be the names of ASN.1 types exported by
|
If TypeNames are given, they must be the names of ASN.1 types exported by
|
||||||
an ASN.1 modules that are compiled into asn1_print. Use the
|
an ASN.1 modules that are compiled into asn1_print. Use the
|
||||||
|
@@ -169,6 +169,7 @@
|
|||||||
#define A1_OP_OPENTYPE_ID (0xb0000000)
|
#define A1_OP_OPENTYPE_ID (0xb0000000)
|
||||||
#define A1_OP_OPENTYPE (0xc0000000)
|
#define A1_OP_OPENTYPE (0xc0000000)
|
||||||
#define A1_OP_NAME (0xd0000000)
|
#define A1_OP_NAME (0xd0000000)
|
||||||
|
#define A1_OP_TYPE_DECORATE (0xe0000000)
|
||||||
|
|
||||||
#define A1_FLAG_MASK (0x0f000000)
|
#define A1_FLAG_MASK (0x0f000000)
|
||||||
#define A1_FLAG_OPTIONAL (0x01000000)
|
#define A1_FLAG_OPTIONAL (0x01000000)
|
||||||
|
@@ -48,6 +48,7 @@
|
|||||||
.Op Fl Fl support-ber
|
.Op Fl Fl support-ber
|
||||||
.Op Fl Fl preserve-binary=TYPE-NAME
|
.Op Fl Fl preserve-binary=TYPE-NAME
|
||||||
.Op Fl Fl sequence=TYPE-NAME
|
.Op Fl Fl sequence=TYPE-NAME
|
||||||
|
.Op Fl Fl decorate=TYPE-NAME:FIELD-TYPE:field-name[?]
|
||||||
.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
|
||||||
@@ -109,6 +110,21 @@ Generate add/remove functions for
|
|||||||
and
|
and
|
||||||
.Sq SEQUENCE OF
|
.Sq SEQUENCE OF
|
||||||
types.
|
types.
|
||||||
|
.It Fl Fl decorate=TYPE-NAME:FIELD-TYPE:field-name[?]
|
||||||
|
Add to the
|
||||||
|
.Va TYPE-NAME
|
||||||
|
SET or SEQUENCE type a field of the given
|
||||||
|
.Va FIELD-TYPE
|
||||||
|
and
|
||||||
|
.Va field-name ,
|
||||||
|
but do not encode or decode this field.
|
||||||
|
If the
|
||||||
|
.Va field-name
|
||||||
|
ends in a question mark, then treat the field as OPTIONAL for
|
||||||
|
the purposes of copy/free function stubs.
|
||||||
|
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 not encoded.
|
||||||
.It Fl Fl one-code-file
|
.It Fl Fl one-code-file
|
||||||
Generate a single source code file.
|
Generate a single source code file.
|
||||||
Otherwise a separate code file will be generated for every type.
|
Otherwise a separate code file will be generated for every type.
|
||||||
|
@@ -100,9 +100,9 @@ test_principal (void)
|
|||||||
|
|
||||||
|
|
||||||
Principal values[] = {
|
Principal values[] = {
|
||||||
{ { KRB5_NT_PRINCIPAL, { 1, lha_principal } }, "SU.SE" },
|
{ { KRB5_NT_PRINCIPAL, { 1, lha_principal } }, "SU.SE", NULL },
|
||||||
{ { KRB5_NT_PRINCIPAL, { 2, lharoot_princ } }, "SU.SE" },
|
{ { KRB5_NT_PRINCIPAL, { 2, lharoot_princ } }, "SU.SE", NULL },
|
||||||
{ { KRB5_NT_SRV_HST, { 2, datan_princ } }, "E.KTH.SE" }
|
{ { KRB5_NT_SRV_HST, { 2, datan_princ } }, "E.KTH.SE", NULL }
|
||||||
};
|
};
|
||||||
int i, ret;
|
int i, ret;
|
||||||
int ntests = sizeof(tests) / sizeof(*tests);
|
int ntests = sizeof(tests) / sizeof(*tests);
|
||||||
@@ -1016,6 +1016,50 @@ test_choice (void)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Test --decorate=TYPE:FIELD-TYPE:field-name[?] */
|
||||||
|
static int
|
||||||
|
test_decorated(void)
|
||||||
|
{
|
||||||
|
TESTNotDecorated tnd;
|
||||||
|
TESTDecorated td;
|
||||||
|
size_t len, size;
|
||||||
|
void *ptr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
memset(&td, 0, sizeof(td));
|
||||||
|
memset(&tnd, 0, sizeof(tnd));
|
||||||
|
|
||||||
|
td.version = 3;
|
||||||
|
if ((td.version2 = malloc(sizeof(*td.version2))) == NULL)
|
||||||
|
errx(1, "out of memory");
|
||||||
|
*td.version2 = 5;
|
||||||
|
ASN1_MALLOC_ENCODE(TESTDecorated, ptr, len, &td, &size, ret);
|
||||||
|
if (ret) {
|
||||||
|
warnx("could not encode a TESTDecorated struct");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
ret = decode_TESTNotDecorated(ptr, len, &tnd, &size);
|
||||||
|
if (ret) {
|
||||||
|
warnx("could not decode a TESTDecorated struct as TESTNotDecorated");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (size != len) {
|
||||||
|
warnx("TESTDecorated encoded size mismatch");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (td.version != tnd.version) {
|
||||||
|
warnx("TESTDecorated did not decode as a TESTNotDecorated correctly");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
free_TESTDecorated(&td);
|
||||||
|
if (td.version2) {
|
||||||
|
warnx("free_TESTDecorated() did not work correctly");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cmp_TESTImplicit (void *a, void *b)
|
cmp_TESTImplicit (void *a, void *b)
|
||||||
{
|
{
|
||||||
@@ -2493,6 +2537,8 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
DO_ONE(test_default);
|
DO_ONE(test_default);
|
||||||
|
|
||||||
|
DO_ONE(test_decorated);
|
||||||
|
|
||||||
#if ASN1_IOS_SUPPORTED
|
#if ASN1_IOS_SUPPORTED
|
||||||
DO_ONE(test_ios);
|
DO_ONE(test_ios);
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1355,6 +1355,8 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t
|
|||||||
case TSet:
|
case TSet:
|
||||||
case TSequence: {
|
case TSequence: {
|
||||||
Member *m;
|
Member *m;
|
||||||
|
char *ft, *fn;
|
||||||
|
int deco_opt;
|
||||||
|
|
||||||
getnewbasename(&newbasename, typedefp || level == 0, basename, name);
|
getnewbasename(&newbasename, typedefp || level == 0, basename, name);
|
||||||
|
|
||||||
@@ -1395,6 +1397,13 @@ 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 (decorate_type(newbasename, &ft, &fn, &deco_opt)) {
|
||||||
|
space(level + 1);
|
||||||
|
fprintf(headerfile, "%s %s%s;\n", ft, deco_opt ? "*" : "", fn);
|
||||||
|
fprintf(jsonfile, ",\"decorate\":{\"type\":\"%s\",\"name\":\"%s\", \"optional\":%s}", ft, fn, deco_opt ? "true" : "false");
|
||||||
|
free(ft);
|
||||||
|
free(fn);
|
||||||
|
}
|
||||||
space(level);
|
space(level);
|
||||||
fprintf (headerfile, "} %s;\n", name);
|
fprintf (headerfile, "} %s;\n", name);
|
||||||
break;
|
break;
|
||||||
|
@@ -229,6 +229,9 @@ void
|
|||||||
generate_type_copy (const Symbol *s)
|
generate_type_copy (const Symbol *s)
|
||||||
{
|
{
|
||||||
int preserve = preserve_type(s->name) ? TRUE : FALSE;
|
int preserve = preserve_type(s->name) ? TRUE : FALSE;
|
||||||
|
int save_used_fail = used_fail;
|
||||||
|
int deco_opt;
|
||||||
|
char *ft, *fn;
|
||||||
|
|
||||||
used_fail = 0;
|
used_fail = 0;
|
||||||
|
|
||||||
@@ -238,6 +241,19 @@ 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, &ft, &fn, &deco_opt)) {
|
||||||
|
if (deco_opt) {
|
||||||
|
fprintf(codefile, "if (from->%s) {\n", fn);
|
||||||
|
fprintf(codefile, "(to)->%s = malloc(sizeof(*(to)->%s));\n", fn, fn);
|
||||||
|
fprintf(codefile, "if (copy_%s((from)->%s, (to)->%s)) goto fail;\n", ft, fn, fn);
|
||||||
|
fprintf(codefile, "}\n");
|
||||||
|
} else {
|
||||||
|
fprintf(codefile, "if (copy_%s(&(from)->%s, &(to)->%s)) goto fail;\n", ft, fn, fn);
|
||||||
|
}
|
||||||
|
used_fail++;
|
||||||
|
free(ft);
|
||||||
|
free(fn);
|
||||||
|
}
|
||||||
fprintf (codefile, "return 0;\n");
|
fprintf (codefile, "return 0;\n");
|
||||||
|
|
||||||
if (used_fail)
|
if (used_fail)
|
||||||
@@ -248,5 +264,6 @@ generate_type_copy (const Symbol *s)
|
|||||||
|
|
||||||
fprintf(codefile,
|
fprintf(codefile,
|
||||||
"}\n\n");
|
"}\n\n");
|
||||||
|
used_fail = save_used_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -119,7 +119,7 @@ free_type (const char *name, const Type *t, int preserve)
|
|||||||
have_ellipsis->label,
|
have_ellipsis->label,
|
||||||
name, have_ellipsis->gen_name);
|
name, have_ellipsis->gen_name);
|
||||||
fprintf(codefile, "}\n");
|
fprintf(codefile, "}\n");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TSetOf:
|
case TSetOf:
|
||||||
@@ -179,6 +179,8 @@ void
|
|||||||
generate_type_free (const Symbol *s)
|
generate_type_free (const Symbol *s)
|
||||||
{
|
{
|
||||||
int preserve = preserve_type(s->name) ? TRUE : FALSE;
|
int preserve = preserve_type(s->name) ? TRUE : FALSE;
|
||||||
|
int deco_opt;
|
||||||
|
char *ft, *fn;
|
||||||
|
|
||||||
fprintf (codefile, "void ASN1CALL\n"
|
fprintf (codefile, "void ASN1CALL\n"
|
||||||
"free_%s(%s *data)\n"
|
"free_%s(%s *data)\n"
|
||||||
@@ -186,6 +188,19 @@ 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, &ft, &fn, &deco_opt)) {
|
||||||
|
if (deco_opt) {
|
||||||
|
fprintf(codefile, "if ((data)->%s) {\n", fn);
|
||||||
|
fprintf(codefile, "free_%s((data)->%s);\n", ft, fn);
|
||||||
|
fprintf(codefile, "free((data)->%s);\n", fn);
|
||||||
|
fprintf(codefile, "(data)->%s = NULL;\n", fn);
|
||||||
|
fprintf(codefile, "}\n");
|
||||||
|
} else {
|
||||||
|
fprintf(codefile, "free_%s(&(data)->%s);\n", ft, fn);
|
||||||
|
}
|
||||||
|
free(ft);
|
||||||
|
free(fn);
|
||||||
|
}
|
||||||
fprintf (codefile, "}\n\n");
|
fprintf (codefile, "}\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -144,6 +144,7 @@ int is_tagged_type(const Type *);
|
|||||||
|
|
||||||
int preserve_type(const char *);
|
int preserve_type(const char *);
|
||||||
int seq_type(const char *);
|
int seq_type(const char *);
|
||||||
|
int decorate_type(const char *, char **, char **, int *);
|
||||||
|
|
||||||
void generate_header_of_codefile(const char *);
|
void generate_header_of_codefile(const char *);
|
||||||
void close_codefile(void);
|
void close_codefile(void);
|
||||||
|
@@ -1063,6 +1063,8 @@ template_members(struct templatehead *temp,
|
|||||||
Member *m;
|
Member *m;
|
||||||
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;
|
||||||
|
int deco_opt;
|
||||||
|
char *ft, *fn;
|
||||||
|
|
||||||
if (isstruct && t->actual_parameter)
|
if (isstruct && t->actual_parameter)
|
||||||
get_open_type_defn_fields(t, &typeidmember, &opentypemember,
|
get_open_type_defn_fields(t, &typeidmember, &opentypemember,
|
||||||
@@ -1102,6 +1104,17 @@ 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, &ft, &fn, &deco_opt)) {
|
||||||
|
char *poffset2;
|
||||||
|
|
||||||
|
poffset2 = partial_offset(basetype, fn, 1, isstruct);
|
||||||
|
add_line_pointer(temp, ft, poffset2, "A1_OP_TYPE_DECORATE %s",
|
||||||
|
deco_opt ? "|A1_FLAG_OPTIONAL" : "");
|
||||||
|
free(poffset2);
|
||||||
|
free(ft);
|
||||||
|
free(fn);
|
||||||
|
}
|
||||||
|
|
||||||
if (isstruct)
|
if (isstruct)
|
||||||
template_names(temp, basetype, t);
|
template_names(temp, basetype, t);
|
||||||
break;
|
break;
|
||||||
@@ -1114,6 +1127,8 @@ template_members(struct templatehead *temp,
|
|||||||
Member *m;
|
Member *m;
|
||||||
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;
|
||||||
|
int deco_opt;
|
||||||
|
char *ft, *fn;
|
||||||
|
|
||||||
if (isstruct && t->actual_parameter)
|
if (isstruct && t->actual_parameter)
|
||||||
get_open_type_defn_fields(t, &typeidmember, &opentypemember,
|
get_open_type_defn_fields(t, &typeidmember, &opentypemember,
|
||||||
@@ -1153,6 +1168,17 @@ 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, &ft, &fn, &deco_opt)) {
|
||||||
|
char *poffset2;
|
||||||
|
|
||||||
|
poffset2 = partial_offset(basetype, fn, 1, isstruct);
|
||||||
|
add_line_pointer(temp, ft, poffset2, "A1_OP_TYPE_DECORATE %s",
|
||||||
|
deco_opt ? "|A1_FLAG_OPTIONAL" : "");
|
||||||
|
free(poffset2);
|
||||||
|
free(ft);
|
||||||
|
free(fn);
|
||||||
|
}
|
||||||
|
|
||||||
if (isstruct)
|
if (isstruct)
|
||||||
template_names(temp, basetype, t);
|
template_names(temp, basetype, t);
|
||||||
break;
|
break;
|
||||||
|
@@ -39,6 +39,7 @@ extern FILE *yyin;
|
|||||||
|
|
||||||
static getarg_strings preserve;
|
static getarg_strings preserve;
|
||||||
static getarg_strings seq;
|
static getarg_strings seq;
|
||||||
|
static getarg_strings decorate;
|
||||||
|
|
||||||
int
|
int
|
||||||
preserve_type(const char *p)
|
preserve_type(const char *p)
|
||||||
@@ -53,13 +54,49 @@ preserve_type(const char *p)
|
|||||||
int
|
int
|
||||||
seq_type(const char *p)
|
seq_type(const char *p)
|
||||||
{
|
{
|
||||||
int i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < seq.num_strings; i++)
|
for (i = 0; i < seq.num_strings; i++)
|
||||||
if (strcmp(seq.strings[i], p) == 0)
|
if (strcmp(seq.strings[i], p) == 0)
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
decorate_type(const char *p, char **field_type, char **field_name, int *opt)
|
||||||
|
{
|
||||||
|
size_t plen = strlen(p);
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
*field_type = NULL;
|
||||||
|
*field_name = NULL;
|
||||||
|
*opt = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < decorate.num_strings; i++) {
|
||||||
|
const char *r;
|
||||||
|
char *q;
|
||||||
|
|
||||||
|
if (strncmp(decorate.strings[i], p, plen) != 0)
|
||||||
|
continue;
|
||||||
|
if (decorate.strings[i][plen] != ':')
|
||||||
|
errx(1, "--decorate argument missing field type");
|
||||||
|
|
||||||
|
p = &decorate.strings[i][plen + 1];
|
||||||
|
if ((r = strchr(p, ':')) == NULL)
|
||||||
|
errx(1, "--decorate argument missing field name");
|
||||||
|
r++;
|
||||||
|
*field_type = estrdup(p);
|
||||||
|
*(strchr(*field_type, ':')) = '\0';
|
||||||
|
*field_name = estrdup(r);
|
||||||
|
if ((q = strchr(*field_name, '?'))) {
|
||||||
|
*q = '\0';
|
||||||
|
*opt = 1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
my_basename(const char *fn)
|
my_basename(const char *fn)
|
||||||
{
|
{
|
||||||
@@ -113,6 +150,8 @@ struct getargs args[] = {
|
|||||||
"verification)", "TYPE-NAME" },
|
"verification)", "TYPE-NAME" },
|
||||||
{ "sequence", 0, arg_strings, &seq,
|
{ "sequence", 0, arg_strings, &seq,
|
||||||
"Generate add/remove functions for SEQUENCE OF types", "TYPE-NAME" },
|
"Generate add/remove functions for SEQUENCE OF types", "TYPE-NAME" },
|
||||||
|
{ "decorate", 0, arg_strings, &decorate,
|
||||||
|
"Generate private field for SEQUENCE/SET type", "TYPE-NAME:FIELD_TYPE:field_name[?]" },
|
||||||
{ "one-code-file", 0, arg_flag, &one_code_file, NULL, NULL },
|
{ "one-code-file", 0, arg_flag, &one_code_file, NULL, NULL },
|
||||||
{ "gen-name", 0, arg_string, &name,
|
{ "gen-name", 0, arg_string, &name,
|
||||||
"Name of generated module", "NAME" },
|
"Name of generated module", "NAME" },
|
||||||
|
@@ -774,6 +774,7 @@ _asn1_decode(const struct asn1_template *t, unsigned flags,
|
|||||||
return ret;
|
return ret;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case A1_OP_TYPE_DECORATE: break;
|
||||||
case A1_OP_NAME: break;
|
case A1_OP_NAME: break;
|
||||||
case A1_OP_DEFVAL:
|
case A1_OP_DEFVAL:
|
||||||
tdefval = t;
|
tdefval = t;
|
||||||
@@ -1417,6 +1418,7 @@ _asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const
|
|||||||
}
|
}
|
||||||
case A1_OP_NAME: break;
|
case A1_OP_NAME: break;
|
||||||
case A1_OP_DEFVAL: break;
|
case A1_OP_DEFVAL: break;
|
||||||
|
case A1_OP_TYPE_DECORATE: break;
|
||||||
case A1_OP_TYPE:
|
case A1_OP_TYPE:
|
||||||
case A1_OP_TYPE_EXTERN: {
|
case A1_OP_TYPE_EXTERN: {
|
||||||
size_t newsize;
|
size_t newsize;
|
||||||
@@ -1992,6 +1994,7 @@ _asn1_length(const struct asn1_template *t, const void *data)
|
|||||||
}
|
}
|
||||||
case A1_OP_NAME: break;
|
case A1_OP_NAME: break;
|
||||||
case A1_OP_DEFVAL: break;
|
case A1_OP_DEFVAL: break;
|
||||||
|
case A1_OP_TYPE_DECORATE: break;
|
||||||
case A1_OP_TYPE:
|
case A1_OP_TYPE:
|
||||||
case A1_OP_TYPE_EXTERN: {
|
case A1_OP_TYPE_EXTERN: {
|
||||||
const void *el = DPOC(data, t->offset);
|
const void *el = DPOC(data, t->offset);
|
||||||
@@ -2253,6 +2256,7 @@ _asn1_free(const struct asn1_template *t, void *data)
|
|||||||
}
|
}
|
||||||
case A1_OP_NAME: break;
|
case A1_OP_NAME: break;
|
||||||
case A1_OP_DEFVAL: break;
|
case A1_OP_DEFVAL: break;
|
||||||
|
case A1_OP_TYPE_DECORATE:
|
||||||
case A1_OP_TYPE:
|
case A1_OP_TYPE:
|
||||||
case A1_OP_TYPE_EXTERN: {
|
case A1_OP_TYPE_EXTERN: {
|
||||||
void *el = DPO(data, t->offset);
|
void *el = DPO(data, t->offset);
|
||||||
@@ -2264,7 +2268,7 @@ _asn1_free(const struct asn1_template *t, void *data)
|
|||||||
el = *pel;
|
el = *pel;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
|
if ((t->tt & A1_OP_MASK) == A1_OP_TYPE || (t->tt & A1_OP_MASK) == A1_OP_TYPE_DECORATE) {
|
||||||
_asn1_free(t->ptr, el);
|
_asn1_free(t->ptr, el);
|
||||||
} else {
|
} else {
|
||||||
const struct asn1_type_func *f = t->ptr;
|
const struct asn1_type_func *f = t->ptr;
|
||||||
@@ -2541,6 +2545,7 @@ _asn1_print(const struct asn1_template *t,
|
|||||||
break;
|
break;
|
||||||
case A1_OP_NAME: break;
|
case A1_OP_NAME: break;
|
||||||
case A1_OP_DEFVAL: break;
|
case A1_OP_DEFVAL: break;
|
||||||
|
case A1_OP_TYPE_DECORATE: break; /* We could probably print this though */
|
||||||
case A1_OP_TYPE:
|
case A1_OP_TYPE:
|
||||||
case A1_OP_TYPE_EXTERN: {
|
case A1_OP_TYPE_EXTERN: {
|
||||||
const void *el = DPOC(data, t->offset);
|
const void *el = DPOC(data, t->offset);
|
||||||
@@ -2858,6 +2863,7 @@ _asn1_copy(const struct asn1_template *t, const void *from, void *to)
|
|||||||
}
|
}
|
||||||
case A1_OP_NAME: break;
|
case A1_OP_NAME: break;
|
||||||
case A1_OP_DEFVAL: break;
|
case A1_OP_DEFVAL: break;
|
||||||
|
case A1_OP_TYPE_DECORATE:
|
||||||
case A1_OP_TYPE:
|
case A1_OP_TYPE:
|
||||||
case A1_OP_TYPE_EXTERN: {
|
case A1_OP_TYPE_EXTERN: {
|
||||||
const void *fel = DPOC(from, t->offset);
|
const void *fel = DPOC(from, t->offset);
|
||||||
|
@@ -286,4 +286,14 @@ TESTExtensible ::= SEQUENCE {
|
|||||||
extensions SEQUENCE OF TESTExtension
|
extensions SEQUENCE OF TESTExtension
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TESTDecorated ::= SEQUENCE {
|
||||||
|
version TESTuint32
|
||||||
|
-- gets decorated
|
||||||
|
}
|
||||||
|
|
||||||
|
TESTNotDecorated ::= SEQUENCE {
|
||||||
|
version TESTuint32
|
||||||
|
-- should have the same encoding as TESTDecorated
|
||||||
|
}
|
||||||
|
|
||||||
END
|
END
|
||||||
|
Reference in New Issue
Block a user