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