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