2 * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 extern const char *enum_prefix
;
39 extern int prefix_enum
;
43 FILE *privheaderfile
, *headerfile
, *oidsfile
, *codefile
, *logfile
, *templatefile
;
48 static const char *orig_filename
;
49 static char *privheader
, *header
, *template;
50 static const char *headerbase
= STEM
;
52 /* XXX same as der_length_tag */
54 length_tag(unsigned int tag
)
76 static struct import
*imports
= NULL
;
79 add_import (const char *module
)
81 struct import
*tmp
= emalloc (sizeof(*tmp
));
87 fprintf (headerfile
, "#include <%s_asn1.h>\n", module
);
91 * List of all exported symbols
100 static struct sexport
*exports
= NULL
;
103 add_export (const char *name
)
105 struct sexport
*tmp
= emalloc (sizeof(*tmp
));
113 is_export(const char *name
)
117 if (exports
== NULL
) /* no export list, all exported */
120 for (tmp
= exports
; tmp
!= NULL
; tmp
= tmp
->next
) {
121 if (strcmp(tmp
->name
, name
) == 0) {
132 return orig_filename
;
136 init_generate (const char *filename
, const char *base
)
140 orig_filename
= filename
;
142 headerbase
= strdup(base
);
143 if (headerbase
== NULL
)
147 /* public header file */
148 if (asprintf(&header
, "%s.h", headerbase
) < 0 || header
== NULL
)
150 if (asprintf(&fn
, "%s.hx", headerbase
) < 0 || fn
== NULL
)
152 headerfile
= fopen (fn
, "w");
153 if (headerfile
== NULL
)
154 err (1, "open %s", fn
);
158 /* private header file */
159 if (asprintf(&privheader
, "%s-priv.h", headerbase
) < 0 || privheader
== NULL
)
161 if (asprintf(&fn
, "%s-priv.hx", headerbase
) < 0 || fn
== NULL
)
163 privheaderfile
= fopen (fn
, "w");
164 if (privheaderfile
== NULL
)
165 err (1, "open %s", fn
);
170 if (asprintf(&template, "%s-template.x", headerbase
) < 0 || template == NULL
)
173 "/* Generated from %s */\n"
174 "/* Do not edit */\n\n",
178 "#define __%s_h__\n\n", headerbase
, headerbase
);
180 "#include <stddef.h>\n"
181 "#include <stdint.h>\n"
182 "#include <time.h>\n\n");
184 "#ifndef __asn1_common_definitions__\n"
185 "#define __asn1_common_definitions__\n\n");
187 "#ifndef __HEIM_BASE_DATA__\n"
188 "#define __HEIM_BASE_DATA__ 1\n"
189 "struct heim_base_data {\n"
193 "typedef struct heim_base_data heim_octet_string;\n"
196 "typedef struct heim_integer {\n"
200 "} heim_integer;\n\n");
202 "typedef char *heim_general_string;\n\n"
205 "typedef char *heim_utf8_string;\n\n"
208 "typedef struct heim_base_data heim_printable_string;\n\n"
211 "typedef struct heim_base_data heim_ia5_string;\n\n"
214 "typedef struct heim_bmp_string {\n"
217 "} heim_bmp_string;\n\n");
219 "typedef struct heim_universal_string {\n"
222 "} heim_universal_string;\n\n");
224 "typedef char *heim_visible_string;\n\n"
227 "typedef struct heim_oid {\n"
229 " unsigned *components;\n"
232 "typedef struct heim_bit_string {\n"
235 "} heim_bit_string;\n\n");
237 "typedef struct heim_base_data heim_any;\n"
238 "typedef struct heim_base_data heim_any_set;\n"
239 "typedef struct heim_base_data HEIM_ANY;\n"
240 "typedef struct heim_base_data HEIM_ANY_SET;\n\n");
243 "enum asn1_print_flags {\n"
244 " ASN1_PRINT_INDENT = 1,\n"
246 fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R) \\\n"
248 " (BL) = length_##T((S)); \\\n"
249 " (B) = malloc((BL)); \\\n"
250 " if((B) == NULL) { \\\n"
252 " (R) = ENOMEM; \\\n"
254 " (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \\\n"
256 " if((R) != 0) { \\\n"
264 fputs("#ifdef _WIN32\n"
266 "#define ASN1EXP __declspec(dllimport)\n"
270 "#define ASN1CALL __stdcall\n"
276 fprintf (headerfile
, "struct units;\n\n");
277 fprintf (headerfile
, "#endif\n\n");
278 if (asprintf(&fn
, "%s_files", base
) < 0 || fn
== NULL
)
280 logfile
= fopen(fn
, "w");
282 err (1, "open %s", fn
);
286 if (asprintf(&fn
, "%s_oids.x", base
) < 0 || fn
== NULL
)
288 oidsfile
= fopen(fn
, "w");
289 if (oidsfile
== NULL
)
290 err (1, "open %s", fn
);
291 if (asprintf(&fn
, "%s_syms.x", base
) < 0 || fn
== NULL
)
293 symsfile
= fopen(fn
, "w");
294 if (symsfile
== NULL
)
295 err (1, "open %s", fn
);
299 /* if one code file, write into the one codefile */
303 templatefile
= fopen (template, "w");
304 if (templatefile
== NULL
)
305 err (1, "open %s", template);
307 fprintf (templatefile
,
308 "/* Generated from %s */\n"
309 "/* Do not edit */\n\n"
310 "#include <stdio.h>\n"
311 "#include <stdlib.h>\n"
312 "#include <time.h>\n"
313 "#include <string.h>\n"
314 "#include <errno.h>\n"
315 "#include <limits.h>\n"
316 "#include <asn1_err.h>\n"
321 fprintf (templatefile
,
325 "#include <asn1-template.h>\n",
332 close_generate (void)
334 fprintf (headerfile
, "#endif /* __%s_h__ */\n", headerbase
);
336 if (headerfile
&& fclose(headerfile
) == EOF
)
337 err(1, "writes to public header file failed");
338 if (privheaderfile
&& fclose(privheaderfile
) == EOF
)
339 err(1, "writes to private header file failed");
340 if (templatefile
&& fclose(templatefile
) == EOF
)
341 err(1, "writes to template file failed");
343 fprintf(logfile
, "\n");
344 if (fclose(logfile
) == EOF
)
345 err(1, "writes to log file failed");
350 gen_assign_defval(const char *var
, struct value
*val
)
354 fprintf(codefile
, "if((%s = strdup(\"%s\")) == NULL)\nreturn ENOMEM;\n", var
, val
->u
.stringvalue
);
357 fprintf(codefile
, "%s = %lld;\n",
358 var
, (long long)val
->u
.integervalue
);
361 if(val
->u
.booleanvalue
)
362 fprintf(codefile
, "%s = 1;\n", var
);
364 fprintf(codefile
, "%s = 0;\n", var
);
372 gen_compare_defval(const char *var
, struct value
*val
)
376 fprintf(codefile
, "if(strcmp(%s, \"%s\") != 0)\n", var
, val
->u
.stringvalue
);
379 fprintf(codefile
, "if(%s != %lld)\n",
380 var
, (long long)val
->u
.integervalue
);
383 if(val
->u
.booleanvalue
)
384 fprintf(codefile
, "if(!%s)\n", var
);
386 fprintf(codefile
, "if(%s)\n", var
);
394 generate_header_of_codefile(const char *name
)
396 char *filename
= NULL
;
398 if (codefile
!= NULL
)
401 if (asprintf (&filename
, "%s_%s.x", STEM
, name
) < 0 || filename
== NULL
)
403 codefile
= fopen (filename
, "w");
404 if (codefile
== NULL
)
405 err (1, "fopen %s", filename
);
407 fprintf(logfile
, "%s ", filename
);
411 "/* Generated from %s */\n"
412 "/* Do not edit */\n\n"
413 "#define ASN1_LIB\n\n"
414 "#include <stdio.h>\n"
415 "#include <stdlib.h>\n"
416 "#include <time.h>\n"
417 "#include <string.h>\n"
418 "#include <errno.h>\n"
419 "#include <limits.h>\n"
429 "#include <asn1_err.h>\n"
431 "#include <asn1-template.h>\n\n");
433 if (parse_units_flag
)
435 "#include <parse_units.h>\n\n");
438 fprintf(codefile
, "#pragma warning(disable: 4101)\n\n");
445 if (codefile
== NULL
)
448 if (fclose(codefile
) == EOF
)
449 err(1, "writes to source code file failed");
455 generate_constant (const Symbol
*s
)
457 switch(s
->value
->type
) {
462 * Work around the fact that OpenSSL defines macros for PKIX constants
463 * that we want to generate as enums, which causes conflicts for things
464 * like ub-name (ub_name).
470 "enum { %s = %lld };\n\n",
471 s
->gen_name
, s
->gen_name
, s
->gen_name
,
472 (long long)s
->value
->u
.integervalue
);
473 if (is_export(s
->name
))
474 fprintf(symsfile
, "ASN1_SYM_INTVAL(\"%s\", \"%s\", %s, %lld)\n",
475 s
->name
, s
->gen_name
, s
->gen_name
,
476 (long long)s
->value
->u
.integervalue
);
482 case objectidentifiervalue
: {
483 struct objid
*o
, **list
;
488 generate_header_of_codefile(s
->gen_name
);
491 for (o
= s
->value
->u
.objectidentifiervalue
; o
!= NULL
; o
= o
->next
)
494 printf("s->gen_name: %s",s
->gen_name
);
498 list
= emalloc(sizeof(*list
) * len
);
501 for (o
= s
->value
->u
.objectidentifiervalue
; o
!= NULL
; o
= o
->next
)
504 fprintf (headerfile
, "/* OBJECT IDENTIFIER %s ::= { ", s
->name
);
505 for (i
= len
; i
> 0; i
--) {
507 fprintf(headerfile
, "%s(%d) ",
508 o
->label
? o
->label
: "label-less", o
->value
);
511 fprintf (codefile
, "static unsigned oid_%s_variable_num[%lu] = {",
512 s
->gen_name
, (unsigned long)len
);
513 for (i
= len
; i
> 0; i
--) {
514 fprintf(codefile
, "%d%s ", list
[i
- 1]->value
, i
> 1 ? "," : "");
516 fprintf(codefile
, "};\n");
518 fprintf (codefile
, "const heim_oid asn1_oid_%s = "
519 "{ %lu, oid_%s_variable_num };\n\n",
520 s
->gen_name
, (unsigned long)len
, s
->gen_name
);
522 fprintf(oidsfile
, "DEFINE_OID_WITH_NAME(%s)\n", s
->gen_name
);
523 if (is_export(s
->name
))
524 fprintf(symsfile
, "ASN1_SYM_OID(\"%s\", \"%s\", %s)\n",
525 s
->name
, s
->gen_name
, s
->gen_name
);
531 gen_upper
= strdup(s
->gen_name
);
532 len
= strlen(gen_upper
);
533 for (i
= 0; i
< len
; i
++)
534 gen_upper
[i
] = toupper((int)s
->gen_name
[i
]);
536 fprintf (headerfile
, "} */\n");
538 "extern ASN1EXP const heim_oid asn1_oid_%s;\n"
539 "#define ASN1_OID_%s (&asn1_oid_%s)\n\n",
557 is_tagged_type(const Type
*t
)
560 * Start by chasing aliasings like this:
567 * to <Type0>, then check if <Type0> is tagged.
569 while (t
->type
== TType
) {
572 else if (t
->symbol
&& t
->symbol
->type
)
578 if (t
->type
== TTag
&& t
->tag
.tagenv
== TE_EXPLICIT
)
580 if (t
->type
== TTag
) {
582 return is_tagged_type(t
->subtype
);
583 if (t
->symbol
&& t
->symbol
->type
)
584 return is_tagged_type(t
->symbol
->type
);
585 /* This is the tag */
592 is_primitive_type(const Type
*t
)
595 * Start by chasing aliasings like this:
602 * to <Type0>, then check if <Type0> is primitive.
604 while (t
->type
== TType
&&
607 if (t
->symbol
->type
->type
== TType
)
608 t
= t
->symbol
->type
; /* Alias */
609 else if (t
->symbol
->type
->type
== TTag
&&
610 t
->symbol
->type
->tag
.tagenv
== TE_IMPLICIT
)
612 * IMPLICIT-tagged alias, something like:
614 * Type0 ::= [0] IMPLICIT ...
618 return is_primitive_type(t
->symbol
->type
);
623 /* EXPLICIT non-UNIVERSAL tags are always constructed */
624 if (t
->type
== TTag
&& t
->tag
.tagclass
!= ASN1_C_UNIV
&&
625 t
->tag
.tagenv
== TE_EXPLICIT
)
627 if (t
->symbol
&& t
->symbol
->type
) {
628 /* EXPLICIT non-UNIVERSAL tags are constructed */
629 if (t
->symbol
->type
->type
== TTag
&&
630 t
->symbol
->type
->tag
.tagclass
!= ASN1_C_UNIV
&&
631 t
->symbol
->type
->tag
.tagenv
== TE_EXPLICIT
)
633 /* EXPLICIT UNIVERSAL tags are constructed if they are SEQUENCE/SET */
634 if (t
->symbol
->type
->type
== TTag
&&
635 t
->symbol
->type
->tag
.tagclass
== ASN1_C_UNIV
) {
636 switch (t
->symbol
->type
->tag
.tagvalue
) {
637 case UT_Sequence
: return 0;
638 case UT_Set
: return 0;
649 case TGeneralizedTime
:
655 case TPrintableString
:
658 case TUniversalString
:
663 return is_primitive_type(t
->subtype
);
673 fprintf(headerfile
, " ");
677 last_member_p(struct member
*m
)
679 struct member
*n
= HEIM_TAILQ_NEXT(m
, members
);
682 if (n
->ellipsis
&& HEIM_TAILQ_NEXT(n
, members
) == NULL
)
687 static struct member
*
688 have_ellipsis(Type
*t
)
691 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
699 define_asn1 (int level
, Type
*t
)
703 if (!t
->symbol
&& t
->typeref
.iosclass
) {
704 fprintf(headerfile
, "%s.&%s",
705 t
->typeref
.iosclass
->symbol
->name
,
706 t
->typeref
.field
->name
);
708 fprintf(headerfile
, "%s", t
->symbol
->name
);
711 if(t
->members
== NULL
) {
712 fprintf (headerfile
, "INTEGER");
714 fprintf (headerfile
, " (%lld..%lld)",
715 (long long)t
->range
->min
,
716 (long long)t
->range
->max
);
719 fprintf (headerfile
, "INTEGER {\n");
720 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
722 fprintf(headerfile
, "%s(%d)%s\n", m
->gen_name
, m
->val
,
726 fprintf (headerfile
, "}");
730 fprintf (headerfile
, "BOOLEAN");
733 fprintf (headerfile
, "OCTET STRING");
740 if(t
->type
== TBitString
)
741 fprintf (headerfile
, "BIT STRING {\n");
743 fprintf (headerfile
, "ENUMERATED {\n");
744 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
746 fprintf (headerfile
, "%s(%d)%s\n", m
->name
, m
->val
,
750 fprintf (headerfile
, "}");
757 size_t max_width
= 0;
759 if(t
->type
== TChoice
)
760 fprintf(headerfile
, "CHOICE {\n");
761 else if(t
->type
== TSet
)
762 fprintf(headerfile
, "SET {\n");
764 fprintf(headerfile
, "SEQUENCE {\n");
765 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
766 if(strlen(m
->name
) > max_width
)
767 max_width
= strlen(m
->name
);
770 if(max_width
< 16) max_width
= 16;
771 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
772 size_t width
= max_width
;
775 fprintf (headerfile
, "...");
777 width
-= fprintf(headerfile
, "%s", m
->name
);
778 fprintf(headerfile
, "%*s", (int)width
, "");
779 define_asn1(level
+ 1, m
->type
);
781 fprintf(headerfile
, " OPTIONAL");
784 fprintf (headerfile
, ",");
785 fprintf (headerfile
, "\n");
788 fprintf (headerfile
, "}");
792 fprintf (headerfile
, "SEQUENCE OF ");
793 define_asn1 (0, t
->subtype
);
796 fprintf (headerfile
, "SET OF ");
797 define_asn1 (0, t
->subtype
);
799 case TGeneralizedTime
:
800 fprintf (headerfile
, "GeneralizedTime");
803 fprintf (headerfile
, "GeneralString");
806 fprintf (headerfile
, "TeletexString");
809 const char *classnames
[] = { "UNIVERSAL ", "APPLICATION ",
810 "" /* CONTEXT */, "PRIVATE " };
811 if(t
->tag
.tagclass
!= ASN1_C_UNIV
)
812 fprintf (headerfile
, "[%s%d] ",
813 classnames
[t
->tag
.tagclass
],
815 if(t
->tag
.tagenv
== TE_IMPLICIT
)
816 fprintf (headerfile
, "IMPLICIT ");
817 define_asn1 (level
, t
->subtype
);
821 fprintf (headerfile
, "UTCTime");
825 fprintf (headerfile
, "UTF8String");
827 case TPrintableString
:
829 fprintf (headerfile
, "PrintableString");
833 fprintf (headerfile
, "IA5String");
837 fprintf (headerfile
, "BMPString");
839 case TUniversalString
:
841 fprintf (headerfile
, "UniversalString");
845 fprintf (headerfile
, "VisibleString");
849 fprintf(headerfile
, "OBJECT IDENTIFIER");
853 fprintf (headerfile
, "NULL");
861 getnewbasename(char **newbasename
, int typedefp
, const char *basename
, const char *name
)
864 *newbasename
= strdup(name
);
868 if (asprintf(newbasename
, "%s_%s", basename
, name
) < 0)
871 if (*newbasename
== NULL
)
875 static void define_type(int, const char *, const char *, Type
*, Type
*, int, int);
878 * Get the SET/SEQUENCE member pair and CLASS field pair defining an open type.
880 * There are three cases:
882 * - open types embedded in OCTET STRING, with the open type object class
883 * relation declared via a constraint
885 * - open types not embedded in OCTET STRING, which are really more like ANY
886 * DEFINED BY types, so, HEIM_ANY
888 * - open types in a nested structure member where the type ID field is in a
889 * member of the ancestor structure (this happens in PKIX's `AttributeSet',
890 * where the open type is essentially a SET OF HEIM_ANY).
892 * In a type like PKIX's SingleAttribute the type ID member would be the one
893 * named "type" and the open type member would be the one named "value", and
894 * the corresponding fields of the ATTRIBUTE class would be named "id" and
897 * NOTE: We assume a single open type member pair in any SET/SEQUENCE. In
898 * principle there could be more pairs and we could iterate them, or
899 * better yet, we could be given the name of an open type member and then
900 * just find its related type ID member and fields, then our caller would
901 * iterate the SET/SEQUENCE type's members looking for open type members
902 * and would call this function for each one found.
905 get_open_type_defn_fields(const Type
*t
,
906 Member
**typeidmember
,
907 Member
**opentypemember
,
909 Field
**opentypefield
,
913 Field
*junk1
, *junk2
;
914 char *idmembername
= NULL
;
916 if (!typeidfield
) typeidfield
= &junk1
;
917 if (!opentypefield
) opentypefield
= &junk2
;
919 *typeidfield
= *opentypefield
= NULL
;
920 *typeidmember
= *opentypemember
= NULL
;
923 /* Look for the open type member */
924 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
925 Type
*subtype
= m
->type
;
926 Type
*sOfType
= NULL
;
928 while (subtype
->type
== TTag
||
929 subtype
->type
== TSetOf
||
930 subtype
->type
== TSequenceOf
) {
931 if (subtype
->type
== TTag
&& subtype
->subtype
) {
932 if (subtype
->subtype
->type
== TOctetString
||
933 subtype
->subtype
->type
== TBitString
)
935 subtype
= subtype
->subtype
;
936 } else if (subtype
->type
== TSetOf
|| subtype
->type
== TSequenceOf
) {
940 if (subtype
->subtype
)
941 subtype
= subtype
->subtype
;
946 * If we traversed through a non-inlined SET OF or SEQUENCE OF type,
947 * then this cannot be an open type field.
949 if (sOfType
&& sOfType
->symbol
)
952 * The type of the field we're interested in has to have an information
955 if (!subtype
->constraint
)
957 if (subtype
->type
!= TType
&& subtype
->type
!= TTag
)
960 * Check if it's an ANY-like member or like an OCTET STRING CONTAINING
961 * member. Those are the only two possibilities.
963 if ((subtype
->type
== TTag
|| subtype
->type
== TType
) &&
965 subtype
->constraint
->ctype
== CT_CONTENTS
&&
966 subtype
->constraint
->u
.content
.type
&&
967 subtype
->constraint
->u
.content
.type
->type
== TType
&&
968 !subtype
->constraint
->u
.content
.type
->subtype
&&
969 subtype
->constraint
->u
.content
.type
->constraint
&&
970 subtype
->constraint
->u
.content
.type
->constraint
->ctype
== CT_TABLE_CONSTRAINT
) {
971 /* Type like OCTET STRING or BIT STRING CONTAINING open type */
973 *opentypefield
= subtype
->constraint
->u
.content
.type
->typeref
.field
;
974 *is_array_of
= sOfType
!= NULL
;
975 idmembername
= subtype
->constraint
->u
.content
.type
->constraint
->u
.content
.crel
.membername
;
977 } else if (subtype
->symbol
&& strcmp(subtype
->symbol
->name
, "HEIM_ANY") == 0) {
978 /* Open type, but NOT embedded in OCTET STRING or BIT STRING */
980 *opentypefield
= subtype
->typeref
.field
;
981 *is_array_of
= sOfType
!= NULL
;
982 idmembername
= subtype
->constraint
->u
.content
.crel
.membername
;
986 /* Look for the type ID member identified in the previous loop */
987 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
988 if (!m
->type
->subtype
|| strcmp(m
->name
, idmembername
))
990 if (m
->type
->constraint
&&
991 m
->type
->constraint
->ctype
== CT_TABLE_CONSTRAINT
)
992 *typeidfield
= m
->type
->typeref
.field
;
993 else if (m
->type
->subtype
->constraint
&&
994 m
->type
->subtype
->constraint
->ctype
== CT_TABLE_CONSTRAINT
)
995 *typeidfield
= m
->type
->subtype
->typeref
.field
;
998 /* This is the type ID field (because there _is_ a subtype) */
1005 * Generate CHOICE-like struct fields for open types declared via
1006 * X.681/682/683 syntax.
1008 * We could support multiple open type members in a SET/SEQUENCE, but for now
1009 * we support only one.
1012 define_open_type(int level
, const char *newbasename
, const char *name
, const char *basename
, Type
*pt
, Type
*t
)
1014 Member
*opentypemember
, *typeidmember
;
1015 Field
*opentypefield
, *typeidfield
;
1017 IOSObjectSet
*os
= pt
->actual_parameter
;
1018 IOSObject
**objects
;
1020 int is_array_of_open_type
;
1022 get_open_type_defn_fields(pt
, &typeidmember
, &opentypemember
,
1023 &typeidfield
, &opentypefield
,
1024 &is_array_of_open_type
);
1025 if (!opentypemember
|| !typeidmember
||
1026 !opentypefield
|| !typeidfield
)
1027 errx(1, "Open type specification in %s is incomplete", name
);
1029 sort_object_set(os
, typeidfield
, &objects
, &nobjs
);
1031 fprintf(headerfile
, "struct {\n");
1033 /* Iterate objects in the object set, gen enum labels */
1034 fprintf(headerfile
, "enum { choice_%s_iosnumunknown = 0,\n",
1036 for (i
= 0; i
< nobjs
; i
++) {
1037 HEIM_TAILQ_FOREACH(of
, objects
[i
]->objfields
, objfields
) {
1038 if (strcmp(of
->name
, typeidfield
->name
))
1040 if (!of
->value
|| !of
->value
->s
)
1041 errx(1, "Unknown value in value field %s of object %s",
1042 of
->name
, objects
[i
]->symbol
->name
);
1043 fprintf(headerfile
, "choice_%s_iosnum_%s,\n",
1044 newbasename
, of
->value
->s
->gen_name
);
1047 fprintf(headerfile
, "} element;\n");
1049 if (is_array_of_open_type
)
1050 fprintf(headerfile
, "unsigned int len;\n");
1052 /* Iterate objects in the object set, gen union arms */
1053 fprintf(headerfile
, "union {\nvoid *_any;\n");
1054 for (i
= 0; i
< nobjs
; i
++) {
1055 HEIM_TAILQ_FOREACH(of
, objects
[i
]->objfields
, objfields
) {
1058 if (strcmp(of
->name
, opentypefield
->name
))
1060 if (!of
->type
|| (!of
->type
->symbol
&& of
->type
->type
!= TTag
) ||
1061 of
->type
->tag
.tagclass
!= ASN1_C_UNIV
) {
1062 warnx("Ignoring unknown or unset type field %s of object %s",
1063 of
->name
, objects
[i
]->symbol
->name
);
1067 if (asprintf(&n
, "*%s", objects
[i
]->symbol
->gen_name
) < 0 || n
== NULL
)
1069 define_type(level
+ 2, n
, newbasename
, NULL
, of
->type
, FALSE
, FALSE
);
1073 if (is_array_of_open_type
) {
1074 fprintf(headerfile
, "} *val;\n} _ioschoice_%s;\n", opentypemember
->gen_name
);
1076 fprintf(headerfile
, "} u;\n");
1077 fprintf(headerfile
, "} _ioschoice_%s;\n", opentypemember
->gen_name
);
1083 define_type(int level
, const char *name
, const char *basename
, Type
*pt
, Type
*t
, int typedefp
, int preservep
)
1085 const char *label_prefix
= NULL
;
1086 const char *label_prefix_sep
= NULL
;
1087 char *newbasename
= NULL
;
1092 if (!t
->symbol
&& t
->actual_parameter
)
1093 define_open_type(level
, newbasename
, name
, basename
, t
, t
);
1094 else if (!t
->symbol
&& pt
->actual_parameter
)
1095 define_open_type(level
, newbasename
, name
, basename
, pt
, t
);
1097 fprintf(headerfile
, "%s %s;\n", t
->symbol
->gen_name
, name
);
1100 if (t
->symbol
&& t
->symbol
->emitted_definition
)
1107 label_prefix
= prefix_enum
? name
: (enum_prefix
? enum_prefix
: "");
1108 label_prefix_sep
= prefix_enum
? "_" : "";
1109 fprintf (headerfile
, "enum %s {\n", typedefp
? name
: "");
1110 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
1112 fprintf(headerfile
, "%s%s%s = %d%s\n",
1113 label_prefix
, label_prefix_sep
,
1114 m
->gen_name
, m
->val
, last_member_p(m
));
1116 fprintf(headerfile
, "} %s;\n", name
);
1117 } else if (t
->range
== NULL
) {
1118 fprintf(headerfile
, "heim_integer %s;\n", name
);
1119 } else if (t
->range
->min
< 0 &&
1120 (t
->range
->min
< INT_MIN
|| t
->range
->max
> INT_MAX
)) {
1121 fprintf(headerfile
, "int64_t %s;\n", name
);
1122 } else if (t
->range
->min
< 0) {
1123 fprintf (headerfile
, "int %s;\n", name
);
1124 } else if (t
->range
->max
> UINT_MAX
) {
1125 fprintf (headerfile
, "uint64_t %s;\n", name
);
1127 fprintf (headerfile
, "unsigned int %s;\n", name
);
1132 fprintf (headerfile
, "int %s;\n", name
);
1136 fprintf (headerfile
, "heim_octet_string %s;\n", name
);
1141 struct range range
= { 0, UINT_MAX
};
1142 size_t max_memno
= 0;
1145 if (t
->symbol
&& t
->symbol
->emitted_definition
)
1147 memset(&i
, 0, sizeof(i
));
1150 * range.max implies the size of the base unsigned integer used for the
1151 * bitfield members. If it's less than or equal to UINT_MAX, then that
1152 * will be unsigned int, otherwise it will be uint64_t.
1154 * We could just use uint64_t, yes, but for now, and in case that any
1155 * projects were exposing the BIT STRING types' C representations in
1156 * ABIs prior to this compiler supporting BIT STRING with larger
1157 * members, we stick to this.
1159 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
1160 if (m
->val
> max_memno
)
1164 range
.max
= INT64_MAX
;
1166 range
.max
= 1ULL << max_memno
;
1171 i
.constraint
= NULL
;
1174 if(HEIM_TAILQ_EMPTY(t
->members
))
1175 fprintf (headerfile
, "heim_bit_string %s;\n", name
);
1178 getnewbasename(&newbasename
, typedefp
|| level
== 0, basename
, name
);
1180 fprintf (headerfile
, "struct %s {\n", newbasename
);
1181 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
1185 * pad unused bits beween declared members (hopefully this
1186 * forces the compiler to give us an obvious layout)
1188 while (pos
< m
->val
) {
1189 if (asprintf (&n
, "_unused%d:1", pos
) < 0 || n
== NULL
)
1191 define_type(level
+ 1, n
, newbasename
, NULL
, &i
, FALSE
, FALSE
);
1197 if (asprintf (&n
, "%s:1", m
->gen_name
) < 0 || n
== NULL
)
1199 define_type(level
+ 1, n
, newbasename
, NULL
, &i
, FALSE
, FALSE
);
1204 /* pad unused tail (ditto) */
1205 bitset_size
= max_memno
;
1207 bitset_size
+= 64 - (max_memno
% 64);
1210 while (pos
< bitset_size
) {
1212 if (asprintf (&n
, "_unused%d:1", pos
) < 0 || n
== NULL
)
1214 define_type(level
+ 1, n
, newbasename
, NULL
, &i
, FALSE
, FALSE
);
1220 fprintf (headerfile
, "} %s;\n\n", name
);
1227 if (t
->symbol
&& t
->symbol
->emitted_definition
)
1230 label_prefix
= prefix_enum
? name
: (enum_prefix
? enum_prefix
: "");
1231 label_prefix_sep
= prefix_enum
? "_" : "";
1233 fprintf (headerfile
, "enum %s {\n", typedefp
? name
: "");
1234 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
1237 fprintf (headerfile
, "/* ... */\n");
1239 fprintf(headerfile
, "%s%s%s = %d%s\n",
1240 label_prefix
, label_prefix_sep
,
1241 m
->gen_name
, m
->val
, last_member_p(m
));
1244 fprintf (headerfile
, "} %s;\n\n", name
);
1251 getnewbasename(&newbasename
, typedefp
|| level
== 0, basename
, name
);
1254 fprintf (headerfile
, "struct %s {\n", newbasename
);
1255 if (t
->type
== TSequence
&& preservep
) {
1257 fprintf(headerfile
, "heim_octet_string _save;\n");
1259 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
1262 } else if (m
->optional
) {
1265 if (asprintf(&n
, "*%s", m
->gen_name
) < 0 || n
== NULL
)
1267 define_type(level
+ 1, n
, newbasename
, t
, m
->type
, FALSE
, FALSE
);
1270 define_type(level
+ 1, m
->gen_name
, newbasename
, t
, m
->type
, FALSE
, FALSE
);
1272 if (t
->actual_parameter
&& t
->actual_parameter
->objects
)
1273 define_open_type(level
, newbasename
, name
, basename
, t
, t
);
1275 fprintf (headerfile
, "} %s;\n", name
);
1281 struct range range
= { 0, UINT_MAX
};
1283 getnewbasename(&newbasename
, typedefp
|| level
== 0, basename
, name
);
1285 memset(&i
, 0, sizeof(i
));
1290 fprintf (headerfile
, "struct %s {\n", newbasename
);
1291 define_type(level
+ 1, "len", newbasename
, t
, &i
, FALSE
, FALSE
);
1292 define_type(level
+ 1, "*val", newbasename
, t
, t
->subtype
, FALSE
, FALSE
);
1294 fprintf (headerfile
, "} %s;\n", name
);
1297 case TGeneralizedTime
:
1299 fprintf (headerfile
, "time_t %s;\n", name
);
1301 case TGeneralString
:
1303 fprintf (headerfile
, "heim_general_string %s;\n", name
);
1305 case TTeletexString
:
1307 fprintf (headerfile
, "heim_general_string %s;\n", name
);
1310 define_type(level
, name
, basename
, t
, t
->subtype
, typedefp
, preservep
);
1316 getnewbasename(&newbasename
, typedefp
|| level
== 0, basename
, name
);
1319 fprintf (headerfile
, "struct %s {\n", newbasename
);
1322 fprintf(headerfile
, "heim_octet_string _save;\n");
1325 fprintf (headerfile
, "enum %s_enum {\n", newbasename
);
1326 m
= have_ellipsis(t
);
1329 fprintf (headerfile
, "%s = 0,\n", m
->label
);
1332 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
1335 fprintf (headerfile
, "/* ... */\n");
1337 fprintf (headerfile
, "%s%s%s\n", m
->label
,
1338 first
? " = 1" : "",
1343 fprintf (headerfile
, "} element;\n");
1345 fprintf (headerfile
, "union {\n");
1346 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
1349 fprintf(headerfile
, "heim_octet_string asn1_ellipsis;\n");
1350 } else if (m
->optional
) {
1353 if (asprintf (&n
, "*%s", m
->gen_name
) < 0 || n
== NULL
)
1355 define_type(level
+ 2, n
, newbasename
, t
, m
->type
, FALSE
, FALSE
);
1358 define_type(level
+ 2, m
->gen_name
, newbasename
, t
, m
->type
, FALSE
, FALSE
);
1361 fprintf (headerfile
, "} u;\n");
1363 fprintf (headerfile
, "} %s;\n", name
);
1368 fprintf (headerfile
, "time_t %s;\n", name
);
1372 fprintf (headerfile
, "heim_utf8_string %s;\n", name
);
1374 case TPrintableString
:
1376 fprintf (headerfile
, "heim_printable_string %s;\n", name
);
1380 fprintf (headerfile
, "heim_ia5_string %s;\n", name
);
1384 fprintf (headerfile
, "heim_bmp_string %s;\n", name
);
1386 case TUniversalString
:
1388 fprintf (headerfile
, "heim_universal_string %s;\n", name
);
1390 case TVisibleString
:
1392 fprintf (headerfile
, "heim_visible_string %s;\n", name
);
1396 fprintf (headerfile
, "heim_oid %s;\n", name
);
1400 fprintf (headerfile
, "int %s;\n", name
);
1409 declare_type(const Symbol
*s
, Type
*t
, int typedefp
)
1411 char *newbasename
= NULL
;
1414 fprintf(headerfile
, "typedef ");
1418 define_type(0, s
->gen_name
, s
->gen_name
, NULL
, s
->type
, TRUE
, TRUE
);
1420 generate_template_type_forward(s
->gen_name
);
1421 emitted_declaration(s
);
1428 case TGeneralizedTime
:
1429 case TGeneralString
:
1430 case TTeletexString
:
1433 case TPrintableString
:
1436 case TUniversalString
:
1437 case TVisibleString
:
1440 define_type(0, s
->gen_name
, s
->gen_name
, NULL
, s
->type
, TRUE
, TRUE
);
1442 generate_template_type_forward(s
->gen_name
);
1443 emitted_declaration(s
);
1444 emitted_definition(s
);
1447 declare_type(s
, t
->subtype
, FALSE
);
1448 emitted_declaration(s
);
1457 getnewbasename(&newbasename
, TRUE
, s
->gen_name
, s
->gen_name
);
1458 fprintf(headerfile
, "struct %s %s;\n", newbasename
, s
->gen_name
);
1462 getnewbasename(&newbasename
, TRUE
, s
->gen_name
, s
->gen_name
);
1463 fprintf(headerfile
, "struct %s %s;\n", newbasename
, s
->gen_name
);
1466 getnewbasename(&newbasename
, TRUE
, s
->gen_name
, s
->gen_name
);
1467 fprintf(headerfile
, "struct %s %s;\n", newbasename
, s
->gen_name
);
1473 emitted_declaration(s
);
1476 static void generate_subtypes_header_helper(const Member
*m
);
1477 static void generate_type_header(const Symbol
*);
1480 generate_subtypes_header_helper(const Member
*m
)
1487 if (m
->type
->symbol
&& (s
= getsym(m
->type
->symbol
->name
)) &&
1488 !s
->emitted_definition
) {
1489 /* A field of some named type; recurse */
1490 if (!m
->optional
&& !m
->defval
)
1491 generate_type_header(s
);
1494 if (!m
->type
->subtype
&& !m
->type
->members
)
1496 if (m
->type
->type
== TTag
&&
1497 m
->type
->subtype
&& m
->type
->subtype
->symbol
&&
1498 (s
= getsym(m
->type
->subtype
->symbol
->name
))) {
1499 if (!m
->optional
&& !m
->defval
)
1500 generate_type_header(s
);
1503 if (m
->type
->subtype
) {
1504 switch (m
->type
->subtype
->type
) {
1512 /* A field of some anonymous (inlined) structured type */
1513 HEIM_TAILQ_FOREACH(sm
, m
->type
->subtype
->members
, members
) {
1514 generate_subtypes_header_helper(sm
);
1517 if (m
->type
->members
) {
1518 HEIM_TAILQ_FOREACH(sm
, m
->type
->members
, members
) {
1519 generate_subtypes_header_helper(sm
);
1525 generate_subtypes_header(const Symbol
*s
)
1531 * Recurse down structured types to make sure top-level types get
1532 * defined before they are referenced.
1534 * We'll take care to skip OPTIONAL member fields of constructed types so
1535 * that we can have circular types like:
1537 * Foo ::= SEQUENCE {
1541 * Bar ::= SEQUENCE {
1545 * not unlike XDR, which uses `*' to mean "optional", except in XDR it's
1546 * called a "pointer". With some care we should be able to eventually
1547 * support the silly XDR linked list example:
1549 * ListOfFoo ::= SEQUENCE {
1550 * someField SomeType,
1551 * next ListOfFoo OPTIONAL
1554 * Not that anyone needs it -- just use a SEQUENCE OF and be done.
1557 while (t
->type
== TTag
&& t
->subtype
) {
1558 switch (t
->subtype
->type
) {
1575 if (t
->symbol
&& (s2
= getsym(t
->symbol
->name
)) != s
)
1576 generate_type_header(s2
);
1585 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
1586 generate_subtypes_header_helper(m
);
1591 generate_type_header (const Symbol
*s
)
1598 * Recurse down the types of member fields of `s' to make sure that
1599 * referenced types have had their definitions emitted already if the
1600 * member fields are not OPTIONAL/DEFAULTed.
1602 generate_subtypes_header(s
);
1603 fprintf(headerfile
, "/*\n");
1604 fprintf(headerfile
, "%s ::= ", s
->name
);
1605 define_asn1 (0, s
->type
);
1606 fprintf(headerfile
, "\n*/\n\n");
1609 * Emit enums for the outermost tag of this type. These are needed for
1610 * dealing with IMPLICIT tags so we know what to rewrite the tag to when
1613 * See gen_encode.c and gen_decode.c for a complete explanation. Short
1614 * version: we need to change the prototypes of the length/encode/decode
1615 * functions to take an optional IMPLICIT tag to use instead of the type's
1616 * outermost tag, but for now we hack it, and to do that we need to know
1617 * the type's outermost tag outside the context of the bodies of the codec
1618 * functions we generate for it. Using an enum means no extra space is
1619 * needed in stripped objects.
1621 if (!s
->emitted_tag_enums
) {
1622 while (t
->type
== TType
&& s
->type
->symbol
&& s
->type
->symbol
->type
) {
1626 t
= s
->type
->symbol
->type
;
1629 if (t
->type
== TType
&& t
->symbol
&& strcmp(t
->symbol
->name
, "HEIM_ANY")) {
1631 * This type is ultimately an alias of an imported type, so we don't
1632 * know its outermost tag here.
1635 "enum { asn1_tag_length_%s = asn1_tag_length_%s,\n"
1636 " asn1_tag_class_%s = asn1_tag_class_%s,\n"
1637 " asn1_tag_tag_%s = asn1_tag_tag_%s };\n",
1638 s
->gen_name
, s
->type
->symbol
->gen_name
,
1639 s
->gen_name
, s
->type
->symbol
->gen_name
,
1640 s
->gen_name
, s
->type
->symbol
->gen_name
);
1641 emitted_tag_enums(s
);
1642 } else if (t
->type
!= TType
) {
1643 /* This type's outermost tag is known here */
1645 "enum { asn1_tag_length_%s = %lu,\n"
1646 " asn1_tag_class_%s = %d,\n"
1647 " asn1_tag_tag_%s = %d };\n",
1648 s
->gen_name
, (unsigned long)length_tag(s
->type
->tag
.tagvalue
),
1649 s
->gen_name
, s
->type
->tag
.tagclass
,
1650 s
->gen_name
, s
->type
->tag
.tagvalue
);
1651 emitted_tag_enums(s
);
1655 if (s
->emitted_definition
)
1658 if (is_export(s
->name
))
1659 fprintf(symsfile
, "ASN1_SYM_TYPE(\"%s\", \"%s\", %s)\n",
1660 s
->name
, s
->gen_name
, s
->gen_name
);
1661 fprintf(headerfile
, "typedef ");
1662 define_type(0, s
->gen_name
, s
->gen_name
, NULL
, s
->type
, TRUE
,
1663 preserve_type(s
->name
) ? TRUE
: FALSE
);
1664 fprintf(headerfile
, "\n");
1666 emitted_definition(s
);
1670 generate_type_header_forwards(const Symbol
*s
)
1672 declare_type(s
, s
->type
, TRUE
);
1673 fprintf(headerfile
, "\n");
1675 generate_template_type_forward(s
->gen_name
);
1679 generate_type (const Symbol
*s
)
1685 generate_header_of_codefile(s
->gen_name
);
1687 generate_type_header(s
);
1690 generate_template(s
);
1692 if (template_flag
== 0 || is_template_compat(s
) == 0) {
1693 generate_type_encode (s
);
1694 generate_type_decode (s
);
1695 generate_type_free (s
);
1696 generate_type_length (s
);
1697 generate_type_copy (s
);
1698 generate_type_print_stub(s
);
1700 generate_type_seq (s
);
1701 generate_glue (s
->type
, s
->gen_name
);
1703 /* generate prototypes */
1705 if (is_export(s
->name
)) {
1715 "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n",
1717 s
->gen_name
, s
->gen_name
);
1720 "encode_%s(unsigned char *, size_t, const %s *, size_t *);\n",
1722 s
->gen_name
, s
->gen_name
);
1724 "%ssize_t ASN1CALL length_%s(const %s *);\n",
1726 s
->gen_name
, s
->gen_name
);
1728 "%sint ASN1CALL copy_%s (const %s *, %s *);\n",
1730 s
->gen_name
, s
->gen_name
, s
->gen_name
);
1732 "%svoid ASN1CALL free_%s (%s *);\n",
1734 s
->gen_name
, s
->gen_name
);
1737 "%schar * ASN1CALL print_%s (const %s *, int);\n",
1739 s
->gen_name
, s
->gen_name
);
1743 if (!one_code_file
) {
1744 fprintf(codefile
, "\n\n");