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