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