xref: /freebsd/crypto/heimdal/lib/asn1/gen.c (revision 23f282aa31e9b6fceacd449020e936e98d6f2298)
1 /*
2  * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska H�gskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the Institute nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include "gen_locl.h"
35 
36 RCSID("$Id: gen.c,v 1.41 1999/12/02 17:05:02 joda Exp $");
37 
38 FILE *headerfile, *codefile, *logfile;
39 
40 #define STEM "asn1"
41 
42 static char *orig_filename;
43 static char header[1024];
44 static char headerbase[1024] = STEM;
45 
46 void
47 init_generate (char *filename, char *base)
48 {
49     orig_filename = filename;
50     if(base)
51 	strcpy(headerbase, base);
52     sprintf(header, "%s.h", headerbase);
53     headerfile = fopen (header, "w");
54     if (headerfile == NULL)
55 	err (1, "open %s", header);
56     fprintf (headerfile,
57 	     "/* Generated from %s */\n"
58 	     "/* Do not edit */\n\n",
59 	     filename);
60     fprintf (headerfile,
61 	     "#ifndef __%s_h__\n"
62 	     "#define __%s_h__\n\n", headerbase, headerbase);
63     fprintf (headerfile,
64 	     "#include <stddef.h>\n"
65 	     "#include <time.h>\n\n");
66 #ifndef HAVE_TIMEGM
67     fprintf (headerfile, "time_t timegm (struct tm*);\n\n");
68 #endif
69     fprintf (headerfile,
70 	     "#ifndef __asn1_common_definitions__\n"
71 	     "#define __asn1_common_definitions__\n\n");
72     fprintf (headerfile,
73 	     "typedef struct octet_string {\n"
74 	     "  size_t length;\n"
75 	     "  void *data;\n"
76 	     "} octet_string;\n\n");
77     fprintf (headerfile,
78 #if 0
79 	     "typedef struct general_string {\n"
80 	     "  size_t length;\n"
81 	     "  char *data;\n"
82 	     "} general_string;\n\n"
83 #else
84 	     "typedef char *general_string;\n\n"
85 #endif
86 	     );
87     fprintf (headerfile, "#endif\n\n");
88     logfile = fopen(STEM "_files", "w");
89     if (logfile == NULL)
90 	err (1, "open " STEM "_files");
91 }
92 
93 void
94 close_generate ()
95 {
96     fprintf (headerfile, "#endif /* __%s_h__ */\n", headerbase);
97 
98     fclose (headerfile);
99     fprintf (logfile, "\n");
100     fclose (logfile);
101 }
102 
103 void
104 generate_constant (const Symbol *s)
105 {
106   fprintf (headerfile, "enum { %s = %d };\n\n",
107 	   s->gen_name, s->constant);
108 }
109 
110 static void
111 space(int level)
112 {
113     while(level-- > 0)
114 	fprintf(headerfile, "  ");
115 }
116 
117 static void
118 define_asn1 (int level, Type *t)
119 {
120     switch (t->type) {
121     case TType:
122 	space(level);
123 	fprintf (headerfile, "%s", t->symbol->name);
124 	break;
125     case TInteger:
126 	space(level);
127 	fprintf (headerfile, "INTEGER");
128 	break;
129     case TOctetString:
130 	space(level);
131 	fprintf (headerfile, "OCTET STRING");
132 	break;
133     case TBitString: {
134 	Member *m;
135 	Type i;
136 	int tag = -1;
137 
138 	i.type = TInteger;
139 	space(level);
140 	fprintf (headerfile, "BIT STRING {\n");
141 	for (m = t->members; m && m->val != tag; m = m->next) {
142 	    if (tag == -1)
143 		tag = m->val;
144 	    space(level + 1);
145 	    fprintf (headerfile, "%s(%d)%s\n", m->name, m->val,
146 		     m->next->val == tag?"":",");
147 
148 	}
149 	space(level);
150 	fprintf (headerfile, "}");
151 	break;
152     }
153     case TSequence: {
154 	Member *m;
155 	int tag;
156 	int max_width = 0;
157 
158 	space(level);
159 	fprintf (headerfile, "SEQUENCE {\n");
160 	for (m = t->members, tag = -1; m && m->val != tag; m = m->next) {
161 	    if (tag == -1)
162 		tag = m->val;
163 	    if(strlen(m->name) + (m->val > 9) > max_width)
164 		max_width = strlen(m->name) + (m->val > 9);
165 	}
166 	max_width += 3 + 2;
167 	if(max_width < 16) max_width = 16;
168 	for (m = t->members, tag = -1 ; m && m->val != tag; m = m->next) {
169 	    int width;
170 	    if (tag == -1)
171 		tag = m->val;
172 	    space(level + 1);
173 	    fprintf(headerfile, "%s[%d]", m->name, m->val);
174 	    width = max_width - strlen(m->name) - 3 - (m->val > 9) - 2;
175 	    fprintf(headerfile, "%*s", width, "");
176 	    define_asn1(level + 1, m->type);
177 	    if(m->optional)
178 		fprintf(headerfile, " OPTIONAL");
179 	    if(m->next->val != tag)
180 		fprintf (headerfile, ",");
181 	    fprintf (headerfile, "\n");
182 	}
183 	space(level);
184 	fprintf (headerfile, "}");
185 	break;
186     }
187     case TSequenceOf: {
188 	space(level);
189 	fprintf (headerfile, "SEQUENCE OF ");
190 	define_asn1 (0, t->subtype);
191 	break;
192     }
193     case TGeneralizedTime:
194 	space(level);
195 	fprintf (headerfile, "GeneralizedTime");
196 	break;
197     case TGeneralString:
198 	space(level);
199 	fprintf (headerfile, "GeneralString");
200 	break;
201     case TApplication:
202 	fprintf (headerfile, "[APPLICATION %d] ", t->application);
203 	define_asn1 (level, t->subtype);
204 	break;
205     default:
206 	abort ();
207     }
208 }
209 
210 static void
211 define_type (int level, char *name, Type *t, int typedefp)
212 {
213     switch (t->type) {
214     case TType:
215 	space(level);
216 	fprintf (headerfile, "%s %s;\n", t->symbol->gen_name, name);
217 	break;
218     case TInteger:
219 	space(level);
220 	fprintf (headerfile, "int %s;\n", name);
221 	break;
222     case TUInteger:
223 	space(level);
224 	fprintf (headerfile, "unsigned int %s;\n", name);
225 	break;
226     case TOctetString:
227 	space(level);
228 	fprintf (headerfile, "octet_string %s;\n", name);
229 	break;
230     case TBitString: {
231 	Member *m;
232 	Type i;
233 	int tag = -1;
234 
235 	i.type = TUInteger;
236 	space(level);
237 	fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
238 	for (m = t->members; m && m->val != tag; m = m->next) {
239 	    char *n;
240 
241 	    asprintf (&n, "%s:1", m->gen_name);
242 	    define_type (level + 1, n, &i, FALSE);
243 	    free (n);
244 	    if (tag == -1)
245 		tag = m->val;
246 	}
247 	space(level);
248 	fprintf (headerfile, "} %s;\n\n", name);
249 	break;
250     }
251     case TSequence: {
252 	Member *m;
253 	int tag = -1;
254 
255 	space(level);
256 	fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
257 	for (m = t->members; m && m->val != tag; m = m->next) {
258 	    if (m->optional) {
259 		char *n;
260 
261 		asprintf (&n, "*%s", m->gen_name);
262 		define_type (level + 1, n, m->type, FALSE);
263 		free (n);
264 	    } else
265 		define_type (level + 1, m->gen_name, m->type, FALSE);
266 	    if (tag == -1)
267 		tag = m->val;
268 	}
269 	space(level);
270 	fprintf (headerfile, "} %s;\n", name);
271 	break;
272     }
273     case TSequenceOf: {
274 	Type i;
275 
276 	i.type = TUInteger;
277 	i.application = 0;
278 
279 	space(level);
280 	fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
281 	define_type (level + 1, "len", &i, FALSE);
282 	define_type (level + 1, "*val", t->subtype, FALSE);
283 	space(level);
284 	fprintf (headerfile, "} %s;\n", name);
285 	break;
286     }
287     case TGeneralizedTime:
288 	space(level);
289 	fprintf (headerfile, "time_t %s;\n", name);
290 	break;
291     case TGeneralString:
292 	space(level);
293 	fprintf (headerfile, "general_string %s;\n", name);
294 	break;
295     case TApplication:
296 	define_type (level, name, t->subtype, FALSE);
297 	break;
298     default:
299 	abort ();
300     }
301 }
302 
303 static void
304 generate_type_header (const Symbol *s)
305 {
306     fprintf (headerfile, "/*\n");
307     fprintf (headerfile, "%s ::= ", s->name);
308     define_asn1 (0, s->type);
309     fprintf (headerfile, "\n*/\n\n");
310 
311     fprintf (headerfile, "typedef ");
312     define_type (0, s->gen_name, s->type, TRUE);
313 
314     fprintf (headerfile, "\n");
315 }
316 
317 
318 void
319 generate_type (const Symbol *s)
320 {
321     char *filename;
322 
323     asprintf (&filename, "%s_%s.x", STEM, s->gen_name);
324     codefile = fopen (filename, "w");
325     if (codefile == NULL)
326 	err (1, "fopen %s", filename);
327     fprintf(logfile, "%s ", filename);
328     free(filename);
329     fprintf (codefile,
330 	     "/* Generated from %s */\n"
331 	     "/* Do not edit */\n\n"
332 	     "#include \"libasn1.h\"\n\n"
333 #if 0
334 	     "#include <stdio.h>\n"
335 	     "#include <stdlib.h>\n"
336 	     "#include <time.h>\n"
337 	     "#include <" STEM ".h>\n\n"
338 	     "#include <asn1_err.h>\n"
339 	     "#include <der.h>\n"
340 #endif
341 	     ,orig_filename);
342     generate_type_header (s);
343     generate_type_encode (s);
344     generate_type_decode (s);
345     generate_type_free (s);
346     generate_type_length (s);
347     generate_type_copy (s);
348     generate_glue (s);
349     fprintf(headerfile, "\n\n");
350     fclose(codefile);
351 }
352