xref: /freebsd/crypto/heimdal/lib/asn1/gen.c (revision b52b9d56d4e96089873a75f9e29062eec19fabba)
1 /*
2  * Copyright (c) 1997 - 2001 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.47 2001/09/27 16:21:47 assar Exp $");
37 
38 FILE *headerfile, *codefile, *logfile;
39 
40 #define STEM "asn1"
41 
42 static const char *orig_filename;
43 static char header[1024];
44 static char headerbase[1024] = STEM;
45 
46 /*
47  * list of all IMPORTs
48  */
49 
50 struct import {
51     const char *module;
52     struct import *next;
53 };
54 
55 static struct import *imports = NULL;
56 
57 void
58 add_import (const char *module)
59 {
60     struct import *tmp = emalloc (sizeof(*tmp));
61 
62     tmp->module = module;
63     tmp->next   = imports;
64     imports     = tmp;
65 }
66 
67 const char *
68 filename (void)
69 {
70     return orig_filename;
71 }
72 
73 void
74 init_generate (const char *filename, const char *base)
75 {
76     orig_filename = filename;
77     if(base)
78 	strcpy(headerbase, base);
79     sprintf(header, "%s.h", headerbase);
80     headerfile = fopen (header, "w");
81     if (headerfile == NULL)
82 	err (1, "open %s", header);
83     fprintf (headerfile,
84 	     "/* Generated from %s */\n"
85 	     "/* Do not edit */\n\n",
86 	     filename);
87     fprintf (headerfile,
88 	     "#ifndef __%s_h__\n"
89 	     "#define __%s_h__\n\n", headerbase, headerbase);
90     fprintf (headerfile,
91 	     "#include <stddef.h>\n"
92 	     "#include <time.h>\n\n");
93 #ifndef HAVE_TIMEGM
94     fprintf (headerfile, "time_t timegm (struct tm*);\n\n");
95 #endif
96     fprintf (headerfile,
97 	     "#ifndef __asn1_common_definitions__\n"
98 	     "#define __asn1_common_definitions__\n\n");
99     fprintf (headerfile,
100 	     "typedef struct octet_string {\n"
101 	     "  size_t length;\n"
102 	     "  void *data;\n"
103 	     "} octet_string;\n\n");
104     fprintf (headerfile,
105 #if 0
106 	     "typedef struct general_string {\n"
107 	     "  size_t length;\n"
108 	     "  char *data;\n"
109 	     "} general_string;\n\n"
110 #else
111 	     "typedef char *general_string;\n\n"
112 #endif
113 	     );
114     fprintf (headerfile,
115 	     "typedef struct oid {\n"
116 	     "  size_t length;\n"
117 	     "  unsigned *components;\n"
118 	     "} oid;\n\n");
119     fprintf (headerfile, "#endif\n\n");
120     logfile = fopen(STEM "_files", "w");
121     if (logfile == NULL)
122 	err (1, "open " STEM "_files");
123 }
124 
125 void
126 close_generate (void)
127 {
128     fprintf (headerfile, "#endif /* __%s_h__ */\n", headerbase);
129 
130     fclose (headerfile);
131     fprintf (logfile, "\n");
132     fclose (logfile);
133 }
134 
135 void
136 generate_constant (const Symbol *s)
137 {
138   fprintf (headerfile, "enum { %s = %d };\n\n",
139 	   s->gen_name, s->constant);
140 }
141 
142 static void
143 space(int level)
144 {
145     while(level-- > 0)
146 	fprintf(headerfile, "  ");
147 }
148 
149 static void
150 define_asn1 (int level, Type *t)
151 {
152     switch (t->type) {
153     case TType:
154 	space(level);
155 	fprintf (headerfile, "%s", t->symbol->name);
156 	break;
157     case TInteger:
158 	space(level);
159 	fprintf (headerfile, "INTEGER");
160 	break;
161     case TUInteger:
162 	space(level);
163 	fprintf (headerfile, "UNSIGNED INTEGER");
164 	break;
165     case TOctetString:
166 	space(level);
167 	fprintf (headerfile, "OCTET STRING");
168 	break;
169     case TOID :
170 	space(level);
171 	fprintf(headerfile, "OBJECT IDENTIFIER");
172 	break;
173     case TBitString: {
174 	Member *m;
175 	int tag = -1;
176 
177 	space(level);
178 	fprintf (headerfile, "BIT STRING {\n");
179 	for (m = t->members; m && m->val != tag; m = m->next) {
180 	    if (tag == -1)
181 		tag = m->val;
182 	    space(level + 1);
183 	    fprintf (headerfile, "%s(%d)%s\n", m->name, m->val,
184 		     m->next->val == tag?"":",");
185 
186 	}
187 	space(level);
188 	fprintf (headerfile, "}");
189 	break;
190     }
191     case TEnumerated : {
192 	Member *m;
193 	int tag = -1;
194 
195 	space(level);
196 	fprintf (headerfile, "ENUMERATED {\n");
197 	for (m = t->members; m && m->val != tag; m = m->next) {
198 	    if (tag == -1)
199 		tag = m->val;
200 	    space(level + 1);
201 	    fprintf (headerfile, "%s(%d)%s\n", m->name, m->val,
202 		     m->next->val == tag?"":",");
203 
204 	}
205 	space(level);
206 	fprintf (headerfile, "}");
207 	break;
208     }
209     case TSequence: {
210 	Member *m;
211 	int tag;
212 	int max_width = 0;
213 
214 	space(level);
215 	fprintf (headerfile, "SEQUENCE {\n");
216 	for (m = t->members, tag = -1; m && m->val != tag; m = m->next) {
217 	    if (tag == -1)
218 		tag = m->val;
219 	    if(strlen(m->name) + (m->val > 9) > max_width)
220 		max_width = strlen(m->name) + (m->val > 9);
221 	}
222 	max_width += 3 + 2;
223 	if(max_width < 16) max_width = 16;
224 	for (m = t->members, tag = -1 ; m && m->val != tag; m = m->next) {
225 	    int width;
226 	    if (tag == -1)
227 		tag = m->val;
228 	    space(level + 1);
229 	    fprintf(headerfile, "%s[%d]", m->name, m->val);
230 	    width = max_width - strlen(m->name) - 3 - (m->val > 9) - 2;
231 	    fprintf(headerfile, "%*s", width, "");
232 	    define_asn1(level + 1, m->type);
233 	    if(m->optional)
234 		fprintf(headerfile, " OPTIONAL");
235 	    if(m->next->val != tag)
236 		fprintf (headerfile, ",");
237 	    fprintf (headerfile, "\n");
238 	}
239 	space(level);
240 	fprintf (headerfile, "}");
241 	break;
242     }
243     case TSequenceOf: {
244 	space(level);
245 	fprintf (headerfile, "SEQUENCE OF ");
246 	define_asn1 (0, t->subtype);
247 	break;
248     }
249     case TGeneralizedTime:
250 	space(level);
251 	fprintf (headerfile, "GeneralizedTime");
252 	break;
253     case TGeneralString:
254 	space(level);
255 	fprintf (headerfile, "GeneralString");
256 	break;
257     case TApplication:
258 	fprintf (headerfile, "[APPLICATION %d] ", t->application);
259 	define_asn1 (level, t->subtype);
260 	break;
261     default:
262 	abort ();
263     }
264 }
265 
266 static void
267 define_type (int level, char *name, Type *t, int typedefp)
268 {
269     switch (t->type) {
270     case TType:
271 	space(level);
272 	fprintf (headerfile, "%s %s;\n", t->symbol->gen_name, name);
273 	break;
274     case TInteger:
275 	space(level);
276         if(t->members == NULL) {
277             fprintf (headerfile, "int %s;\n", name);
278         } else {
279             Member *m;
280             int tag = -1;
281             fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
282 	    for (m = t->members; m && m->val != tag; m = m->next) {
283                 if(tag == -1)
284                     tag = m->val;
285                 space (level + 1);
286                 fprintf(headerfile, "%s = %d%s\n", m->gen_name, m->val,
287                         m->next->val == tag ? "" : ",");
288             }
289             fprintf (headerfile, "} %s;\n", name);
290         }
291 	break;
292     case TUInteger:
293 	space(level);
294 	fprintf (headerfile, "unsigned int %s;\n", name);
295 	break;
296     case TOctetString:
297 	space(level);
298 	fprintf (headerfile, "octet_string %s;\n", name);
299 	break;
300     case TOID :
301 	space(level);
302 	fprintf (headerfile, "oid %s;\n", name);
303 	break;
304     case TBitString: {
305 	Member *m;
306 	Type i;
307 	int tag = -1;
308 
309 	i.type = TUInteger;
310 	space(level);
311 	fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
312 	for (m = t->members; m && m->val != tag; m = m->next) {
313 	    char *n;
314 
315 	    asprintf (&n, "%s:1", m->gen_name);
316 	    define_type (level + 1, n, &i, FALSE);
317 	    free (n);
318 	    if (tag == -1)
319 		tag = m->val;
320 	}
321 	space(level);
322 	fprintf (headerfile, "} %s;\n\n", name);
323 	break;
324     }
325     case TEnumerated: {
326 	Member *m;
327 	int tag = -1;
328 
329 	space(level);
330 	fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
331 	for (m = t->members; m && m->val != tag; m = m->next) {
332 	    if (tag == -1)
333 		tag = m->val;
334 	    space(level + 1);
335 	    fprintf (headerfile, "%s = %d%s\n", m->gen_name, m->val,
336                         m->next->val == tag ? "" : ",");
337 	}
338 	space(level);
339 	fprintf (headerfile, "} %s;\n\n", name);
340 	break;
341     }
342     case TSequence: {
343 	Member *m;
344 	int tag = -1;
345 
346 	space(level);
347 	fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
348 	for (m = t->members; m && m->val != tag; m = m->next) {
349 	    if (m->optional) {
350 		char *n;
351 
352 		asprintf (&n, "*%s", m->gen_name);
353 		define_type (level + 1, n, m->type, FALSE);
354 		free (n);
355 	    } else
356 		define_type (level + 1, m->gen_name, m->type, FALSE);
357 	    if (tag == -1)
358 		tag = m->val;
359 	}
360 	space(level);
361 	fprintf (headerfile, "} %s;\n", name);
362 	break;
363     }
364     case TSequenceOf: {
365 	Type i;
366 
367 	i.type = TUInteger;
368 	i.application = 0;
369 
370 	space(level);
371 	fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
372 	define_type (level + 1, "len", &i, FALSE);
373 	define_type (level + 1, "*val", t->subtype, FALSE);
374 	space(level);
375 	fprintf (headerfile, "} %s;\n", name);
376 	break;
377     }
378     case TGeneralizedTime:
379 	space(level);
380 	fprintf (headerfile, "time_t %s;\n", name);
381 	break;
382     case TGeneralString:
383 	space(level);
384 	fprintf (headerfile, "general_string %s;\n", name);
385 	break;
386     case TApplication:
387 	define_type (level, name, t->subtype, FALSE);
388 	break;
389     default:
390 	abort ();
391     }
392 }
393 
394 static void
395 generate_type_header (const Symbol *s)
396 {
397     fprintf (headerfile, "/*\n");
398     fprintf (headerfile, "%s ::= ", s->name);
399     define_asn1 (0, s->type);
400     fprintf (headerfile, "\n*/\n\n");
401 
402     fprintf (headerfile, "typedef ");
403     define_type (0, s->gen_name, s->type, TRUE);
404 
405     fprintf (headerfile, "\n");
406 }
407 
408 
409 void
410 generate_type (const Symbol *s)
411 {
412     struct import *i;
413     char *filename;
414 
415     asprintf (&filename, "%s_%s.x", STEM, s->gen_name);
416     codefile = fopen (filename, "w");
417     if (codefile == NULL)
418 	err (1, "fopen %s", filename);
419     fprintf(logfile, "%s ", filename);
420     free(filename);
421     fprintf (codefile,
422 	     "/* Generated from %s */\n"
423 	     "/* Do not edit */\n\n"
424 	     "#include <stdio.h>\n"
425 	     "#include <stdlib.h>\n"
426 	     "#include <time.h>\n"
427 	     "#include <errno.h>\n",
428 	     orig_filename);
429 
430     for (i = imports; i != NULL; i = i->next)
431 	fprintf (codefile,
432 		 "#include <%s_asn1.h>\n",
433 		 i->module);
434     fprintf (codefile,
435 	     "#include <%s.h>\n",
436 	     headerbase);
437     fprintf (codefile,
438 	     "#include <asn1_err.h>\n"
439 	     "#include <der.h>\n"
440 	     "#include <parse_units.h>\n\n");
441     generate_type_header (s);
442     generate_type_encode (s);
443     generate_type_decode (s);
444     generate_type_free (s);
445     generate_type_length (s);
446     generate_type_copy (s);
447     generate_glue (s);
448     fprintf(headerfile, "\n\n");
449     fclose(codefile);
450 }
451