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