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
40 FILE *privheaderfile
, *headerfile
, *codefile
, *logfile
, *templatefile
;
44 static const char *orig_filename
;
45 static char *privheader
, *header
, *template;
46 static const char *headerbase
= STEM
;
57 static struct import
*imports
= NULL
;
60 add_import (const char *module
)
62 struct import
*tmp
= emalloc (sizeof(*tmp
));
68 fprintf (headerfile
, "#include <%s_asn1.h>\n", module
);
72 * List of all exported symbols
81 static struct sexport
*exports
= NULL
;
84 add_export (const char *name
)
86 struct sexport
*tmp
= emalloc (sizeof(*tmp
));
94 is_export(const char *name
)
98 if (exports
== NULL
) /* no export list, all exported */
101 for (tmp
= exports
; tmp
!= NULL
; tmp
= tmp
->next
) {
102 if (strcmp(tmp
->name
, name
) == 0) {
113 return orig_filename
;
117 init_generate (const char *filename
, const char *base
)
121 orig_filename
= filename
;
123 headerbase
= strdup(base
);
124 if (headerbase
== NULL
)
128 /* public header file */
129 asprintf(&header
, "%s.h", headerbase
);
132 asprintf(&fn
, "%s.hx", headerbase
);
135 headerfile
= fopen (fn
, "w");
136 if (headerfile
== NULL
)
137 err (1, "open %s", fn
);
140 /* private header file */
141 asprintf(&privheader
, "%s-priv.h", headerbase
);
142 if (privheader
== NULL
)
144 asprintf(&fn
, "%s-priv.hx", headerbase
);
147 privheaderfile
= fopen (fn
, "w");
148 if (privheaderfile
== NULL
)
149 err (1, "open %s", fn
);
153 asprintf(&template, "%s-template.c", headerbase
);
154 if (template == NULL
)
158 "/* Generated from %s */\n"
159 "/* Do not edit */\n\n",
163 "#define __%s_h__\n\n", headerbase
, headerbase
);
165 "#include <stddef.h>\n"
166 "#include <time.h>\n\n");
168 "#ifndef __asn1_common_definitions__\n"
169 "#define __asn1_common_definitions__\n\n");
171 "typedef struct heim_integer {\n"
175 "} heim_integer;\n\n");
177 "typedef struct heim_octet_string {\n"
180 "} heim_octet_string;\n\n");
182 "typedef char *heim_general_string;\n\n"
185 "typedef char *heim_utf8_string;\n\n"
188 "typedef char *heim_printable_string;\n\n"
191 "typedef char *heim_ia5_string;\n\n"
194 "typedef struct heim_bmp_string {\n"
197 "} heim_bmp_string;\n\n");
199 "typedef struct heim_universal_string {\n"
202 "} heim_universal_string;\n\n");
204 "typedef char *heim_visible_string;\n\n"
207 "typedef struct heim_oid {\n"
209 " unsigned *components;\n"
212 "typedef struct heim_bit_string {\n"
215 "} heim_bit_string;\n\n");
217 "typedef struct heim_octet_string heim_any;\n"
218 "typedef struct heim_octet_string heim_any_set;\n\n");
219 fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R) \\\n"
221 " (BL) = length_##T((S)); \\\n"
222 " (B) = malloc((BL)); \\\n"
223 " if((B) == NULL) { \\\n"
224 " (R) = ENOMEM; \\\n"
226 " (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \\\n"
228 " if((R) != 0) { \\\n"
235 fprintf (headerfile
, "struct units;\n\n");
236 fprintf (headerfile
, "#endif\n\n");
237 asprintf(&fn
, "%s_files", base
);
240 logfile
= fopen(fn
, "w");
242 err (1, "open %s", fn
);
244 /* if one code file, write into the one codefile */
248 templatefile
= fopen (template, "w");
249 if (templatefile
== NULL
)
250 err (1, "open %s", template);
252 fprintf (templatefile
,
253 "/* Generated from %s */\n"
254 "/* Do not edit */\n\n"
255 "#include <stdio.h>\n"
256 "#include <stdlib.h>\n"
257 "#include <time.h>\n"
258 "#include <string.h>\n"
259 "#include <errno.h>\n"
260 "#include <limits.h>\n"
261 "#include <krb5-types.h>\n",
264 fprintf (templatefile
,
268 "#include <der-private.h>\n"
269 "#include <asn1-template.h>\n",
276 close_generate (void)
278 fprintf (headerfile
, "#endif /* __%s_h__ */\n", headerbase
);
283 fclose (privheaderfile
);
285 fclose (templatefile
);
287 fprintf (logfile
, "\n");
292 gen_assign_defval(const char *var
, struct value
*val
)
296 fprintf(codefile
, "if((%s = strdup(\"%s\")) == NULL)\nreturn ENOMEM;\n", var
, val
->u
.stringvalue
);
299 fprintf(codefile
, "%s = %d;\n", var
, val
->u
.integervalue
);
302 if(val
->u
.booleanvalue
)
303 fprintf(codefile
, "%s = TRUE;\n", var
);
305 fprintf(codefile
, "%s = FALSE;\n", var
);
313 gen_compare_defval(const char *var
, struct value
*val
)
317 fprintf(codefile
, "if(strcmp(%s, \"%s\") != 0)\n", var
, val
->u
.stringvalue
);
320 fprintf(codefile
, "if(%s != %d)\n", var
, val
->u
.integervalue
);
323 if(val
->u
.booleanvalue
)
324 fprintf(codefile
, "if(!%s)\n", var
);
326 fprintf(codefile
, "if(%s)\n", var
);
334 generate_header_of_codefile(const char *name
)
338 if (codefile
!= NULL
)
341 asprintf (&filename
, "%s_%s.x", STEM
, name
);
342 if (filename
== NULL
)
344 codefile
= fopen (filename
, "w");
345 if (codefile
== NULL
)
346 err (1, "fopen %s", filename
);
347 fprintf(logfile
, "%s ", filename
);
350 "/* Generated from %s */\n"
351 "/* Do not edit */\n\n"
352 "#include <stdio.h>\n"
353 "#include <stdlib.h>\n"
354 "#include <time.h>\n"
355 "#include <string.h>\n"
356 "#include <errno.h>\n"
357 "#include <limits.h>\n"
358 "#include <krb5-types.h>\n",
366 "#include <asn1_err.h>\n"
368 "#include <der-private.h>\n"
369 "#include <asn1-template.h>\n"
370 "#include <parse_units.h>\n\n");
377 if (codefile
== NULL
)
386 generate_constant (const Symbol
*s
)
388 switch(s
->value
->type
) {
392 fprintf (headerfile
, "enum { %s = %d };\n\n",
393 s
->gen_name
, s
->value
->u
.integervalue
);
399 case objectidentifiervalue
: {
400 struct objid
*o
, **list
;
404 generate_header_of_codefile(s
->gen_name
);
407 for (o
= s
->value
->u
.objectidentifiervalue
; o
!= NULL
; o
= o
->next
)
410 printf("s->gen_name: %s",s
->gen_name
);
414 list
= emalloc(sizeof(*list
) * len
);
417 for (o
= s
->value
->u
.objectidentifiervalue
; o
!= NULL
; o
= o
->next
)
420 fprintf (headerfile
, "/* OBJECT IDENTIFIER %s ::= { ", s
->name
);
421 for (i
= len
; i
> 0; i
--) {
423 fprintf(headerfile
, "%s(%d) ",
424 o
->label
? o
->label
: "label-less", o
->value
);
427 fprintf (headerfile
, "} */\n");
429 "extern const heim_oid asn1_oid_%s;\n\n",
433 fprintf (codefile
, "static unsigned oid_%s_variable_num[%d] = {",
435 for (i
= len
; i
> 0; i
--) {
436 fprintf(codefile
, "%d%s ", list
[i
- 1]->value
, i
> 1 ? "," : "");
438 fprintf(codefile
, "};\n");
440 fprintf (codefile
, "const heim_oid asn1_oid_%s = "
441 "{ %d, oid_%s_variable_num };\n\n",
442 s
->gen_name
, len
, s
->gen_name
);
457 is_primitive_type(int type
)
465 case TGeneralizedTime
:
471 case TPrintableString
:
474 case TUniversalString
:
487 fprintf(headerfile
, " ");
491 last_member_p(struct member
*m
)
493 struct member
*n
= ASN1_TAILQ_NEXT(m
, members
);
496 if (n
->ellipsis
&& ASN1_TAILQ_NEXT(n
, members
) == NULL
)
501 static struct member
*
502 have_ellipsis(Type
*t
)
505 ASN1_TAILQ_FOREACH(m
, t
->members
, members
) {
513 define_asn1 (int level
, Type
*t
)
517 fprintf (headerfile
, "%s", t
->symbol
->name
);
520 if(t
->members
== NULL
) {
521 fprintf (headerfile
, "INTEGER");
523 fprintf (headerfile
, " (%d..%d)",
524 t
->range
->min
, t
->range
->max
);
527 fprintf (headerfile
, "INTEGER {\n");
528 ASN1_TAILQ_FOREACH(m
, t
->members
, members
) {
530 fprintf(headerfile
, "%s(%d)%s\n", m
->gen_name
, m
->val
,
534 fprintf (headerfile
, "}");
538 fprintf (headerfile
, "BOOLEAN");
541 fprintf (headerfile
, "OCTET STRING");
548 if(t
->type
== TBitString
)
549 fprintf (headerfile
, "BIT STRING {\n");
551 fprintf (headerfile
, "ENUMERATED {\n");
552 ASN1_TAILQ_FOREACH(m
, t
->members
, members
) {
554 fprintf (headerfile
, "%s(%d)%s\n", m
->name
, m
->val
,
558 fprintf (headerfile
, "}");
567 if(t
->type
== TChoice
)
568 fprintf(headerfile
, "CHOICE {\n");
569 else if(t
->type
== TSet
)
570 fprintf(headerfile
, "SET {\n");
572 fprintf(headerfile
, "SEQUENCE {\n");
573 ASN1_TAILQ_FOREACH(m
, t
->members
, members
) {
574 if(strlen(m
->name
) > max_width
)
575 max_width
= strlen(m
->name
);
578 if(max_width
< 16) max_width
= 16;
579 ASN1_TAILQ_FOREACH(m
, t
->members
, members
) {
580 int width
= max_width
;
583 fprintf (headerfile
, "...");
585 width
-= fprintf(headerfile
, "%s", m
->name
);
586 fprintf(headerfile
, "%*s", width
, "");
587 define_asn1(level
+ 1, m
->type
);
589 fprintf(headerfile
, " OPTIONAL");
592 fprintf (headerfile
, ",");
593 fprintf (headerfile
, "\n");
596 fprintf (headerfile
, "}");
600 fprintf (headerfile
, "SEQUENCE OF ");
601 define_asn1 (0, t
->subtype
);
604 fprintf (headerfile
, "SET OF ");
605 define_asn1 (0, t
->subtype
);
607 case TGeneralizedTime
:
608 fprintf (headerfile
, "GeneralizedTime");
611 fprintf (headerfile
, "GeneralString");
614 fprintf (headerfile
, "TeletexString");
617 const char *classnames
[] = { "UNIVERSAL ", "APPLICATION ",
618 "" /* CONTEXT */, "PRIVATE " };
619 if(t
->tag
.tagclass
!= ASN1_C_UNIV
)
620 fprintf (headerfile
, "[%s%d] ",
621 classnames
[t
->tag
.tagclass
],
623 if(t
->tag
.tagenv
== TE_IMPLICIT
)
624 fprintf (headerfile
, "IMPLICIT ");
625 define_asn1 (level
, t
->subtype
);
629 fprintf (headerfile
, "UTCTime");
633 fprintf (headerfile
, "UTF8String");
635 case TPrintableString
:
637 fprintf (headerfile
, "PrintableString");
641 fprintf (headerfile
, "IA5String");
645 fprintf (headerfile
, "BMPString");
647 case TUniversalString
:
649 fprintf (headerfile
, "UniversalString");
653 fprintf (headerfile
, "VisibleString");
657 fprintf(headerfile
, "OBJECT IDENTIFIER");
661 fprintf (headerfile
, "NULL");
669 getnewbasename(char **newbasename
, int typedefp
, const char *basename
, const char *name
)
672 *newbasename
= strdup(name
);
676 asprintf(newbasename
, "%s_%s", basename
, name
);
678 if (*newbasename
== NULL
)
683 define_type (int level
, const char *name
, const char *basename
, Type
*t
, int typedefp
, int preservep
)
685 char *newbasename
= NULL
;
690 fprintf (headerfile
, "%s %s;\n", t
->symbol
->gen_name
, name
);
696 fprintf (headerfile
, "enum %s {\n", typedefp
? name
: "");
697 ASN1_TAILQ_FOREACH(m
, t
->members
, members
) {
699 fprintf(headerfile
, "%s = %d%s\n", m
->gen_name
, m
->val
,
702 fprintf (headerfile
, "} %s;\n", name
);
703 } else if (t
->range
== NULL
) {
704 fprintf (headerfile
, "heim_integer %s;\n", name
);
705 } else if (t
->range
->min
== INT_MIN
&& t
->range
->max
== INT_MAX
) {
706 fprintf (headerfile
, "int %s;\n", name
);
707 } else if (t
->range
->min
== 0 && t
->range
->max
== UINT_MAX
) {
708 fprintf (headerfile
, "unsigned int %s;\n", name
);
709 } else if (t
->range
->min
== 0 && t
->range
->max
== INT_MAX
) {
710 fprintf (headerfile
, "unsigned int %s;\n", name
);
712 errx(1, "%s: unsupported range %d -> %d",
713 name
, t
->range
->min
, t
->range
->max
);
717 fprintf (headerfile
, "int %s;\n", name
);
721 fprintf (headerfile
, "heim_octet_string %s;\n", name
);
726 struct range range
= { 0, INT_MAX
};
734 if(ASN1_TAILQ_EMPTY(t
->members
))
735 fprintf (headerfile
, "heim_bit_string %s;\n", name
);
738 getnewbasename(&newbasename
, typedefp
, basename
, name
);
740 fprintf (headerfile
, "struct %s {\n", newbasename
);
741 ASN1_TAILQ_FOREACH(m
, t
->members
, members
) {
745 while (pos
< m
->val
) {
746 asprintf (&n
, "_unused%d:1", pos
);
747 define_type (level
+ 1, n
, newbasename
, &i
, FALSE
, FALSE
);
752 asprintf (&n
, "%s:1", m
->gen_name
);
755 define_type (level
+ 1, n
, newbasename
, &i
, FALSE
, FALSE
);
759 /* pad to 32 elements */
762 asprintf (&n
, "_unused%d:1", pos
);
763 define_type (level
+ 1, n
, newbasename
, &i
, FALSE
, FALSE
);
769 fprintf (headerfile
, "} %s;\n\n", name
);
777 fprintf (headerfile
, "enum %s {\n", typedefp
? name
: "");
778 ASN1_TAILQ_FOREACH(m
, t
->members
, members
) {
781 fprintf (headerfile
, "/* ... */\n");
783 fprintf (headerfile
, "%s = %d%s\n", m
->gen_name
, m
->val
,
787 fprintf (headerfile
, "} %s;\n\n", name
);
794 getnewbasename(&newbasename
, typedefp
, basename
, name
);
797 fprintf (headerfile
, "struct %s {\n", newbasename
);
798 if (t
->type
== TSequence
&& preservep
) {
800 fprintf(headerfile
, "heim_octet_string _save;\n");
802 ASN1_TAILQ_FOREACH(m
, t
->members
, members
) {
805 } else if (m
->optional
) {
808 asprintf (&n
, "*%s", m
->gen_name
);
811 define_type (level
+ 1, n
, newbasename
, m
->type
, FALSE
, FALSE
);
814 define_type (level
+ 1, m
->gen_name
, newbasename
, m
->type
, FALSE
, FALSE
);
817 fprintf (headerfile
, "} %s;\n", name
);
823 struct range range
= { 0, INT_MAX
};
825 getnewbasename(&newbasename
, typedefp
, basename
, name
);
833 fprintf (headerfile
, "struct %s {\n", newbasename
);
834 define_type (level
+ 1, "len", newbasename
, &i
, FALSE
, FALSE
);
835 define_type (level
+ 1, "*val", newbasename
, t
->subtype
, FALSE
, FALSE
);
837 fprintf (headerfile
, "} %s;\n", name
);
840 case TGeneralizedTime
:
842 fprintf (headerfile
, "time_t %s;\n", name
);
846 fprintf (headerfile
, "heim_general_string %s;\n", name
);
850 fprintf (headerfile
, "heim_general_string %s;\n", name
);
853 define_type (level
, name
, basename
, t
->subtype
, typedefp
, preservep
);
859 getnewbasename(&newbasename
, typedefp
, basename
, name
);
862 fprintf (headerfile
, "struct %s {\n", newbasename
);
865 fprintf(headerfile
, "heim_octet_string _save;\n");
868 fprintf (headerfile
, "enum {\n");
869 m
= have_ellipsis(t
);
872 fprintf (headerfile
, "%s = 0,\n", m
->label
);
875 ASN1_TAILQ_FOREACH(m
, t
->members
, members
) {
878 fprintf (headerfile
, "/* ... */\n");
880 fprintf (headerfile
, "%s%s%s\n", m
->label
,
886 fprintf (headerfile
, "} element;\n");
888 fprintf (headerfile
, "union {\n");
889 ASN1_TAILQ_FOREACH(m
, t
->members
, members
) {
892 fprintf(headerfile
, "heim_octet_string asn1_ellipsis;\n");
893 } else if (m
->optional
) {
896 asprintf (&n
, "*%s", m
->gen_name
);
899 define_type (level
+ 2, n
, newbasename
, m
->type
, FALSE
, FALSE
);
902 define_type (level
+ 2, m
->gen_name
, newbasename
, m
->type
, FALSE
, FALSE
);
905 fprintf (headerfile
, "} u;\n");
907 fprintf (headerfile
, "} %s;\n", name
);
912 fprintf (headerfile
, "time_t %s;\n", name
);
916 fprintf (headerfile
, "heim_utf8_string %s;\n", name
);
918 case TPrintableString
:
920 fprintf (headerfile
, "heim_printable_string %s;\n", name
);
924 fprintf (headerfile
, "heim_ia5_string %s;\n", name
);
928 fprintf (headerfile
, "heim_bmp_string %s;\n", name
);
930 case TUniversalString
:
932 fprintf (headerfile
, "heim_universal_string %s;\n", name
);
936 fprintf (headerfile
, "heim_visible_string %s;\n", name
);
940 fprintf (headerfile
, "heim_oid %s;\n", name
);
944 fprintf (headerfile
, "int %s;\n", name
);
954 generate_type_header (const Symbol
*s
)
956 int preservep
= preserve_type(s
->name
) ? TRUE
: FALSE
;
958 fprintf (headerfile
, "/*\n");
959 fprintf (headerfile
, "%s ::= ", s
->name
);
960 define_asn1 (0, s
->type
);
961 fprintf (headerfile
, "\n*/\n\n");
963 fprintf (headerfile
, "typedef ");
964 define_type (0, s
->gen_name
, s
->gen_name
, s
->type
, TRUE
, preservep
);
966 fprintf (headerfile
, "\n");
970 generate_type (const Symbol
*s
)
975 generate_header_of_codefile(s
->gen_name
);
977 generate_type_header (s
);
980 generate_template(s
);
982 if (template_flag
== 0 || is_template_compat(s
) == 0) {
983 generate_type_encode (s
);
984 generate_type_decode (s
);
985 generate_type_free (s
);
986 generate_type_length (s
);
987 generate_type_copy (s
);
989 generate_type_seq (s
);
990 generate_glue (s
->type
, s
->gen_name
);
992 /* generate prototypes */
994 if (is_export(s
->name
))
1001 "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n",
1002 s
->gen_name
, s
->gen_name
);
1005 "encode_%s(unsigned char *, size_t, const %s *, size_t *);\n",
1006 s
->gen_name
, s
->gen_name
);
1008 "size_t length_%s(const %s *);\n",
1009 s
->gen_name
, s
->gen_name
);
1011 "int copy_%s (const %s *, %s *);\n",
1012 s
->gen_name
, s
->gen_name
, s
->gen_name
);
1014 "void free_%s (%s *);\n",
1015 s
->gen_name
, s
->gen_name
);
1020 if (!one_code_file
) {
1021 fprintf(codefile
, "\n\n");