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