asn1: Add support for decoration w/ external types

This adds support for asn1_compile --decorate=... variation that causes
decoration of an ASN.1 SET/SEQUENCE type with a field of a non-ASN.1
type.

This means we can now have an ASN.1 type to represent a request that can
then have a "hidden" field -- hidden in that it is neither encoded nor
decoded.  This field will be copied and freed when the decoration is of
an ASN.1 type or of a external, C type that comes with copy constructor
and destructor functions.  Decoration with a `void *` field which is
neither copied nor freed is also supported.

We may end up using this to, for example, replace the `hdb_entry_ex`
type by decorating `HDB_entry` with a C type that points to the `HDB` in
which the entry was found or to which it should be written.
This commit is contained in:
Nicolas Williams
2022-01-05 23:16:48 -06:00
parent 10fc7730d0
commit df3e08485b
18 changed files with 958 additions and 244 deletions

View File

@@ -178,9 +178,8 @@ free_type (const char *name, const Type *t, int preserve)
void
generate_type_free (const Symbol *s)
{
struct decoration deco;
int preserve = preserve_type(s->name) ? TRUE : FALSE;
int deco_opt;
char *ft, *fn;
fprintf (codefile, "void ASN1CALL\n"
"free_%s(%s *data)\n"
@@ -188,18 +187,46 @@ generate_type_free (const Symbol *s)
s->gen_name, s->gen_name);
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);
if (decorate_type(s->gen_name, &deco)) {
if (deco.ext &&
(deco.free_function_name == NULL ||
deco.free_function_name[0] == '\0')) {
/* Decorated with field of external type but no free function */
if (deco.opt || deco.void_star)
fprintf(codefile, "(data)->%s = 0;\n", deco.field_name);
else
fprintf(codefile,
"memset(&(data)->%s, 0, sizeof((data)->%s));\n",
deco.field_name, deco.field_name);
} else if (deco.ext) {
/* Decorated with field of external type w/ free function */
if (deco.opt) {
fprintf(codefile, "if ((data)->%s) {\n", deco.field_name);
fprintf(codefile, "%s((data)->%s);\n",
deco.free_function_name, deco.field_name);
fprintf(codefile, "(data)->%s = 0;\n", deco.field_name);
fprintf(codefile, "}\n");
} else {
fprintf(codefile, "%s(&(data)->%s);\n",
deco.free_function_name, deco.field_name);
fprintf(codefile,
"memset(&(data)->%s, 0, sizeof((data)->%s));\n",
deco.field_name, deco.field_name);
}
} else if (deco.opt) {
/* Decorated with optional field of ASN.1 type */
fprintf(codefile, "if ((data)->%s) {\n", deco.field_name);
fprintf(codefile, "free_%s((data)->%s);\n",
deco.field_type, deco.field_name);
fprintf(codefile, "free((data)->%s);\n", deco.field_name);
fprintf(codefile, "(data)->%s = NULL;\n", deco.field_name);
fprintf(codefile, "}\n");
} else {
fprintf(codefile, "free_%s(&(data)->%s);\n", ft, fn);
/* Decorated with required field of ASN.1 type */
fprintf(codefile, "free_%s(&(data)->%s);\n",
deco.field_type, deco.field_name);
}
free(ft);
free(fn);
free(deco.field_type);
}
fprintf (codefile, "}\n\n");
}