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 *jsonfile
, *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
);
88 fprintf(jsonfile
, "{\"imports\":\"%s\"}\n", module
);
92 * List of all exported symbols
94 * XXX A hash table would be nice here.
100 struct sexport
*next
;
103 static struct sexport
*exports
= NULL
;
106 add_export (const char *name
)
108 struct sexport
*tmp
= emalloc (sizeof(*tmp
));
116 is_export(const char *name
)
120 if (exports
== NULL
) /* no export list, all exported */
123 for (tmp
= exports
; tmp
!= NULL
; tmp
= tmp
->next
) {
124 if (strcmp(tmp
->name
, name
) == 0) {
135 return orig_filename
;
139 init_generate (const char *filename
, const char *base
)
143 orig_filename
= filename
;
145 headerbase
= strdup(base
);
146 if (headerbase
== NULL
)
151 if (asprintf(&fn
, "%s.json", headerbase
) < 0 || fn
== NULL
)
153 jsonfile
= fopen(fn
, "w");
154 if (jsonfile
== NULL
)
155 err(1, "open %s", fn
);
159 /* public header file */
160 if (asprintf(&header
, "%s.h", headerbase
) < 0 || header
== NULL
)
162 if (asprintf(&fn
, "%s.h", headerbase
) < 0 || fn
== NULL
)
164 headerfile
= fopen (fn
, "w");
165 if (headerfile
== NULL
)
166 err (1, "open %s", fn
);
170 /* private header file */
171 if (asprintf(&privheader
, "%s-priv.h", headerbase
) < 0 || privheader
== NULL
)
173 if (asprintf(&fn
, "%s-priv.h", headerbase
) < 0 || fn
== NULL
)
175 privheaderfile
= fopen (fn
, "w");
176 if (privheaderfile
== NULL
)
177 err (1, "open %s", fn
);
182 if (asprintf(&template, "%s-template.c", headerbase
) < 0 || template == NULL
)
185 "/* Generated from %s */\n"
186 "/* Do not edit */\n\n",
190 "#define __%s_h__\n\n", headerbase
, headerbase
);
192 "#include <stddef.h>\n"
193 "#include <stdint.h>\n"
194 "#include <time.h>\n\n");
196 "#ifndef __asn1_common_definitions__\n"
197 "#define __asn1_common_definitions__\n\n");
199 "#ifndef __HEIM_BASE_DATA__\n"
200 "#define __HEIM_BASE_DATA__ 1\n"
201 "struct heim_base_data {\n"
205 "typedef struct heim_base_data heim_octet_string;\n"
208 "typedef struct heim_integer {\n"
212 "} heim_integer;\n\n");
214 "typedef char *heim_general_string;\n\n"
217 "typedef char *heim_utf8_string;\n\n"
220 "typedef struct heim_base_data heim_printable_string;\n\n"
223 "typedef struct heim_base_data heim_ia5_string;\n\n"
226 "typedef struct heim_bmp_string {\n"
229 "} heim_bmp_string;\n\n");
231 "typedef struct heim_universal_string {\n"
234 "} heim_universal_string;\n\n");
236 "typedef char *heim_visible_string;\n\n"
239 "typedef struct heim_oid {\n"
241 " unsigned *components;\n"
244 "typedef struct heim_bit_string {\n"
247 "} heim_bit_string;\n\n");
249 "typedef struct heim_base_data heim_any;\n"
250 "typedef struct heim_base_data heim_any_set;\n"
251 "typedef struct heim_base_data HEIM_ANY;\n"
252 "typedef struct heim_base_data HEIM_ANY_SET;\n\n");
255 "enum asn1_print_flags {\n"
256 " ASN1_PRINT_INDENT = 1,\n"
258 fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R) \\\n"
260 " (BL) = length_##T((S)); \\\n"
261 " (B) = calloc(1, (BL)); \\\n"
262 " if((B) == NULL) { \\\n"
264 " (R) = ENOMEM; \\\n"
266 " (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \\\n"
268 " if((R) != 0) { \\\n"
276 fputs("#ifdef _WIN32\n"
278 "#define ASN1EXP __declspec(dllimport)\n"
282 "#define ASN1CALL __stdcall\n"
288 fputs("#ifndef ENOTSUP\n"
289 "/* Very old MSVC CRTs lack ENOTSUP */\n"
290 "#define ENOTSUP EINVAL\n"
293 fprintf (headerfile
, "struct units;\n\n");
294 fprintf (headerfile
, "#endif\n\n");
295 if (asprintf(&fn
, "%s_files", base
) < 0 || fn
== NULL
)
297 logfile
= fopen(fn
, "w");
299 err (1, "open %s", fn
);
303 if (asprintf(&fn
, "%s_oids.c", base
) < 0 || fn
== NULL
)
305 oidsfile
= fopen(fn
, "w");
306 if (oidsfile
== NULL
)
307 err (1, "open %s", fn
);
308 if (asprintf(&fn
, "%s_syms.c", base
) < 0 || fn
== NULL
)
310 symsfile
= fopen(fn
, "w");
311 if (symsfile
== NULL
)
312 err (1, "open %s", fn
);
316 /* if one code file, write into the one codefile */
320 templatefile
= fopen (template, "w");
321 if (templatefile
== NULL
)
322 err (1, "open %s", template);
324 fprintf (templatefile
,
325 "/* Generated from %s */\n"
326 "/* Do not edit */\n\n"
327 "#include <stdio.h>\n"
328 "#include <stdlib.h>\n"
329 "#include <time.h>\n"
330 "#include <string.h>\n"
331 "#include <errno.h>\n"
332 "#include <limits.h>\n"
333 "#include <asn1_err.h>\n"
338 fprintf (templatefile
,
342 "#include <asn1-template.h>\n",
349 close_generate (void)
351 fprintf (headerfile
, "#endif /* __%s_h__ */\n", headerbase
);
353 if (headerfile
&& fclose(headerfile
) == EOF
)
354 err(1, "writes to public header file failed");
355 if (privheaderfile
&& fclose(privheaderfile
) == EOF
)
356 err(1, "writes to private header file failed");
357 if (templatefile
&& fclose(templatefile
) == EOF
)
358 err(1, "writes to template file failed");
359 if (!jsonfile
) abort();
360 if (fclose(jsonfile
) == EOF
)
361 err(1, "writes to JSON file failed");
362 if (!oidsfile
) abort();
363 if (fclose(oidsfile
) == EOF
)
364 err(1, "writes to OIDs file failed");
365 if (!symsfile
) abort();
366 if (fclose(symsfile
) == EOF
)
367 err(1, "writes to symbols file failed");
368 if (!logfile
) abort();
369 fprintf(logfile
, "\n");
370 if (fclose(logfile
) == EOF
)
371 err(1, "writes to log file failed");
375 gen_assign_defval(const char *var
, struct value
*val
)
379 fprintf(codefile
, "if((%s = strdup(\"%s\")) == NULL)\nreturn ENOMEM;\n", var
, val
->u
.stringvalue
);
382 fprintf(codefile
, "%s = %lld;\n",
383 var
, (long long)val
->u
.integervalue
);
386 if(val
->u
.booleanvalue
)
387 fprintf(codefile
, "%s = 1;\n", var
);
389 fprintf(codefile
, "%s = 0;\n", var
);
397 gen_compare_defval(const char *var
, struct value
*val
)
401 fprintf(codefile
, "if(strcmp(%s, \"%s\") != 0)\n", var
, val
->u
.stringvalue
);
404 fprintf(codefile
, "if(%s != %lld)\n",
405 var
, (long long)val
->u
.integervalue
);
408 if(val
->u
.booleanvalue
)
409 fprintf(codefile
, "if(!%s)\n", var
);
411 fprintf(codefile
, "if(%s)\n", var
);
419 generate_header_of_codefile(const char *name
)
421 char *filename
= NULL
;
423 if (codefile
!= NULL
)
426 if (asprintf (&filename
, "%s_%s.c", STEM
, name
) < 0 || filename
== NULL
)
428 codefile
= fopen (filename
, "w");
429 if (codefile
== NULL
)
430 err (1, "fopen %s", filename
);
432 fprintf(logfile
, "%s ", filename
);
436 "/* Generated from %s */\n"
437 "/* Do not edit */\n\n"
438 "#if defined(_WIN32) && !defined(ASN1_LIB)\n"
439 "# error \"ASN1_LIB must be defined\"\n"
441 "#include <stdio.h>\n"
442 "#include <stdlib.h>\n"
443 "#include <time.h>\n"
444 "#include <string.h>\n"
445 "#include <errno.h>\n"
446 "#include <limits.h>\n"
456 "#include <asn1_err.h>\n"
458 "#include <asn1-template.h>\n\n");
460 if (parse_units_flag
)
462 "#include <parse_units.h>\n\n");
465 fprintf(codefile
, "#pragma warning(disable: 4101)\n\n");
472 if (codefile
== NULL
)
475 if (fclose(codefile
) == EOF
)
476 err(1, "writes to source code file failed");
480 /* Object identifiers are parsed backwards; this reverses that */
482 objid2list(struct objid
*o
)
484 struct objid
*el
, **list
;
487 for (el
= o
, len
= 0; el
; el
= el
->next
)
491 list
= ecalloc(len
+ 1, sizeof(*list
));
493 for (i
= 0; o
; o
= o
->next
)
497 /* Reverse the list */
498 for (i
= 0; i
< (len
>>1); i
++) {
500 list
[i
] = list
[len
- (i
+ 1)];
501 list
[len
- (i
+ 1)] = el
;
507 generate_constant (const Symbol
*s
)
509 switch(s
->value
->type
) {
514 * Work around the fact that OpenSSL defines macros for PKIX constants
515 * that we want to generate as enums, which causes conflicts for things
516 * like ub-name (ub_name).
522 "enum { %s = %lld };\n\n",
523 s
->gen_name
, s
->gen_name
, s
->gen_name
,
524 (long long)s
->value
->u
.integervalue
);
525 if (is_export(s
->name
))
526 fprintf(symsfile
, "ASN1_SYM_INTVAL(\"%s\", \"%s\", %s, %lld)\n",
527 s
->name
, s
->gen_name
, s
->gen_name
,
528 (long long)s
->value
->u
.integervalue
);
530 "{\"name\":\"%s\",\"gen_name\":\"%s\",\"type\":\"INTEGER\","
531 "\"constant\":true,\"exported\":%s,\"value\":%lld}\n",
532 s
->name
, s
->gen_name
, is_export(s
->name
) ? "true" : "false",
533 (long long)s
->value
->u
.integervalue
);
539 case objectidentifiervalue
: {
540 struct objid
*o
, **list
;
545 generate_header_of_codefile(s
->gen_name
);
547 list
= objid2list(s
->value
->u
.objectidentifiervalue
);
548 for (len
= 0; list
&& list
[len
]; len
++)
551 errx(1, "Empty OBJECT IDENTIFIER named %s\n", s
->name
);
556 "{\"name\":\"%s\",\"gen_name\":\"%s\","
557 "\"type\":\"OBJECT IDENTIFIER\","
558 "\"constant\":true,\"exported\":%s,\"value\":[\n",
559 s
->name
, s
->gen_name
, is_export(s
->name
) ? "true" : "false");
560 fprintf (headerfile
, "/* OBJECT IDENTIFIER %s ::= { ", s
->name
);
561 for (i
= 0; i
< len
; i
++) {
563 fprintf(headerfile
, "%s(%d) ",
564 o
->label
? o
->label
: "label-less", o
->value
);
565 if (o
->label
== NULL
)
566 fprintf(jsonfile
, "%s{\"label\":null,\"value\":%d}",
567 i
? "," : "", o
->value
);
569 fprintf(jsonfile
, "%s{\"label\":\"%s\",\"value\":%d}",
570 i
? "," : "", o
->label
, o
->value
);
572 fprintf(jsonfile
, "]}\n");
574 fprintf (codefile
, "static unsigned oid_%s_variable_num[%lu] = {",
575 s
->gen_name
, (unsigned long)len
);
576 for (i
= 0; list
[i
]; i
++) {
577 fprintf(codefile
, "%s %d", i
? "," : "", list
[i
]->value
);
579 fprintf(codefile
, "};\n");
581 fprintf (codefile
, "const heim_oid asn1_oid_%s = "
582 "{ %lu, oid_%s_variable_num };\n\n",
583 s
->gen_name
, (unsigned long)len
, s
->gen_name
);
585 fprintf(oidsfile
, "DEFINE_OID_WITH_NAME(%s)\n", s
->gen_name
);
586 if (is_export(s
->name
))
587 fprintf(symsfile
, "ASN1_SYM_OID(\"%s\", \"%s\", %s)\n",
588 s
->name
, s
->gen_name
, s
->gen_name
);
594 gen_upper
= strdup(s
->gen_name
);
595 len
= strlen(gen_upper
);
596 for (i
= 0; i
< len
; i
++)
597 gen_upper
[i
] = toupper((unsigned char)s
->gen_name
[i
]);
599 fprintf (headerfile
, "} */\n");
601 "extern ASN1EXP const heim_oid asn1_oid_%s;\n"
602 "#define ASN1_OID_%s (&asn1_oid_%s)\n\n",
620 is_tagged_type(const Type
*t
)
623 * Start by chasing aliasings like this:
630 * to <Type0>, then check if <Type0> is tagged.
632 while (t
->type
== TType
) {
635 else if (t
->symbol
&& t
->symbol
->type
)
641 if (t
->type
== TTag
&& t
->tag
.tagenv
== TE_EXPLICIT
)
643 if (t
->type
== TTag
) {
645 return is_tagged_type(t
->subtype
);
646 if (t
->symbol
&& t
->symbol
->type
)
647 return is_tagged_type(t
->symbol
->type
);
648 /* This is the tag */
655 is_primitive_type(const Type
*t
)
658 * Start by chasing aliasings like this:
665 * to <Type0>, then check if <Type0> is primitive.
667 while (t
->type
== TType
&&
670 if (t
->symbol
->type
->type
== TType
)
671 t
= t
->symbol
->type
; /* Alias */
672 else if (t
->symbol
->type
->type
== TTag
&&
673 t
->symbol
->type
->tag
.tagenv
== TE_IMPLICIT
)
675 * IMPLICIT-tagged alias, something like:
677 * Type0 ::= [0] IMPLICIT ...
681 return is_primitive_type(t
->symbol
->type
);
686 /* EXPLICIT non-UNIVERSAL tags are always constructed */
687 if (t
->type
== TTag
&& t
->tag
.tagclass
!= ASN1_C_UNIV
&&
688 t
->tag
.tagenv
== TE_EXPLICIT
)
690 if (t
->symbol
&& t
->symbol
->type
) {
691 /* EXPLICIT non-UNIVERSAL tags are constructed */
692 if (t
->symbol
->type
->type
== TTag
&&
693 t
->symbol
->type
->tag
.tagclass
!= ASN1_C_UNIV
&&
694 t
->symbol
->type
->tag
.tagenv
== TE_EXPLICIT
)
696 /* EXPLICIT UNIVERSAL tags are constructed if they are SEQUENCE/SET */
697 if (t
->symbol
->type
->type
== TTag
&&
698 t
->symbol
->type
->tag
.tagclass
== ASN1_C_UNIV
) {
699 switch (t
->symbol
->type
->tag
.tagvalue
) {
700 case UT_Sequence
: return 0;
701 case UT_Set
: return 0;
712 case TGeneralizedTime
:
718 case TPrintableString
:
721 case TUniversalString
:
726 return is_primitive_type(t
->subtype
);
736 fprintf(headerfile
, " ");
740 last_member_p(struct member
*m
)
742 struct member
*n
= HEIM_TAILQ_NEXT(m
, members
);
745 if (n
->ellipsis
&& HEIM_TAILQ_NEXT(n
, members
) == NULL
)
750 static struct member
*
751 have_ellipsis(Type
*t
)
754 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
762 define_asn1 (int level
, Type
*t
)
766 if (!t
->symbol
&& t
->typeref
.iosclass
) {
767 fprintf(headerfile
, "%s.&%s",
768 t
->typeref
.iosclass
->symbol
->name
,
769 t
->typeref
.field
->name
);
770 } else if (t
->symbol
)
771 fprintf(headerfile
, "%s", t
->symbol
->name
);
776 if(t
->members
== NULL
) {
777 fprintf (headerfile
, "INTEGER");
779 fprintf (headerfile
, " (%lld..%lld)",
780 (long long)t
->range
->min
,
781 (long long)t
->range
->max
);
784 fprintf (headerfile
, "INTEGER {\n");
785 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
787 fprintf(headerfile
, "%s(%lld)%s\n", m
->gen_name
,
788 (long long)m
->val
, last_member_p(m
));
791 fprintf (headerfile
, "}");
795 fprintf (headerfile
, "BOOLEAN");
798 fprintf (headerfile
, "OCTET STRING");
805 if(t
->type
== TBitString
)
806 fprintf (headerfile
, "BIT STRING {\n");
808 fprintf (headerfile
, "ENUMERATED {\n");
809 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
811 fprintf(headerfile
, "%s(%lld)%s\n", m
->name
,
812 (long long)m
->val
, last_member_p(m
));
815 fprintf (headerfile
, "}");
822 size_t max_width
= 0;
824 if(t
->type
== TChoice
)
825 fprintf(headerfile
, "CHOICE {\n");
826 else if(t
->type
== TSet
)
827 fprintf(headerfile
, "SET {\n");
829 fprintf(headerfile
, "SEQUENCE {\n");
830 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
831 if(strlen(m
->name
) > max_width
)
832 max_width
= strlen(m
->name
);
835 if(max_width
< 16) max_width
= 16;
836 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
837 size_t width
= max_width
;
840 fprintf (headerfile
, "...");
842 width
-= fprintf(headerfile
, "%s", m
->name
);
843 fprintf(headerfile
, "%*s", (int)width
, "");
844 define_asn1(level
+ 1, m
->type
);
846 fprintf(headerfile
, " OPTIONAL");
849 fprintf (headerfile
, ",");
850 fprintf (headerfile
, "\n");
853 fprintf (headerfile
, "}");
857 fprintf (headerfile
, "SEQUENCE OF ");
858 define_asn1 (0, t
->subtype
);
861 fprintf (headerfile
, "SET OF ");
862 define_asn1 (0, t
->subtype
);
864 case TGeneralizedTime
:
865 fprintf (headerfile
, "GeneralizedTime");
868 fprintf (headerfile
, "GeneralString");
871 fprintf (headerfile
, "TeletexString");
874 const char *classnames
[] = { "UNIVERSAL ", "APPLICATION ",
875 "" /* CONTEXT */, "PRIVATE " };
876 if(t
->tag
.tagclass
!= ASN1_C_UNIV
)
877 fprintf (headerfile
, "[%s%d] ",
878 classnames
[t
->tag
.tagclass
],
880 if(t
->tag
.tagenv
== TE_IMPLICIT
)
881 fprintf (headerfile
, "IMPLICIT ");
882 define_asn1 (level
, t
->subtype
);
886 fprintf (headerfile
, "UTCTime");
890 fprintf (headerfile
, "UTF8String");
892 case TPrintableString
:
894 fprintf (headerfile
, "PrintableString");
898 fprintf (headerfile
, "IA5String");
902 fprintf (headerfile
, "BMPString");
904 case TUniversalString
:
906 fprintf (headerfile
, "UniversalString");
910 fprintf (headerfile
, "VisibleString");
914 fprintf(headerfile
, "OBJECT IDENTIFIER");
918 fprintf (headerfile
, "NULL");
926 getnewbasename(char **newbasename
, int typedefp
, const char *basename
, const char *name
)
929 *newbasename
= strdup(name
);
933 if (asprintf(newbasename
, "%s_%s", basename
, name
) < 0)
936 if (*newbasename
== NULL
)
940 typedef enum define_type_options
{
942 DEF_TYPE_PRESERVE
= 1,
943 DEF_TYPE_TYPEDEFP
= 2,
944 DEF_TYPE_EMIT_NAME
= 4
945 } define_type_options
;
946 static void define_type(int, const char *, const char *, Type
*, Type
*, define_type_options
);
949 * Get the SET/SEQUENCE member pair and CLASS field pair defining an open type.
951 * There are three cases:
953 * - open types embedded in OCTET STRING, with the open type object class
954 * relation declared via a constraint
956 * - open types not embedded in OCTET STRING, which are really more like ANY
957 * DEFINED BY types, so, HEIM_ANY
959 * - open types in a nested structure member where the type ID field is in a
960 * member of the ancestor structure (this happens in PKIX's `AttributeSet',
961 * where the open type is essentially a SET OF HEIM_ANY).
963 * In a type like PKIX's SingleAttribute the type ID member would be the one
964 * named "type" and the open type member would be the one named "value", and
965 * the corresponding fields of the ATTRIBUTE class would be named "id" and
968 * NOTE: We assume a single open type member pair in any SET/SEQUENCE. In
969 * principle there could be more pairs and we could iterate them, or
970 * better yet, we could be given the name of an open type member and then
971 * just find its related type ID member and fields, then our caller would
972 * iterate the SET/SEQUENCE type's members looking for open type members
973 * and would call this function for each one found.
976 get_open_type_defn_fields(const Type
*t
,
977 Member
**typeidmember
,
978 Member
**opentypemember
,
980 Field
**opentypefield
,
984 Field
*junk1
, *junk2
;
985 char *idmembername
= NULL
;
987 if (!typeidfield
) typeidfield
= &junk1
;
988 if (!opentypefield
) opentypefield
= &junk2
;
990 *typeidfield
= *opentypefield
= NULL
;
991 *typeidmember
= *opentypemember
= NULL
;
994 /* Look for the open type member */
995 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
996 Type
*subtype
= m
->type
;
997 Type
*sOfType
= NULL
;
999 while (subtype
->type
== TTag
||
1000 subtype
->type
== TSetOf
||
1001 subtype
->type
== TSequenceOf
) {
1002 if (subtype
->type
== TTag
&& subtype
->subtype
) {
1003 if (subtype
->subtype
->type
== TOctetString
||
1004 subtype
->subtype
->type
== TBitString
)
1006 subtype
= subtype
->subtype
;
1007 } else if (subtype
->type
== TSetOf
|| subtype
->type
== TSequenceOf
) {
1009 if (sOfType
->symbol
)
1011 if (subtype
->subtype
)
1012 subtype
= subtype
->subtype
;
1017 * If we traversed through a non-inlined SET OF or SEQUENCE OF type,
1018 * then this cannot be an open type field.
1020 if (sOfType
&& sOfType
->symbol
)
1023 * The type of the field we're interested in has to have an information
1024 * object constraint.
1026 if (!subtype
->constraint
)
1028 if (subtype
->type
!= TType
&& subtype
->type
!= TTag
)
1031 * Check if it's an ANY-like member or like an OCTET STRING CONTAINING
1032 * member. Those are the only two possibilities.
1034 if ((subtype
->type
== TTag
|| subtype
->type
== TType
) &&
1036 subtype
->constraint
->ctype
== CT_CONTENTS
&&
1037 subtype
->constraint
->u
.content
.type
&&
1038 subtype
->constraint
->u
.content
.type
->type
== TType
&&
1039 !subtype
->constraint
->u
.content
.type
->subtype
&&
1040 subtype
->constraint
->u
.content
.type
->constraint
&&
1041 subtype
->constraint
->u
.content
.type
->constraint
->ctype
== CT_TABLE_CONSTRAINT
) {
1042 /* Type like OCTET STRING or BIT STRING CONTAINING open type */
1043 if (*opentypemember
)
1044 errx(1, "Multiple open type members %s and %s for the same "
1045 "field %s?", (*opentypemember
)->name
, m
->name
,
1046 (*opentypefield
)->name
);
1047 *opentypemember
= m
;
1048 *opentypefield
= subtype
->constraint
->u
.content
.type
->typeref
.field
;
1049 *is_array_of
= sOfType
!= NULL
;
1050 idmembername
= subtype
->constraint
->u
.content
.type
->constraint
->u
.content
.crel
.membername
;
1052 } else if (subtype
->symbol
&& strcmp(subtype
->symbol
->name
, "HEIM_ANY") == 0) {
1053 /* Open type, but NOT embedded in OCTET STRING or BIT STRING */
1054 if (*opentypemember
)
1055 errx(1, "Multiple open type members %s and %s for the same "
1056 "field %s?", (*opentypemember
)->name
, m
->name
,
1057 (*opentypefield
)->name
);
1058 *opentypemember
= m
;
1059 *opentypefield
= subtype
->typeref
.field
;
1060 *is_array_of
= sOfType
!= NULL
;
1061 idmembername
= subtype
->constraint
->u
.content
.crel
.membername
;
1067 errx(1, "Missing open type id member in %s",
1068 t
->symbol
? t
->symbol
->name
: "<unknown type>");
1069 /* Look for the type ID member identified in the previous loop */
1070 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
1071 if (!m
->type
->subtype
|| strcmp(m
->name
, idmembername
) != 0)
1073 if (m
->type
->constraint
&&
1074 m
->type
->constraint
->ctype
== CT_TABLE_CONSTRAINT
)
1075 *typeidfield
= m
->type
->typeref
.field
;
1076 else if (m
->type
->subtype
->constraint
&&
1077 m
->type
->subtype
->constraint
->ctype
== CT_TABLE_CONSTRAINT
)
1078 *typeidfield
= m
->type
->subtype
->typeref
.field
;
1081 /* This is the type ID field (because there _is_ a subtype) */
1088 * Generate CHOICE-like struct fields for open types declared via
1089 * X.681/682/683 syntax.
1091 * We could support multiple open type members in a SET/SEQUENCE, but for now
1092 * we support only one.
1095 define_open_type(int level
, const char *newbasename
, const char *name
, const char *basename
, Type
*pt
, Type
*t
)
1097 Member
*opentypemember
, *typeidmember
;
1098 Field
*opentypefield
, *typeidfield
;
1100 IOSObjectSet
*os
= pt
->actual_parameter
;
1101 IOSObject
**objects
;
1103 int is_array_of_open_type
;
1105 get_open_type_defn_fields(pt
, &typeidmember
, &opentypemember
,
1106 &typeidfield
, &opentypefield
,
1107 &is_array_of_open_type
);
1108 if (!opentypemember
|| !typeidmember
||
1109 !opentypefield
|| !typeidfield
)
1110 errx(1, "Open type specification in %s is incomplete", name
);
1112 sort_object_set(os
, typeidfield
, &objects
, &nobjs
);
1114 fprintf(headerfile
, "struct {\n");
1115 fprintf(jsonfile
, "{\"opentype\":true,\"arraytype\":%s,",
1116 is_array_of_open_type
? "true" : "false");
1117 fprintf(jsonfile
, "\"classname\":\"%s\",", os
->iosclass
->symbol
->name
);
1118 fprintf(jsonfile
, "\"objectsetname\":\"%s\",", os
->symbol
->name
);
1119 fprintf(jsonfile
, "\"typeidmember\":\"%s\",", typeidmember
->name
);
1120 fprintf(jsonfile
, "\"opentypemember\":\"%s\",", opentypemember
->name
);
1121 fprintf(jsonfile
, "\"typeidfield\":\"%s\",", typeidfield
->name
);
1122 fprintf(jsonfile
, "\"opentypefield\":\"%s\",", opentypefield
->name
);
1124 /* Iterate objects in the object set, gen enum labels */
1125 fprintf(headerfile
, "enum { choice_%s_iosnumunknown = 0,\n",
1127 fprintf(jsonfile
, "\"opentypeids\":[");
1128 for (i
= 0; i
< nobjs
; i
++) {
1129 HEIM_TAILQ_FOREACH(of
, objects
[i
]->objfields
, objfields
) {
1130 if (strcmp(of
->name
, typeidfield
->name
) != 0)
1132 if (!of
->value
|| !of
->value
->s
)
1133 errx(1, "Unknown value in value field %s of object %s",
1134 of
->name
, objects
[i
]->symbol
->name
);
1135 fprintf(headerfile
, "choice_%s_iosnum_%s,\n",
1136 newbasename
, of
->value
->s
->gen_name
);
1137 fprintf(jsonfile
, "\"%s\"", of
->value
->s
->gen_name
);
1138 fprintf(jsonfile
, "%s", (i
+ 1) < nobjs
? "," : "");
1141 fprintf(jsonfile
, "],\n");
1142 fprintf(headerfile
, "} element;\n");
1144 if (is_array_of_open_type
)
1145 fprintf(headerfile
, "unsigned int len;\n");
1147 /* Iterate objects in the object set, gen union arms */
1148 fprintf(headerfile
, "union {\nvoid *_any;\n");
1149 fprintf(jsonfile
, "\"members\":[");
1150 for (i
= 0; i
< nobjs
; i
++) {
1151 HEIM_TAILQ_FOREACH(of
, objects
[i
]->objfields
, objfields
) {
1154 /* XXX Print the type IDs into the jsonfile too pls */
1156 if (strcmp(of
->name
, opentypefield
->name
) != 0)
1158 if (!of
->type
|| (!of
->type
->symbol
&& of
->type
->type
!= TTag
) ||
1159 of
->type
->tag
.tagclass
!= ASN1_C_UNIV
) {
1160 warnx("Ignoring unknown or unset type field %s of object %s",
1161 of
->name
, objects
[i
]->symbol
->name
);
1165 if (asprintf(&n
, "*%s", objects
[i
]->symbol
->gen_name
) < 0 || n
== NULL
)
1167 define_type(level
+ 2, n
, newbasename
, NULL
, of
->type
, DEF_TYPE_NONE
);
1168 fprintf(jsonfile
, "%s", (i
+ 1) < nobjs
? "," : "");
1172 fprintf(jsonfile
, "]}\n");
1173 if (is_array_of_open_type
) {
1174 fprintf(headerfile
, "} *val;\n} _ioschoice_%s;\n", opentypemember
->gen_name
);
1176 fprintf(headerfile
, "} u;\n");
1177 fprintf(headerfile
, "} _ioschoice_%s;\n", opentypemember
->gen_name
);
1182 static const char * const tagclassnames
[] = {
1183 "UNIVERSAL", "APPLICATION", "CONTEXT", "PRIVATE"
1187 define_type(int level
, const char *name
, const char *basename
,
1188 Type
*pt
, Type
*t
, define_type_options opts
)
1190 const char *label_prefix
= NULL
;
1191 const char *label_prefix_sep
= NULL
;
1192 char *newbasename
= NULL
;
1194 fprintf(jsonfile
, "{\"name\":\"%s\",\"gen_name\":\"%s\","
1195 "\"is_type\":true,\"exported\":%s,\"typedef\":%s,",
1197 t
->symbol
&& is_export(t
->symbol
->name
) ? "true" : "false",
1198 (opts
& DEF_TYPE_TYPEDEFP
) ? "true" : "false");
1203 if (!t
->symbol
&& t
->actual_parameter
) {
1204 define_open_type(level
, newbasename
, name
, basename
, t
, t
);
1205 } else if (!t
->symbol
&& pt
->actual_parameter
) {
1206 define_open_type(level
, newbasename
, name
, basename
, pt
, t
);
1207 } else if (t
->symbol
) {
1208 fprintf(headerfile
, "%s %s;\n", t
->symbol
->gen_name
, name
);
1209 fprintf(jsonfile
, "\"ttype\":\"%s\","
1210 "\"alias\":true\n", t
->symbol
->gen_name
);
1215 if (t
->symbol
&& t
->symbol
->emitted_definition
)
1222 label_prefix
= prefix_enum
? name
: (enum_prefix
? enum_prefix
: "");
1223 label_prefix_sep
= prefix_enum
? "_" : "";
1224 fprintf (headerfile
, "enum %s {\n", (opts
& DEF_TYPE_TYPEDEFP
) ? name
: "");
1225 fprintf(jsonfile
, "\"ttype\":\"INTEGER\",\"ctype\":\"enum\","
1227 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
1229 fprintf(headerfile
, "%s%s%s = %lld%s\n",
1230 label_prefix
, label_prefix_sep
,
1231 m
->gen_name
, (long long)m
->val
, last_member_p(m
));
1232 fprintf(jsonfile
, "{\"%s%s%s\":%lld}%s\n",
1233 label_prefix
, label_prefix_sep
,
1234 m
->gen_name
, (long long)m
->val
, last_member_p(m
));
1236 fprintf(headerfile
, "} %s;\n", name
);
1237 fprintf(jsonfile
, "]");
1238 } else if (t
->range
== NULL
) {
1239 fprintf(headerfile
, "heim_integer %s;\n", name
);
1240 fprintf(jsonfile
, "\"ttype\":\"INTEGER\",\"ctype\":\"heim_integer\"");
1241 } else if (t
->range
->min
< 0 &&
1242 (t
->range
->min
< INT_MIN
|| t
->range
->max
> INT_MAX
)) {
1243 fprintf(headerfile
, "int64_t %s;\n", name
);
1244 fprintf(jsonfile
, "\"ttype\":\"INTEGER\",\"ctype\":\"int64_t\"");
1245 } else if (t
->range
->min
< 0) {
1246 fprintf (headerfile
, "int %s;\n", name
);
1247 fprintf(jsonfile
, "\"ttype\":\"INTEGER\",\"ctype\":\"int\"");
1248 } else if (t
->range
->max
> UINT_MAX
) {
1249 fprintf (headerfile
, "uint64_t %s;\n", name
);
1250 fprintf(jsonfile
, "\"ttype\":\"INTEGER\",\"ctype\":\"uint64_t\"");
1252 fprintf (headerfile
, "unsigned int %s;\n", name
);
1253 fprintf(jsonfile
, "\"ttype\":\"INTEGER\",\"ctype\":\"unsigned int\"");
1258 fprintf (headerfile
, "int %s;\n", name
);
1259 fprintf(jsonfile
, "\"ttype\":\"BOOLEAN\",\"ctype\":\"unsigned int\"");
1263 fprintf (headerfile
, "heim_octet_string %s;\n", name
);
1264 fprintf(jsonfile
, "\"ttype\":\"OCTET STRING\",\"ctype\":\"heim_octet_string\"");
1269 struct range range
= { 0, UINT_MAX
};
1270 size_t max_memno
= 0;
1273 if (t
->symbol
&& t
->symbol
->emitted_definition
)
1275 memset(&i
, 0, sizeof(i
));
1278 * range.max implies the size of the base unsigned integer used for the
1279 * bitfield members. If it's less than or equal to UINT_MAX, then that
1280 * will be unsigned int, otherwise it will be uint64_t.
1282 * We could just use uint64_t, yes, but for now, and in case that any
1283 * projects were exposing the BIT STRING types' C representations in
1284 * ABIs prior to this compiler supporting BIT STRING with larger
1285 * members, we stick to this.
1287 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
1288 if (m
->val
> max_memno
)
1292 range
.max
= INT64_MAX
;
1294 range
.max
= 1ULL << max_memno
;
1299 i
.constraint
= NULL
;
1302 fprintf(jsonfile
, "\"ttype\":\"BIT STRING\",");
1303 if(HEIM_TAILQ_EMPTY(t
->members
)) {
1304 fprintf (headerfile
, "heim_bit_string %s;\n", name
);
1305 fprintf(jsonfile
, "\"ctype\":\"heim_bit_string\"");
1308 getnewbasename(&newbasename
, (opts
& DEF_TYPE_TYPEDEFP
) || level
== 0, basename
, name
);
1310 fprintf (headerfile
, "struct %s {\n", newbasename
);
1311 fprintf(jsonfile
, "\"ctype\":\"struct %s\",\"members\":[\n", newbasename
);
1312 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
1316 * pad unused bits beween declared members (hopefully this
1317 * forces the compiler to give us an obvious layout)
1319 while (pos
< m
->val
) {
1320 if (asprintf (&n
, "_unused%lld:1", (long long)pos
) < 0 ||
1323 define_type(level
+ 1, n
, newbasename
, NULL
, &i
, DEF_TYPE_EMIT_NAME
);
1324 fprintf(jsonfile
, ",");
1330 if (asprintf (&n
, "%s:1", m
->gen_name
) < 0 || n
== NULL
)
1332 define_type(level
+ 1, n
, newbasename
, NULL
, &i
, DEF_TYPE_EMIT_NAME
);
1333 fprintf(jsonfile
, "%s", last_member_p(m
));
1338 /* pad unused tail (ditto) */
1339 bitset_size
= max_memno
;
1341 bitset_size
+= 64 - (max_memno
% 64);
1344 if (pos
< bitset_size
)
1345 fprintf(jsonfile
, ",");
1346 while (pos
< bitset_size
) {
1348 if (asprintf (&n
, "_unused%lld:1", (long long)pos
) < 0 ||
1351 define_type(level
+ 1, n
, newbasename
, NULL
, &i
, DEF_TYPE_EMIT_NAME
);
1352 fprintf(jsonfile
, "%s", (pos
+ 1) < bitset_size
? "," : "");
1358 fprintf(headerfile
, "}%s%s;\n\n",
1359 (opts
& DEF_TYPE_EMIT_NAME
) ? " " : "",
1360 (opts
& DEF_TYPE_EMIT_NAME
) ? name
: "");
1361 fprintf(jsonfile
, "]");
1368 if (t
->symbol
&& t
->symbol
->emitted_definition
)
1371 label_prefix
= prefix_enum
? name
: (enum_prefix
? enum_prefix
: "");
1372 label_prefix_sep
= prefix_enum
? "_" : "";
1374 fprintf (headerfile
, "enum %s {\n", (opts
& DEF_TYPE_TYPEDEFP
) ? name
: "");
1375 fprintf(jsonfile
, "\"ctype\":\"enum %s\",\"extensible\":%s,\"members\":[\n",
1376 (opts
& DEF_TYPE_TYPEDEFP
) ? name
: "", have_ellipsis(t
) ? "true" : "false");
1377 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
1380 fprintf (headerfile
, "/* ... */\n");
1382 fprintf(headerfile
, "%s%s%s = %lld%s\n",
1383 label_prefix
, label_prefix_sep
,
1384 m
->gen_name
, (long long)m
->val
, last_member_p(m
));
1385 fprintf(jsonfile
, "{\"%s%s%s\":%lld%s}\n",
1386 label_prefix
, label_prefix_sep
,
1387 m
->gen_name
, (long long)m
->val
, last_member_p(m
));
1391 fprintf(headerfile
, "}%s%s;\n\n",
1392 (opts
& DEF_TYPE_EMIT_NAME
) ? " " : "",
1393 (opts
& DEF_TYPE_EMIT_NAME
) ? name
: "");
1394 fprintf(jsonfile
, "]");
1400 struct decoration deco
;
1401 ssize_t more_deco
= -1;
1404 getnewbasename(&newbasename
, (opts
& DEF_TYPE_TYPEDEFP
) || level
== 0, basename
, name
);
1408 fprintf (headerfile
, "struct %s {\n", newbasename
);
1409 fprintf(jsonfile
, "\"ttype\":\"%s\",\"extensible\":%s,"
1410 "\"ctype\":\"struct %s\"",
1411 t
->type
== TSet
? "SET" : "SEQUENCE",
1412 have_ellipsis(t
) ? "true" : "false", newbasename
);
1413 if (t
->type
== TSequence
&& (opts
& DEF_TYPE_PRESERVE
)) {
1415 fprintf(headerfile
, "heim_octet_string _save;\n");
1416 fprintf(jsonfile
, ",\"preserve\":true");
1418 fprintf(jsonfile
, ",\"members\":[\n");
1419 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
1422 } else if (m
->optional
|| m
->defval
) {
1423 char *n
= NULL
, *defval
= NULL
;
1424 const char *namep
, *defvalp
;
1427 switch (m
->defval
->type
) {
1429 if (asprintf(&defval
, "\"%s\"", m
->defval
->u
.stringvalue
) < 0 || defval
== NULL
)
1434 if (asprintf(&defval
, "%lld", (long long)m
->defval
->u
.integervalue
) < 0 || defval
== NULL
)
1439 defvalp
= m
->defval
->u
.booleanvalue
? "true" : "false";
1448 if (asprintf(&n
, "*%s", m
->gen_name
) < 0 || n
== NULL
)
1452 namep
= m
->gen_name
;
1454 fprintf(jsonfile
, "{\"name\":\"%s\",\"gen_name\":\"%s\","
1455 "\"optional\":%s,\"defval\":%s,\"type\":",
1456 m
->name
, m
->gen_name
, m
->optional
? "true" : "false", defvalp
);
1457 define_type(level
+ 1, namep
, newbasename
, t
, m
->type
, DEF_TYPE_EMIT_NAME
);
1458 fprintf(jsonfile
, "}%s", last_member_p(m
));
1462 fprintf(jsonfile
, "{\"name\":\"%s\",\"gen_name\":\"%s\","
1463 "\"optional\":false,\"type\":", m
->name
, m
->gen_name
);
1464 define_type(level
+ 1, m
->gen_name
, newbasename
, t
, m
->type
, DEF_TYPE_EMIT_NAME
);
1465 fprintf(jsonfile
, "}%s", last_member_p(m
));
1468 fprintf(jsonfile
, "]");
1469 if (t
->actual_parameter
&& t
->actual_parameter
->objects
) {
1470 fprintf(jsonfile
, ",\"opentype\":");
1471 define_open_type(level
, newbasename
, name
, basename
, t
, t
);
1473 while (decorate_type(newbasename
, &deco
, &more_deco
)) {
1476 fprintf(headerfile
, "%s %s%s;\n", deco
.field_type
,
1477 deco
.opt
? "*" : "", deco
.field_name
);
1479 fprintf(jsonfile
, ",\"decorate\":[");
1480 fprintf(jsonfile
, "%s{"
1481 "\"type\":\"%s\",\"name\":\"%s\",\"optional\":%s,"
1482 "\"external\":%s,\"pointer\":%s,\"void_star\":%s,"
1483 "\"struct_star\":%s,"
1484 "\"copy_function\":\"%s\","
1485 "\"free_function\":\"%s\",\"header_name\":%s%s%s"
1487 deco
.first
? "" : ",",
1488 deco
.field_type
, deco
.field_name
,
1489 deco
.opt
? "true" : "false", deco
.ext
? "true" : "false",
1490 deco
.ptr
? "true" : "false", deco
.void_star
? "true" : "false",
1491 deco
.struct_star
? "true" : "false",
1492 deco
.copy_function_name
? deco
.copy_function_name
: "",
1493 deco
.free_function_name
? deco
.free_function_name
: "",
1494 deco
.header_name
&& deco
.header_name
[0] == '"' ? "" : "\"",
1495 deco
.header_name
? deco
.header_name
: "",
1496 deco
.header_name
&& deco
.header_name
[0] == '"' ? "" : "\""
1500 fprintf(jsonfile
, "]");
1502 fprintf(headerfile
, "}%s%s;\n",
1503 (opts
& DEF_TYPE_EMIT_NAME
) ? " " : "",
1504 (opts
& DEF_TYPE_EMIT_NAME
) ? name
: "");
1505 free(deco
.field_type
);
1511 struct range range
= { 0, UINT_MAX
};
1513 getnewbasename(&newbasename
, (opts
& DEF_TYPE_TYPEDEFP
) || level
== 0, basename
, name
);
1515 memset(&i
, 0, sizeof(i
));
1520 fprintf (headerfile
, "struct %s {\n", newbasename
);
1521 fprintf(jsonfile
, "\"ttype\":\"%s\",\"ctype\":\"struct %s\",\"members\":[",
1522 t
->type
== TSetOf
? "SET OF" : "SEQUENCE OF", newbasename
);
1523 define_type(level
+ 1, "len", newbasename
, t
, &i
, DEF_TYPE_NONE
);
1524 fprintf(jsonfile
, ",");
1525 define_type(level
+ 1, "*val", newbasename
, t
, t
->subtype
, DEF_TYPE_NONE
| DEF_TYPE_EMIT_NAME
);
1527 fprintf(headerfile
, "}%s%s;\n",
1528 (opts
& DEF_TYPE_EMIT_NAME
) ? " " : "",
1529 (opts
& DEF_TYPE_EMIT_NAME
) ? name
: "");
1530 fprintf(jsonfile
, "]");
1533 case TGeneralizedTime
:
1535 fprintf (headerfile
, "time_t %s;\n", name
);
1536 fprintf(jsonfile
, "\"ttype\":\"GeneralizedTime\",\"ctype\":\"time_t\"");
1538 case TGeneralString
:
1540 fprintf (headerfile
, "heim_general_string %s;\n", name
);
1541 fprintf(jsonfile
, "\"ttype\":\"GeneralString\",\"ctype\":\"heim_general_string\"");
1543 case TTeletexString
:
1545 fprintf (headerfile
, "heim_general_string %s;\n", name
);
1546 fprintf(jsonfile
, "\"ttype\":\"TeletexString\",\"ctype\":\"heim_general_string\"");
1549 if (t
->implicit_choice
) {
1550 fprintf(jsonfile
, "\"desired_tagenv\":\"IMPLICIT\",");
1552 fprintf(jsonfile
, "\"tagclass\":\"%s\",\"tagvalue\":%d,\"tagenv\":\"%s\",\n",
1553 tagclassnames
[t
->tag
.tagclass
], t
->tag
.tagvalue
,
1554 t
->tag
.tagenv
== TE_EXPLICIT
? "EXPLICIT" : "IMPLICIT");
1555 fprintf(jsonfile
, "\"ttype\":\n");
1556 define_type(level
, name
, basename
, t
, t
->subtype
, opts
);
1559 struct decoration deco
;
1560 ssize_t more_deco
= -1;
1565 getnewbasename(&newbasename
, (opts
& DEF_TYPE_TYPEDEFP
) || level
== 0, basename
, name
);
1568 fprintf (headerfile
, "struct %s {\n", newbasename
);
1569 fprintf(jsonfile
, "\"ttype\":\"CHOICE\",\"ctype\":\"struct %s\"",
1571 if ((opts
& DEF_TYPE_PRESERVE
)) {
1573 fprintf(headerfile
, "heim_octet_string _save;\n");
1574 fprintf(jsonfile
, ",\"preserve\":true");
1577 fprintf (headerfile
, "enum %s_enum {\n", newbasename
);
1578 m
= have_ellipsis(t
);
1581 fprintf (headerfile
, "%s = 0,\n", m
->label
);
1584 fprintf(jsonfile
, ",\"extensible\":%s", m
? "true" : "false");
1585 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
1588 fprintf (headerfile
, "/* ... */\n");
1590 fprintf (headerfile
, "%s%s%s\n", m
->label
,
1591 first
? " = 1" : "",
1596 fprintf (headerfile
, "} element;\n");
1598 fprintf (headerfile
, "union {\n");
1599 fprintf(jsonfile
, ",\"members\":[\n");
1600 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
1603 fprintf(headerfile
, "heim_octet_string asn1_ellipsis;\n");
1604 } else if (m
->optional
) {
1607 if (asprintf (&n
, "*%s", m
->gen_name
) < 0 || n
== NULL
)
1609 fprintf(jsonfile
, "{\"optional\":");
1610 define_type(level
+ 2, n
, newbasename
, t
, m
->type
, DEF_TYPE_EMIT_NAME
);
1611 fprintf(jsonfile
, "}%s", last_member_p(m
));
1614 define_type(level
+ 2, m
->gen_name
, newbasename
, t
, m
->type
, DEF_TYPE_EMIT_NAME
);
1615 fprintf(jsonfile
, "%s", last_member_p(m
));
1619 fprintf (headerfile
, "} u;\n");
1620 fprintf(jsonfile
, "]");
1622 while (decorate_type(newbasename
, &deco
, &more_deco
)) {
1625 fprintf(headerfile
, "%s %s%s;\n", deco
.field_type
,
1626 deco
.opt
? "*" : "", deco
.field_name
);
1628 fprintf(jsonfile
, ",\"decorate\":[");
1629 fprintf(jsonfile
, "%s{"
1630 "\"type\":\"%s\",\"name\":\"%s\",\"optional\":%s,"
1631 "\"external\":%s,\"pointer\":%s,\"void_star\":%s,"
1632 "\"struct_star\":%s,"
1633 "\"copy_function\":\"%s\","
1634 "\"free_function\":\"%s\",\"header_name\":%s%s%s"
1636 deco
.first
? "" : ",",
1637 deco
.field_type
, deco
.field_name
,
1638 deco
.opt
? "true" : "false", deco
.ext
? "true" : "false",
1639 deco
.ptr
? "true" : "false", deco
.void_star
? "true" : "false",
1640 deco
.struct_star
? "true" : "false",
1641 deco
.copy_function_name
? deco
.copy_function_name
: "",
1642 deco
.free_function_name
? deco
.free_function_name
: "",
1643 deco
.header_name
&& deco
.header_name
[0] == '"' ? "" : "\"",
1644 deco
.header_name
? deco
.header_name
: "",
1645 deco
.header_name
&& deco
.header_name
[0] == '"' ? "" : "\""
1649 fprintf(jsonfile
, "]");
1652 fprintf(headerfile
, "}%s%s;\n",
1653 (opts
& DEF_TYPE_EMIT_NAME
) ? " " : "",
1654 (opts
& DEF_TYPE_EMIT_NAME
) ? name
: "");
1659 fprintf (headerfile
, "time_t %s;\n", name
);
1660 fprintf(jsonfile
, "\"ttype\":\"UTCTime\",\"ctype\":\"time_t\"");
1664 fprintf (headerfile
, "heim_utf8_string %s;\n", name
);
1665 fprintf(jsonfile
, "\"ttype\":\"UTF8String\",\"ctype\":\"heim_utf8_string\"");
1667 case TPrintableString
:
1669 fprintf (headerfile
, "heim_printable_string %s;\n", name
);
1670 fprintf(jsonfile
, "\"ttype\":\"PrintableString\",\"ctype\":\"heim_printable_string\"");
1674 fprintf (headerfile
, "heim_ia5_string %s;\n", name
);
1675 fprintf(jsonfile
, "\"ttype\":\"IA5String\",\"ctype\":\"heim_ia5_string\"");
1679 fprintf (headerfile
, "heim_bmp_string %s;\n", name
);
1680 fprintf(jsonfile
, "\"ttype\":\"BMPString\",\"ctype\":\"heim_bmp_string\"");
1682 case TUniversalString
:
1684 fprintf (headerfile
, "heim_universal_string %s;\n", name
);
1685 fprintf(jsonfile
, "\"ttype\":\"UniversalString\",\"ctype\":\"heim_universal_string\"");
1687 case TVisibleString
:
1689 fprintf (headerfile
, "heim_visible_string %s;\n", name
);
1690 fprintf(jsonfile
, "\"ttype\":\"VisibleString\",\"ctype\":\"heim_visible_string\"");
1694 fprintf (headerfile
, "heim_oid %s;\n", name
);
1695 fprintf(jsonfile
, "\"ttype\":\"OBJECT IDENTIFIER\",\"ctype\":\"heim_oid\"");
1699 fprintf (headerfile
, "int %s;\n", name
);
1700 fprintf(jsonfile
, "\"ttype\":\"NULL\",\"ctype\":\"int\"");
1705 fprintf(jsonfile
, "}\n");
1710 declare_type(const Symbol
*s
, Type
*t
, int typedefp
)
1712 char *newbasename
= NULL
;
1715 fprintf(headerfile
, "typedef ");
1719 define_type(0, s
->gen_name
, s
->gen_name
, NULL
, s
->type
,
1720 DEF_TYPE_PRESERVE
| DEF_TYPE_TYPEDEFP
|
1721 (s
->emitted_declaration
? 0 : DEF_TYPE_EMIT_NAME
));
1722 if (template_flag
&& !s
->emitted_declaration
)
1723 generate_template_type_forward(s
->gen_name
);
1724 emitted_declaration(s
);
1731 case TGeneralizedTime
:
1732 case TGeneralString
:
1733 case TTeletexString
:
1736 case TPrintableString
:
1739 case TUniversalString
:
1740 case TVisibleString
:
1743 define_type(0, s
->gen_name
, s
->gen_name
, NULL
, s
->type
,
1744 DEF_TYPE_PRESERVE
| DEF_TYPE_TYPEDEFP
|
1745 (s
->emitted_declaration
? 0 : DEF_TYPE_EMIT_NAME
));
1746 if (template_flag
&& !s
->emitted_declaration
)
1747 generate_template_type_forward(s
->gen_name
);
1748 emitted_declaration(s
);
1749 emitted_definition(s
);
1752 if (!s
->emitted_declaration
)
1753 declare_type(s
, t
->subtype
, FALSE
);
1754 emitted_declaration(s
);
1763 struct decoration deco
;
1764 ssize_t more_deco
= -1;
1766 getnewbasename(&newbasename
, TRUE
, s
->gen_name
, s
->gen_name
);
1767 fprintf(headerfile
, "struct %s %s;\n", newbasename
, s
->gen_name
);
1768 while (decorate_type(newbasename
, &deco
, &more_deco
)) {
1769 if (deco
.header_name
)
1770 fprintf(headerfile
, "#include %s\n", deco
.header_name
);
1771 free(deco
.field_type
);
1777 getnewbasename(&newbasename
, TRUE
, s
->gen_name
, s
->gen_name
);
1778 fprintf(headerfile
, "struct %s %s;\n", newbasename
, s
->gen_name
);
1781 struct decoration deco
;
1782 ssize_t more_deco
= -1;
1784 getnewbasename(&newbasename
, TRUE
, s
->gen_name
, s
->gen_name
);
1785 fprintf(headerfile
, "struct %s %s;\n", newbasename
, s
->gen_name
);
1786 while (decorate_type(newbasename
, &deco
, &more_deco
)) {
1787 if (deco
.header_name
)
1788 fprintf(headerfile
, "#include %s\n", deco
.header_name
);
1789 free(deco
.field_type
);
1797 emitted_declaration(s
);
1800 static void generate_subtypes_header_helper(const Member
*m
);
1801 static void generate_type_header(const Symbol
*);
1804 generate_subtypes_header_helper(const Member
*m
)
1811 if (m
->type
->symbol
&& (s
= getsym(m
->type
->symbol
->name
)) &&
1812 !s
->emitted_definition
) {
1813 /* A field of some named type; recurse */
1814 if (!m
->optional
&& !m
->defval
)
1815 generate_type_header(s
);
1818 if (!m
->type
->subtype
&& !m
->type
->members
)
1820 if (m
->type
->type
== TTag
&&
1821 m
->type
->subtype
&& m
->type
->subtype
->symbol
&&
1822 (s
= getsym(m
->type
->subtype
->symbol
->name
))) {
1823 if (!m
->optional
&& !m
->defval
)
1824 generate_type_header(s
);
1827 if (m
->type
->subtype
) {
1828 switch (m
->type
->subtype
->type
) {
1836 /* A field of some anonymous (inlined) structured type */
1837 HEIM_TAILQ_FOREACH(sm
, m
->type
->subtype
->members
, members
) {
1838 generate_subtypes_header_helper(sm
);
1841 if (m
->type
->members
) {
1842 HEIM_TAILQ_FOREACH(sm
, m
->type
->members
, members
) {
1843 generate_subtypes_header_helper(sm
);
1849 generate_subtypes_header(const Symbol
*s
)
1855 * Recurse down structured types to make sure top-level types get
1856 * defined before they are referenced.
1858 * We'll take care to skip OPTIONAL member fields of constructed types so
1859 * that we can have circular types like:
1861 * Foo ::= SEQUENCE {
1865 * Bar ::= SEQUENCE {
1869 * not unlike XDR, which uses `*' to mean "optional", except in XDR it's
1870 * called a "pointer". With some care we should be able to eventually
1871 * support the silly XDR linked list example:
1873 * ListOfFoo ::= SEQUENCE {
1874 * someField SomeType,
1875 * next ListOfFoo OPTIONAL
1878 * Not that anyone needs it -- just use a SEQUENCE OF and be done.
1881 while (t
->type
== TTag
&& t
->subtype
) {
1882 switch (t
->subtype
->type
) {
1899 if (t
->symbol
&& (s2
= getsym(t
->symbol
->name
)) != s
)
1900 generate_type_header(s2
);
1909 HEIM_TAILQ_FOREACH(m
, t
->members
, members
) {
1910 generate_subtypes_header_helper(m
);
1915 generate_type_header (const Symbol
*s
)
1923 * Recurse down the types of member fields of `s' to make sure that
1924 * referenced types have had their definitions emitted already if the
1925 * member fields are not OPTIONAL/DEFAULTed.
1927 generate_subtypes_header(s
);
1928 if (!s
->emitted_asn1
) {
1929 fprintf(headerfile
, "/*\n");
1930 fprintf(headerfile
, "%s ::= ", s
->name
);
1931 define_asn1 (0, s
->type
);
1932 fprintf(headerfile
, "\n*/\n\n");
1937 * Emit enums for the outermost tag of this type. These are needed for
1938 * dealing with IMPLICIT tags so we know what to rewrite the tag to when
1941 * See gen_encode.c and gen_decode.c for a complete explanation. Short
1942 * version: we need to change the prototypes of the length/encode/decode
1943 * functions to take an optional IMPLICIT tag to use instead of the type's
1944 * outermost tag, but for now we hack it, and to do that we need to know
1945 * the type's outermost tag outside the context of the bodies of the codec
1946 * functions we generate for it. Using an enum means no extra space is
1947 * needed in stripped objects.
1949 if (!s
->emitted_tag_enums
) {
1950 while (t
->type
== TType
&& s
->type
->symbol
&& s
->type
->symbol
->type
) {
1954 t
= s
->type
->symbol
->type
;
1957 if (t
->type
== TType
&& t
->symbol
&&
1958 strcmp(t
->symbol
->name
, "HEIM_ANY") != 0) {
1960 * This type is ultimately an alias of an imported type, so we don't
1961 * know its outermost tag here.
1964 "enum { asn1_tag_length_%s = asn1_tag_length_%s,\n"
1965 " asn1_tag_class_%s = asn1_tag_class_%s,\n"
1966 " asn1_tag_tag_%s = asn1_tag_tag_%s };\n",
1967 s
->gen_name
, s
->type
->symbol
->gen_name
,
1968 s
->gen_name
, s
->type
->symbol
->gen_name
,
1969 s
->gen_name
, s
->type
->symbol
->gen_name
);
1970 emitted_tag_enums(s
);
1971 } else if (t
->type
!= TType
) {
1972 /* This type's outermost tag is known here */
1974 "enum { asn1_tag_length_%s = %lu,\n"
1975 " asn1_tag_class_%s = %d,\n"
1976 " asn1_tag_tag_%s = %d };\n",
1977 s
->gen_name
, (unsigned long)length_tag(s
->type
->tag
.tagvalue
),
1978 s
->gen_name
, s
->type
->tag
.tagclass
,
1979 s
->gen_name
, s
->type
->tag
.tagvalue
);
1980 emitted_tag_enums(s
);
1984 if (s
->emitted_definition
)
1987 if (is_export(s
->name
))
1988 fprintf(symsfile
, "ASN1_SYM_TYPE(\"%s\", \"%s\", %s)\n",
1989 s
->name
, s
->gen_name
, s
->gen_name
);
1991 if (!s
->emitted_declaration
) {
1992 fprintf(headerfile
, "typedef ");
1993 define_type(0, s
->gen_name
, s
->gen_name
, NULL
, s
->type
,
1994 DEF_TYPE_TYPEDEFP
| DEF_TYPE_EMIT_NAME
|
1995 (preserve_type(s
->name
) ? DEF_TYPE_PRESERVE
: 0));
1996 } else if (s
->type
->type
== TType
) {
1997 /* This is a type alias and we've already declared it */
1998 } else if (s
->type
->type
== TTag
&&
1999 s
->type
->subtype
!= NULL
&&
2000 s
->type
->subtype
->symbol
!= NULL
) {
2001 /* This is a type alias and we've already declared it */
2003 define_type(0, s
->gen_name
, s
->gen_name
, NULL
, s
->type
,
2005 (preserve_type(s
->name
) ? DEF_TYPE_PRESERVE
: 0));
2007 fprintf(headerfile
, "\n");
2009 emitted_definition(s
);
2013 generate_type_header_forwards(const Symbol
*s
)
2015 declare_type(s
, s
->type
, TRUE
);
2016 fprintf(headerfile
, "\n");
2018 generate_template_type_forward(s
->gen_name
);
2022 generate_type (const Symbol
*s
)
2028 generate_header_of_codefile(s
->gen_name
);
2030 generate_type_header(s
);
2033 generate_template(s
);
2035 if (template_flag
== 0 || is_template_compat(s
) == 0) {
2036 generate_type_encode (s
);
2037 generate_type_decode (s
);
2038 generate_type_free (s
);
2039 generate_type_length (s
);
2040 generate_type_copy (s
);
2041 generate_type_print_stub(s
);
2043 generate_type_seq (s
);
2044 generate_glue (s
->type
, s
->gen_name
);
2046 /* generate prototypes */
2048 if (is_export(s
->name
)) {
2058 "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n",
2060 s
->gen_name
, s
->gen_name
);
2063 "encode_%s(unsigned char *, size_t, const %s *, size_t *);\n",
2065 s
->gen_name
, s
->gen_name
);
2067 "%ssize_t ASN1CALL length_%s(const %s *);\n",
2069 s
->gen_name
, s
->gen_name
);
2071 "%sint ASN1CALL copy_%s (const %s *, %s *);\n",
2073 s
->gen_name
, s
->gen_name
, s
->gen_name
);
2075 "%svoid ASN1CALL free_%s (%s *);\n",
2077 s
->gen_name
, s
->gen_name
);
2080 "%schar * ASN1CALL print_%s (const %s *, int);\n",
2082 s
->gen_name
, s
->gen_name
);
2086 if (!one_code_file
) {
2087 fprintf(codefile
, "\n\n");