155682Smarkm/*
2233294Sstas * Copyright (c) 1997 - 2005 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
555682Smarkm *
6233294Sstas * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
755682Smarkm *
8233294Sstas * Redistribution and use in source and binary forms, with or without
9233294Sstas * modification, are permitted provided that the following conditions
10233294Sstas * are met:
1155682Smarkm *
12233294Sstas * 1. Redistributions of source code must retain the above copyright
13233294Sstas *    notice, this list of conditions and the following disclaimer.
1455682Smarkm *
15233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
16233294Sstas *    notice, this list of conditions and the following disclaimer in the
17233294Sstas *    documentation and/or other materials provided with the distribution.
1855682Smarkm *
19233294Sstas * 3. Neither the name of the Institute nor the names of its contributors
20233294Sstas *    may be used to endorse or promote products derived from this software
21233294Sstas *    without specific prior written permission.
22233294Sstas *
23233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33233294Sstas * SUCH DAMAGE.
3455682Smarkm */
3555682Smarkm
3655682Smarkm#include "gen_locl.h"
3755682Smarkm
38233294SstasRCSID("$Id$");
3955682Smarkm
40233294SstasFILE *privheaderfile, *headerfile, *codefile, *logfile, *templatefile;
4155682Smarkm
4255682Smarkm#define STEM "asn1"
4355682Smarkm
4472445Sassarstatic const char *orig_filename;
45233294Sstasstatic char *privheader, *header, *template;
46178825Sdfrstatic const char *headerbase = STEM;
4755682Smarkm
4890926Snectar/*
4990926Snectar * list of all IMPORTs
5090926Snectar */
5190926Snectar
5290926Snectarstruct import {
5390926Snectar    const char *module;
5490926Snectar    struct import *next;
5590926Snectar};
5690926Snectar
5790926Snectarstatic struct import *imports = NULL;
5890926Snectar
5990926Snectarvoid
6090926Snectaradd_import (const char *module)
6190926Snectar{
6290926Snectar    struct import *tmp = emalloc (sizeof(*tmp));
6390926Snectar
6490926Snectar    tmp->module = module;
6590926Snectar    tmp->next   = imports;
6690926Snectar    imports     = tmp;
67178825Sdfr
68178825Sdfr    fprintf (headerfile, "#include <%s_asn1.h>\n", module);
6990926Snectar}
7090926Snectar
71233294Sstas/*
72233294Sstas * List of all exported symbols
73233294Sstas */
74233294Sstas
75233294Sstasstruct sexport {
76233294Sstas    const char *name;
77233294Sstas    int defined;
78233294Sstas    struct sexport *next;
79233294Sstas};
80233294Sstas
81233294Sstasstatic struct sexport *exports = NULL;
82233294Sstas
83233294Sstasvoid
84233294Sstasadd_export (const char *name)
85233294Sstas{
86233294Sstas    struct sexport *tmp = emalloc (sizeof(*tmp));
87233294Sstas
88233294Sstas    tmp->name   = name;
89233294Sstas    tmp->next   = exports;
90233294Sstas    exports     = tmp;
91233294Sstas}
92233294Sstas
93233294Sstasint
94233294Sstasis_export(const char *name)
95233294Sstas{
96233294Sstas    struct sexport *tmp;
97233294Sstas
98233294Sstas    if (exports == NULL) /* no export list, all exported */
99233294Sstas	return 1;
100233294Sstas
101233294Sstas    for (tmp = exports; tmp != NULL; tmp = tmp->next) {
102233294Sstas	if (strcmp(tmp->name, name) == 0) {
103233294Sstas	    tmp->defined = 1;
104233294Sstas	    return 1;
105233294Sstas	}
106233294Sstas    }
107233294Sstas    return 0;
108233294Sstas}
109233294Sstas
11072445Sassarconst char *
111178825Sdfrget_filename (void)
11272445Sassar{
11372445Sassar    return orig_filename;
11472445Sassar}
11572445Sassar
11655682Smarkmvoid
11772445Sassarinit_generate (const char *filename, const char *base)
11855682Smarkm{
119233294Sstas    char *fn = NULL;
120178825Sdfr
12155682Smarkm    orig_filename = filename;
122178825Sdfr    if (base != NULL) {
123178825Sdfr	headerbase = strdup(base);
124178825Sdfr	if (headerbase == NULL)
125178825Sdfr	    errx(1, "strdup");
126178825Sdfr    }
127233294Sstas
128233294Sstas    /* public header file */
129233294Sstas    if (asprintf(&header, "%s.h", headerbase) < 0 || header == NULL)
130178825Sdfr	errx(1, "malloc");
131233294Sstas    if (asprintf(&fn, "%s.hx", headerbase) < 0 || fn == NULL)
132233294Sstas	errx(1, "malloc");
133233294Sstas    headerfile = fopen (fn, "w");
13455682Smarkm    if (headerfile == NULL)
135233294Sstas	err (1, "open %s", fn);
136233294Sstas    free(fn);
137233294Sstas    fn = NULL;
138233294Sstas
139233294Sstas    /* private header file */
140233294Sstas    if (asprintf(&privheader, "%s-priv.h", headerbase) < 0 || privheader == NULL)
141233294Sstas	errx(1, "malloc");
142233294Sstas    if (asprintf(&fn, "%s-priv.hx", headerbase) < 0 || fn == NULL)
143233294Sstas	errx(1, "malloc");
144233294Sstas    privheaderfile = fopen (fn, "w");
145233294Sstas    if (privheaderfile == NULL)
146233294Sstas	err (1, "open %s", fn);
147233294Sstas    free(fn);
148233294Sstas    fn = NULL;
149233294Sstas
150233294Sstas    /* template file */
151233294Sstas    if (asprintf(&template, "%s-template.c", headerbase) < 0 || template == NULL)
152233294Sstas	errx(1, "malloc");
15355682Smarkm    fprintf (headerfile,
15455682Smarkm	     "/* Generated from %s */\n"
15555682Smarkm	     "/* Do not edit */\n\n",
15655682Smarkm	     filename);
157233294Sstas    fprintf (headerfile,
15855682Smarkm	     "#ifndef __%s_h__\n"
15955682Smarkm	     "#define __%s_h__\n\n", headerbase, headerbase);
160233294Sstas    fprintf (headerfile,
16155682Smarkm	     "#include <stddef.h>\n"
16255682Smarkm	     "#include <time.h>\n\n");
16355682Smarkm    fprintf (headerfile,
16455682Smarkm	     "#ifndef __asn1_common_definitions__\n"
16555682Smarkm	     "#define __asn1_common_definitions__\n\n");
16655682Smarkm    fprintf (headerfile,
167178825Sdfr	     "typedef struct heim_integer {\n"
16855682Smarkm	     "  size_t length;\n"
16955682Smarkm	     "  void *data;\n"
170178825Sdfr	     "  int negative;\n"
171178825Sdfr	     "} heim_integer;\n\n");
17255682Smarkm    fprintf (headerfile,
173178825Sdfr	     "typedef struct heim_octet_string {\n"
174178825Sdfr	     "  size_t length;\n"
175178825Sdfr	     "  void *data;\n"
176178825Sdfr	     "} heim_octet_string;\n\n");
177178825Sdfr    fprintf (headerfile,
178178825Sdfr	     "typedef char *heim_general_string;\n\n"
17955682Smarkm	     );
18090926Snectar    fprintf (headerfile,
181178825Sdfr	     "typedef char *heim_utf8_string;\n\n"
182178825Sdfr	     );
183178825Sdfr    fprintf (headerfile,
184233294Sstas	     "typedef struct heim_octet_string heim_printable_string;\n\n"
185178825Sdfr	     );
186178825Sdfr    fprintf (headerfile,
187233294Sstas	     "typedef struct heim_octet_string heim_ia5_string;\n\n"
188178825Sdfr	     );
189178825Sdfr    fprintf (headerfile,
190178825Sdfr	     "typedef struct heim_bmp_string {\n"
19190926Snectar	     "  size_t length;\n"
192178825Sdfr	     "  uint16_t *data;\n"
193178825Sdfr	     "} heim_bmp_string;\n\n");
194178825Sdfr    fprintf (headerfile,
195178825Sdfr	     "typedef struct heim_universal_string {\n"
196178825Sdfr	     "  size_t length;\n"
197178825Sdfr	     "  uint32_t *data;\n"
198178825Sdfr	     "} heim_universal_string;\n\n");
199178825Sdfr    fprintf (headerfile,
200178825Sdfr	     "typedef char *heim_visible_string;\n\n"
201178825Sdfr	     );
202178825Sdfr    fprintf (headerfile,
203178825Sdfr	     "typedef struct heim_oid {\n"
204178825Sdfr	     "  size_t length;\n"
20590926Snectar	     "  unsigned *components;\n"
206178825Sdfr	     "} heim_oid;\n\n");
207178825Sdfr    fprintf (headerfile,
208178825Sdfr	     "typedef struct heim_bit_string {\n"
209178825Sdfr	     "  size_t length;\n"
210178825Sdfr	     "  void *data;\n"
211178825Sdfr	     "} heim_bit_string;\n\n");
212178825Sdfr    fprintf (headerfile,
213178825Sdfr	     "typedef struct heim_octet_string heim_any;\n"
214178825Sdfr	     "typedef struct heim_octet_string heim_any_set;\n\n");
215103423Snectar    fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R)                  \\\n"
216103423Snectar	  "  do {                                                         \\\n"
217103423Snectar	  "    (BL) = length_##T((S));                                    \\\n"
218103423Snectar	  "    (B) = malloc((BL));                                        \\\n"
219103423Snectar	  "    if((B) == NULL) {                                          \\\n"
220103423Snectar	  "      (R) = ENOMEM;                                            \\\n"
221103423Snectar	  "    } else {                                                   \\\n"
222103423Snectar	  "      (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \\\n"
223103423Snectar	  "                       (S), (L));                              \\\n"
224103423Snectar	  "      if((R) != 0) {                                           \\\n"
225103423Snectar	  "        free((B));                                             \\\n"
226103423Snectar	  "        (B) = NULL;                                            \\\n"
227103423Snectar	  "      }                                                        \\\n"
228103423Snectar	  "    }                                                          \\\n"
229103423Snectar	  "  } while (0)\n\n",
230103423Snectar	  headerfile);
231233294Sstas    fputs("#ifdef _WIN32\n"
232233294Sstas	  "#ifndef ASN1_LIB\n"
233233294Sstas	  "#define ASN1EXP  __declspec(dllimport)\n"
234233294Sstas	  "#else\n"
235233294Sstas	  "#define ASN1EXP\n"
236233294Sstas	  "#endif\n"
237233294Sstas	  "#define ASN1CALL __stdcall\n"
238233294Sstas	  "#else\n"
239233294Sstas	  "#define ASN1EXP\n"
240233294Sstas	  "#define ASN1CALL\n"
241233294Sstas	  "#endif\n",
242233294Sstas	  headerfile);
243178825Sdfr    fprintf (headerfile, "struct units;\n\n");
24455682Smarkm    fprintf (headerfile, "#endif\n\n");
245233294Sstas    if (asprintf(&fn, "%s_files", base) < 0 || fn == NULL)
246178825Sdfr	errx(1, "malloc");
247178825Sdfr    logfile = fopen(fn, "w");
24855682Smarkm    if (logfile == NULL)
249178825Sdfr	err (1, "open %s", fn);
250233294Sstas
251233294Sstas    /* if one code file, write into the one codefile */
252233294Sstas    if (one_code_file)
253233294Sstas	return;
254233294Sstas
255233294Sstas    templatefile = fopen (template, "w");
256233294Sstas    if (templatefile == NULL)
257233294Sstas	err (1, "open %s", template);
258233294Sstas
259233294Sstas    fprintf (templatefile,
260233294Sstas	     "/* Generated from %s */\n"
261233294Sstas	     "/* Do not edit */\n\n"
262233294Sstas	     "#include <stdio.h>\n"
263233294Sstas	     "#include <stdlib.h>\n"
264233294Sstas	     "#include <time.h>\n"
265233294Sstas	     "#include <string.h>\n"
266233294Sstas	     "#include <errno.h>\n"
267233294Sstas	     "#include <limits.h>\n"
268233294Sstas	     "#include <krb5-types.h>\n",
269233294Sstas	     filename);
270233294Sstas
271233294Sstas    fprintf (templatefile,
272233294Sstas	     "#include <%s>\n"
273233294Sstas	     "#include <%s>\n"
274233294Sstas	     "#include <der.h>\n"
275233294Sstas	     "#include <der-private.h>\n"
276233294Sstas	     "#include <asn1-template.h>\n",
277233294Sstas	     header, privheader);
278233294Sstas
279233294Sstas
28055682Smarkm}
28155682Smarkm
28255682Smarkmvoid
28372445Sassarclose_generate (void)
28455682Smarkm{
28555682Smarkm    fprintf (headerfile, "#endif /* __%s_h__ */\n", headerbase);
28655682Smarkm
287233294Sstas    if (headerfile)
288233294Sstas        fclose (headerfile);
289233294Sstas    if (privheaderfile)
290233294Sstas        fclose (privheaderfile);
291233294Sstas    if (templatefile)
292233294Sstas        fclose (templatefile);
293233294Sstas    if (logfile)
294233294Sstas        fprintf (logfile, "\n");
295233294Sstas        fclose (logfile);
29655682Smarkm}
29755682Smarkm
29855682Smarkmvoid
299178825Sdfrgen_assign_defval(const char *var, struct value *val)
300178825Sdfr{
301178825Sdfr    switch(val->type) {
302178825Sdfr    case stringvalue:
303178825Sdfr	fprintf(codefile, "if((%s = strdup(\"%s\")) == NULL)\nreturn ENOMEM;\n", var, val->u.stringvalue);
304178825Sdfr	break;
305178825Sdfr    case integervalue:
306178825Sdfr	fprintf(codefile, "%s = %d;\n", var, val->u.integervalue);
307178825Sdfr	break;
308178825Sdfr    case booleanvalue:
309178825Sdfr	if(val->u.booleanvalue)
310178825Sdfr	    fprintf(codefile, "%s = TRUE;\n", var);
311178825Sdfr	else
312178825Sdfr	    fprintf(codefile, "%s = FALSE;\n", var);
313178825Sdfr	break;
314178825Sdfr    default:
315178825Sdfr	abort();
316178825Sdfr    }
317178825Sdfr}
318178825Sdfr
319178825Sdfrvoid
320178825Sdfrgen_compare_defval(const char *var, struct value *val)
321178825Sdfr{
322178825Sdfr    switch(val->type) {
323178825Sdfr    case stringvalue:
324178825Sdfr	fprintf(codefile, "if(strcmp(%s, \"%s\") != 0)\n", var, val->u.stringvalue);
325178825Sdfr	break;
326178825Sdfr    case integervalue:
327178825Sdfr	fprintf(codefile, "if(%s != %d)\n", var, val->u.integervalue);
328178825Sdfr	break;
329178825Sdfr    case booleanvalue:
330178825Sdfr	if(val->u.booleanvalue)
331178825Sdfr	    fprintf(codefile, "if(!%s)\n", var);
332178825Sdfr	else
333178825Sdfr	    fprintf(codefile, "if(%s)\n", var);
334178825Sdfr	break;
335178825Sdfr    default:
336178825Sdfr	abort();
337178825Sdfr    }
338178825Sdfr}
339178825Sdfr
340233294Sstasvoid
341178825Sdfrgenerate_header_of_codefile(const char *name)
342178825Sdfr{
343233294Sstas    char *filename = NULL;
344178825Sdfr
345178825Sdfr    if (codefile != NULL)
346178825Sdfr	abort();
347178825Sdfr
348233294Sstas    if (asprintf (&filename, "%s_%s.x", STEM, name) < 0 || filename == NULL)
349178825Sdfr	errx(1, "malloc");
350178825Sdfr    codefile = fopen (filename, "w");
351178825Sdfr    if (codefile == NULL)
352178825Sdfr	err (1, "fopen %s", filename);
353178825Sdfr    fprintf(logfile, "%s ", filename);
354178825Sdfr    free(filename);
355233294Sstas    filename = NULL;
356233294Sstas    fprintf (codefile,
357178825Sdfr	     "/* Generated from %s */\n"
358178825Sdfr	     "/* Do not edit */\n\n"
359233294Sstas	     "#define  ASN1_LIB\n\n"
360178825Sdfr	     "#include <stdio.h>\n"
361178825Sdfr	     "#include <stdlib.h>\n"
362178825Sdfr	     "#include <time.h>\n"
363178825Sdfr	     "#include <string.h>\n"
364178825Sdfr	     "#include <errno.h>\n"
365178825Sdfr	     "#include <limits.h>\n"
366178825Sdfr	     "#include <krb5-types.h>\n",
367178825Sdfr	     orig_filename);
368178825Sdfr
369178825Sdfr    fprintf (codefile,
370233294Sstas	     "#include <%s>\n"
371233294Sstas	     "#include <%s>\n",
372233294Sstas	     header, privheader);
373178825Sdfr    fprintf (codefile,
374178825Sdfr	     "#include <asn1_err.h>\n"
375178825Sdfr	     "#include <der.h>\n"
376233294Sstas	     "#include <der-private.h>\n"
377233294Sstas	     "#include <asn1-template.h>\n"
378178825Sdfr	     "#include <parse_units.h>\n\n");
379178825Sdfr
380178825Sdfr}
381178825Sdfr
382233294Sstasvoid
383178825Sdfrclose_codefile(void)
384178825Sdfr{
385178825Sdfr    if (codefile == NULL)
386178825Sdfr	abort();
387178825Sdfr
388178825Sdfr    fclose(codefile);
389178825Sdfr    codefile = NULL;
390178825Sdfr}
391178825Sdfr
392178825Sdfr
393178825Sdfrvoid
39455682Smarkmgenerate_constant (const Symbol *s)
39555682Smarkm{
396178825Sdfr    switch(s->value->type) {
397178825Sdfr    case booleanvalue:
398178825Sdfr	break;
399178825Sdfr    case integervalue:
400178825Sdfr	fprintf (headerfile, "enum { %s = %d };\n\n",
401178825Sdfr		 s->gen_name, s->value->u.integervalue);
402178825Sdfr	break;
403178825Sdfr    case nullvalue:
404178825Sdfr	break;
405178825Sdfr    case stringvalue:
406178825Sdfr	break;
407178825Sdfr    case objectidentifiervalue: {
408178825Sdfr	struct objid *o, **list;
409233294Sstas	unsigned int i, len;
410233294Sstas	char *gen_upper;
411178825Sdfr
412233294Sstas	if (!one_code_file)
413233294Sstas	    generate_header_of_codefile(s->gen_name);
414178825Sdfr
415178825Sdfr	len = 0;
416178825Sdfr	for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next)
417178825Sdfr	    len++;
418233294Sstas	if (len == 0) {
419233294Sstas	    printf("s->gen_name: %s",s->gen_name);
420233294Sstas	    fflush(stdout);
421233294Sstas	    break;
422233294Sstas	}
423178825Sdfr	list = emalloc(sizeof(*list) * len);
424178825Sdfr
425178825Sdfr	i = 0;
426178825Sdfr	for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next)
427178825Sdfr	    list[i++] = o;
428178825Sdfr
429178825Sdfr	fprintf (headerfile, "/* OBJECT IDENTIFIER %s ::= { ", s->name);
430233294Sstas	for (i = len ; i > 0; i--) {
431233294Sstas	    o = list[i - 1];
432178825Sdfr	    fprintf(headerfile, "%s(%d) ",
433178825Sdfr		    o->label ? o->label : "label-less", o->value);
434178825Sdfr	}
435178825Sdfr
436178825Sdfr	fprintf (codefile, "static unsigned oid_%s_variable_num[%d] =  {",
437178825Sdfr		 s->gen_name, len);
438233294Sstas	for (i = len ; i > 0; i--) {
439233294Sstas	    fprintf(codefile, "%d%s ", list[i - 1]->value, i > 1 ? "," : "");
440178825Sdfr	}
441178825Sdfr	fprintf(codefile, "};\n");
442178825Sdfr
443233294Sstas	fprintf (codefile, "const heim_oid asn1_oid_%s = "
444233294Sstas		 "{ %d, oid_%s_variable_num };\n\n",
445178825Sdfr		 s->gen_name, len, s->gen_name);
446178825Sdfr
447233294Sstas	free(list);
448178825Sdfr
449233294Sstas	/* header file */
450178825Sdfr
451233294Sstas	gen_upper = strdup(s->gen_name);
452233294Sstas	len = strlen(gen_upper);
453233294Sstas	for (i = 0; i < len; i++)
454233294Sstas	    gen_upper[i] = toupper((int)s->gen_name[i]);
455233294Sstas
456233294Sstas	fprintf (headerfile, "} */\n");
457233294Sstas	fprintf (headerfile,
458233294Sstas		 "extern ASN1EXP const heim_oid asn1_oid_%s;\n"
459233294Sstas		 "#define ASN1_OID_%s (&asn1_oid_%s)\n\n",
460233294Sstas		 s->gen_name,
461233294Sstas		 gen_upper,
462233294Sstas		 s->gen_name);
463233294Sstas
464233294Sstas	free(gen_upper);
465233294Sstas
466233294Sstas	if (!one_code_file)
467233294Sstas	    close_codefile();
468233294Sstas
469178825Sdfr	break;
470178825Sdfr    }
471178825Sdfr    default:
472178825Sdfr	abort();
473178825Sdfr    }
47455682Smarkm}
47555682Smarkm
476233294Sstasint
477233294Sstasis_primitive_type(int type)
478233294Sstas{
479233294Sstas    switch(type) {
480233294Sstas    case TInteger:
481233294Sstas    case TBoolean:
482233294Sstas    case TOctetString:
483233294Sstas    case TBitString:
484233294Sstas    case TEnumerated:
485233294Sstas    case TGeneralizedTime:
486233294Sstas    case TGeneralString:
487233294Sstas    case TTeletexString:
488233294Sstas    case TOID:
489233294Sstas    case TUTCTime:
490233294Sstas    case TUTF8String:
491233294Sstas    case TPrintableString:
492233294Sstas    case TIA5String:
493233294Sstas    case TBMPString:
494233294Sstas    case TUniversalString:
495233294Sstas    case TVisibleString:
496233294Sstas    case TNull:
497233294Sstas	return 1;
498233294Sstas    default:
499233294Sstas	return 0;
500233294Sstas    }
501233294Sstas}
502233294Sstas
50355682Smarkmstatic void
50455682Smarkmspace(int level)
50555682Smarkm{
50655682Smarkm    while(level-- > 0)
50755682Smarkm	fprintf(headerfile, "  ");
50855682Smarkm}
50955682Smarkm
510178825Sdfrstatic const char *
511178825Sdfrlast_member_p(struct member *m)
512178825Sdfr{
513178825Sdfr    struct member *n = ASN1_TAILQ_NEXT(m, members);
514178825Sdfr    if (n == NULL)
515178825Sdfr	return "";
516178825Sdfr    if (n->ellipsis && ASN1_TAILQ_NEXT(n, members) == NULL)
517178825Sdfr	return "";
518178825Sdfr    return ",";
519178825Sdfr}
520178825Sdfr
521178825Sdfrstatic struct member *
522178825Sdfrhave_ellipsis(Type *t)
523178825Sdfr{
524178825Sdfr    struct member *m;
525178825Sdfr    ASN1_TAILQ_FOREACH(m, t->members, members) {
526178825Sdfr	if (m->ellipsis)
527178825Sdfr	    return m;
528178825Sdfr    }
529178825Sdfr    return NULL;
530178825Sdfr}
531178825Sdfr
53255682Smarkmstatic void
53355682Smarkmdefine_asn1 (int level, Type *t)
53455682Smarkm{
53555682Smarkm    switch (t->type) {
53655682Smarkm    case TType:
53755682Smarkm	fprintf (headerfile, "%s", t->symbol->name);
53855682Smarkm	break;
53955682Smarkm    case TInteger:
540178825Sdfr	if(t->members == NULL) {
541178825Sdfr            fprintf (headerfile, "INTEGER");
542178825Sdfr	    if (t->range)
543178825Sdfr		fprintf (headerfile, " (%d..%d)",
544178825Sdfr			 t->range->min, t->range->max);
545178825Sdfr        } else {
546178825Sdfr	    Member *m;
547178825Sdfr            fprintf (headerfile, "INTEGER {\n");
548178825Sdfr	    ASN1_TAILQ_FOREACH(m, t->members, members) {
549178825Sdfr                space (level + 1);
550233294Sstas		fprintf(headerfile, "%s(%d)%s\n", m->gen_name, m->val,
551178825Sdfr			last_member_p(m));
552178825Sdfr            }
553178825Sdfr	    space(level);
554178825Sdfr            fprintf (headerfile, "}");
555178825Sdfr        }
55655682Smarkm	break;
557178825Sdfr    case TBoolean:
558178825Sdfr	fprintf (headerfile, "BOOLEAN");
55972445Sassar	break;
56055682Smarkm    case TOctetString:
56155682Smarkm	fprintf (headerfile, "OCTET STRING");
56255682Smarkm	break;
563178825Sdfr    case TEnumerated :
56455682Smarkm    case TBitString: {
56555682Smarkm	Member *m;
56655682Smarkm
56755682Smarkm	space(level);
568178825Sdfr	if(t->type == TBitString)
569178825Sdfr	    fprintf (headerfile, "BIT STRING {\n");
570178825Sdfr	else
571178825Sdfr	    fprintf (headerfile, "ENUMERATED {\n");
572178825Sdfr	ASN1_TAILQ_FOREACH(m, t->members, members) {
57355682Smarkm	    space(level + 1);
574233294Sstas	    fprintf (headerfile, "%s(%d)%s\n", m->name, m->val,
575178825Sdfr		     last_member_p(m));
57655682Smarkm	}
57755682Smarkm	space(level);
57855682Smarkm	fprintf (headerfile, "}");
57955682Smarkm	break;
58055682Smarkm    }
581178825Sdfr    case TChoice:
582178825Sdfr    case TSet:
58355682Smarkm    case TSequence: {
58455682Smarkm	Member *m;
58555682Smarkm	int max_width = 0;
58655682Smarkm
587178825Sdfr	if(t->type == TChoice)
588178825Sdfr	    fprintf(headerfile, "CHOICE {\n");
589178825Sdfr	else if(t->type == TSet)
590178825Sdfr	    fprintf(headerfile, "SET {\n");
591178825Sdfr	else
592178825Sdfr	    fprintf(headerfile, "SEQUENCE {\n");
593178825Sdfr	ASN1_TAILQ_FOREACH(m, t->members, members) {
594178825Sdfr	    if(strlen(m->name) > max_width)
595178825Sdfr		max_width = strlen(m->name);
59655682Smarkm	}
597178825Sdfr	max_width += 3;
59855682Smarkm	if(max_width < 16) max_width = 16;
599178825Sdfr	ASN1_TAILQ_FOREACH(m, t->members, members) {
600178825Sdfr	    int width = max_width;
60155682Smarkm	    space(level + 1);
602178825Sdfr	    if (m->ellipsis) {
603178825Sdfr		fprintf (headerfile, "...");
604178825Sdfr	    } else {
605178825Sdfr		width -= fprintf(headerfile, "%s", m->name);
606178825Sdfr		fprintf(headerfile, "%*s", width, "");
607178825Sdfr		define_asn1(level + 1, m->type);
608178825Sdfr		if(m->optional)
609178825Sdfr		    fprintf(headerfile, " OPTIONAL");
610178825Sdfr	    }
611178825Sdfr	    if(last_member_p(m))
61255682Smarkm		fprintf (headerfile, ",");
61355682Smarkm	    fprintf (headerfile, "\n");
61455682Smarkm	}
61555682Smarkm	space(level);
61655682Smarkm	fprintf (headerfile, "}");
61755682Smarkm	break;
61855682Smarkm    }
619178825Sdfr    case TSequenceOf:
62055682Smarkm	fprintf (headerfile, "SEQUENCE OF ");
62155682Smarkm	define_asn1 (0, t->subtype);
62255682Smarkm	break;
623178825Sdfr    case TSetOf:
624178825Sdfr	fprintf (headerfile, "SET OF ");
625178825Sdfr	define_asn1 (0, t->subtype);
626178825Sdfr	break;
62755682Smarkm    case TGeneralizedTime:
62855682Smarkm	fprintf (headerfile, "GeneralizedTime");
62955682Smarkm	break;
63055682Smarkm    case TGeneralString:
63155682Smarkm	fprintf (headerfile, "GeneralString");
63255682Smarkm	break;
633233294Sstas    case TTeletexString:
634233294Sstas	fprintf (headerfile, "TeletexString");
635233294Sstas	break;
636178825Sdfr    case TTag: {
637233294Sstas	const char *classnames[] = { "UNIVERSAL ", "APPLICATION ",
638178825Sdfr				     "" /* CONTEXT */, "PRIVATE " };
639178825Sdfr	if(t->tag.tagclass != ASN1_C_UNIV)
640233294Sstas	    fprintf (headerfile, "[%s%d] ",
641178825Sdfr		     classnames[t->tag.tagclass],
642178825Sdfr		     t->tag.tagvalue);
643178825Sdfr	if(t->tag.tagenv == TE_IMPLICIT)
644178825Sdfr	    fprintf (headerfile, "IMPLICIT ");
64555682Smarkm	define_asn1 (level, t->subtype);
64655682Smarkm	break;
647178825Sdfr    }
648178825Sdfr    case TUTCTime:
649178825Sdfr	fprintf (headerfile, "UTCTime");
650178825Sdfr	break;
651178825Sdfr    case TUTF8String:
652178825Sdfr	space(level);
653178825Sdfr	fprintf (headerfile, "UTF8String");
654178825Sdfr	break;
655178825Sdfr    case TPrintableString:
656178825Sdfr	space(level);
657178825Sdfr	fprintf (headerfile, "PrintableString");
658178825Sdfr	break;
659178825Sdfr    case TIA5String:
660178825Sdfr	space(level);
661178825Sdfr	fprintf (headerfile, "IA5String");
662178825Sdfr	break;
663178825Sdfr    case TBMPString:
664178825Sdfr	space(level);
665178825Sdfr	fprintf (headerfile, "BMPString");
666178825Sdfr	break;
667178825Sdfr    case TUniversalString:
668178825Sdfr	space(level);
669178825Sdfr	fprintf (headerfile, "UniversalString");
670178825Sdfr	break;
671178825Sdfr    case TVisibleString:
672178825Sdfr	space(level);
673178825Sdfr	fprintf (headerfile, "VisibleString");
674178825Sdfr	break;
675178825Sdfr    case TOID :
676178825Sdfr	space(level);
677178825Sdfr	fprintf(headerfile, "OBJECT IDENTIFIER");
678178825Sdfr	break;
679178825Sdfr    case TNull:
680178825Sdfr	space(level);
681178825Sdfr	fprintf (headerfile, "NULL");
682178825Sdfr	break;
68355682Smarkm    default:
68455682Smarkm	abort ();
68555682Smarkm    }
68655682Smarkm}
68755682Smarkm
68855682Smarkmstatic void
689233294Sstasgetnewbasename(char **newbasename, int typedefp, const char *basename, const char *name)
69055682Smarkm{
691233294Sstas    if (typedefp)
692233294Sstas	*newbasename = strdup(name);
693233294Sstas    else {
694233294Sstas	if (name[0] == '*')
695233294Sstas	    name++;
696233294Sstas	if (asprintf(newbasename, "%s_%s", basename, name) < 0)
697233294Sstas	    errx(1, "malloc");
698233294Sstas    }
699233294Sstas    if (*newbasename == NULL)
700233294Sstas	err(1, "malloc");
701233294Sstas}
702233294Sstas
703233294Sstasstatic void
704233294Sstasdefine_type (int level, const char *name, const char *basename, Type *t, int typedefp, int preservep)
705233294Sstas{
706233294Sstas    char *newbasename = NULL;
707233294Sstas
70855682Smarkm    switch (t->type) {
70955682Smarkm    case TType:
71055682Smarkm	space(level);
71155682Smarkm	fprintf (headerfile, "%s %s;\n", t->symbol->gen_name, name);
71255682Smarkm	break;
71355682Smarkm    case TInteger:
71455682Smarkm	space(level);
715178825Sdfr	if(t->members) {
71672445Sassar            Member *m;
71772445Sassar            fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
718178825Sdfr	    ASN1_TAILQ_FOREACH(m, t->members, members) {
71972445Sassar                space (level + 1);
720233294Sstas                fprintf(headerfile, "%s = %d%s\n", m->gen_name, m->val,
721178825Sdfr                        last_member_p(m));
72272445Sassar            }
72372445Sassar            fprintf (headerfile, "} %s;\n", name);
724178825Sdfr	} else if (t->range == NULL) {
725178825Sdfr	    fprintf (headerfile, "heim_integer %s;\n", name);
726178825Sdfr	} else if (t->range->min == INT_MIN && t->range->max == INT_MAX) {
727178825Sdfr	    fprintf (headerfile, "int %s;\n", name);
728178825Sdfr	} else if (t->range->min == 0 && t->range->max == UINT_MAX) {
729178825Sdfr	    fprintf (headerfile, "unsigned int %s;\n", name);
730178825Sdfr	} else if (t->range->min == 0 && t->range->max == INT_MAX) {
731178825Sdfr	    fprintf (headerfile, "unsigned int %s;\n", name);
732178825Sdfr	} else
733233294Sstas	    errx(1, "%s: unsupported range %d -> %d",
734178825Sdfr		 name, t->range->min, t->range->max);
73555682Smarkm	break;
736178825Sdfr    case TBoolean:
73755682Smarkm	space(level);
738178825Sdfr	fprintf (headerfile, "int %s;\n", name);
73955682Smarkm	break;
74055682Smarkm    case TOctetString:
74155682Smarkm	space(level);
742178825Sdfr	fprintf (headerfile, "heim_octet_string %s;\n", name);
74355682Smarkm	break;
74455682Smarkm    case TBitString: {
74555682Smarkm	Member *m;
74655682Smarkm	Type i;
747178825Sdfr	struct range range = { 0, INT_MAX };
74855682Smarkm
749178825Sdfr	i.type = TInteger;
750178825Sdfr	i.range = &range;
751178825Sdfr	i.members = NULL;
752178825Sdfr	i.constraint = NULL;
753178825Sdfr
75455682Smarkm	space(level);
755233294Sstas	if(ASN1_TAILQ_EMPTY(t->members))
756178825Sdfr	    fprintf (headerfile, "heim_bit_string %s;\n", name);
757178825Sdfr	else {
758233294Sstas	    int pos = 0;
759233294Sstas	    getnewbasename(&newbasename, typedefp, basename, name);
760233294Sstas
761233294Sstas	    fprintf (headerfile, "struct %s {\n", newbasename);
762178825Sdfr	    ASN1_TAILQ_FOREACH(m, t->members, members) {
763233294Sstas		char *n = NULL;
764233294Sstas
765233294Sstas		/* pad unused */
766233294Sstas		while (pos < m->val) {
767233294Sstas		    if (asprintf (&n, "_unused%d:1", pos) < 0 || n == NULL)
768233294Sstas			errx(1, "malloc");
769233294Sstas		    define_type (level + 1, n, newbasename, &i, FALSE, FALSE);
770233294Sstas		    free(n);
771233294Sstas		    pos++;
772233294Sstas		}
773233294Sstas
774233294Sstas		n = NULL;
775233294Sstas		if (asprintf (&n, "%s:1", m->gen_name) < 0 || n == NULL)
776178825Sdfr		    errx(1, "malloc");
777233294Sstas		define_type (level + 1, n, newbasename, &i, FALSE, FALSE);
778178825Sdfr		free (n);
779233294Sstas		n = NULL;
780233294Sstas		pos++;
781178825Sdfr	    }
782233294Sstas	    /* pad to 32 elements */
783233294Sstas	    while (pos < 32) {
784233294Sstas		char *n = NULL;
785233294Sstas		if (asprintf (&n, "_unused%d:1", pos) < 0 || n == NULL)
786233294Sstas		    errx(1, "malloc");
787233294Sstas		define_type (level + 1, n, newbasename, &i, FALSE, FALSE);
788233294Sstas		free(n);
789233294Sstas		pos++;
790233294Sstas	    }
791233294Sstas
792178825Sdfr	    space(level);
793178825Sdfr	    fprintf (headerfile, "} %s;\n\n", name);
79455682Smarkm	}
79555682Smarkm	break;
79655682Smarkm    }
79790926Snectar    case TEnumerated: {
79890926Snectar	Member *m;
79990926Snectar
80090926Snectar	space(level);
80190926Snectar	fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
802178825Sdfr	ASN1_TAILQ_FOREACH(m, t->members, members) {
80390926Snectar	    space(level + 1);
804178825Sdfr	    if (m->ellipsis)
805178825Sdfr		fprintf (headerfile, "/* ... */\n");
806178825Sdfr	    else
807178825Sdfr		fprintf (headerfile, "%s = %d%s\n", m->gen_name, m->val,
808178825Sdfr			 last_member_p(m));
80990926Snectar	}
81090926Snectar	space(level);
81190926Snectar	fprintf (headerfile, "} %s;\n\n", name);
81290926Snectar	break;
81390926Snectar    }
814178825Sdfr    case TSet:
81555682Smarkm    case TSequence: {
81655682Smarkm	Member *m;
81755682Smarkm
818233294Sstas	getnewbasename(&newbasename, typedefp, basename, name);
819233294Sstas
82055682Smarkm	space(level);
821233294Sstas	fprintf (headerfile, "struct %s {\n", newbasename);
822178825Sdfr	if (t->type == TSequence && preservep) {
823178825Sdfr	    space(level + 1);
824178825Sdfr	    fprintf(headerfile, "heim_octet_string _save;\n");
825178825Sdfr	}
826178825Sdfr	ASN1_TAILQ_FOREACH(m, t->members, members) {
827178825Sdfr	    if (m->ellipsis) {
828178825Sdfr		;
829178825Sdfr	    } else if (m->optional) {
830233294Sstas		char *n = NULL;
83155682Smarkm
832233294Sstas		if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL)
833178825Sdfr		    errx(1, "malloc");
834233294Sstas		define_type (level + 1, n, newbasename, m->type, FALSE, FALSE);
83555682Smarkm		free (n);
83655682Smarkm	    } else
837233294Sstas		define_type (level + 1, m->gen_name, newbasename, m->type, FALSE, FALSE);
83855682Smarkm	}
83955682Smarkm	space(level);
84055682Smarkm	fprintf (headerfile, "} %s;\n", name);
84155682Smarkm	break;
84255682Smarkm    }
843178825Sdfr    case TSetOf:
84455682Smarkm    case TSequenceOf: {
84555682Smarkm	Type i;
846178825Sdfr	struct range range = { 0, INT_MAX };
84755682Smarkm
848233294Sstas	getnewbasename(&newbasename, typedefp, basename, name);
849233294Sstas
850178825Sdfr	i.type = TInteger;
851178825Sdfr	i.range = &range;
852178825Sdfr	i.members = NULL;
853178825Sdfr	i.constraint = NULL;
85455682Smarkm
85555682Smarkm	space(level);
856233294Sstas	fprintf (headerfile, "struct %s {\n", newbasename);
857233294Sstas	define_type (level + 1, "len", newbasename, &i, FALSE, FALSE);
858233294Sstas	define_type (level + 1, "*val", newbasename, t->subtype, FALSE, FALSE);
85955682Smarkm	space(level);
86055682Smarkm	fprintf (headerfile, "} %s;\n", name);
86155682Smarkm	break;
86255682Smarkm    }
86355682Smarkm    case TGeneralizedTime:
86455682Smarkm	space(level);
86555682Smarkm	fprintf (headerfile, "time_t %s;\n", name);
86655682Smarkm	break;
86755682Smarkm    case TGeneralString:
86855682Smarkm	space(level);
869178825Sdfr	fprintf (headerfile, "heim_general_string %s;\n", name);
87055682Smarkm	break;
871233294Sstas    case TTeletexString:
872233294Sstas	space(level);
873233294Sstas	fprintf (headerfile, "heim_general_string %s;\n", name);
874233294Sstas	break;
875178825Sdfr    case TTag:
876233294Sstas	define_type (level, name, basename, t->subtype, typedefp, preservep);
87755682Smarkm	break;
878178825Sdfr    case TChoice: {
879178825Sdfr	int first = 1;
880178825Sdfr	Member *m;
881178825Sdfr
882233294Sstas	getnewbasename(&newbasename, typedefp, basename, name);
883233294Sstas
884178825Sdfr	space(level);
885233294Sstas	fprintf (headerfile, "struct %s {\n", newbasename);
886178825Sdfr	if (preservep) {
887178825Sdfr	    space(level + 1);
888178825Sdfr	    fprintf(headerfile, "heim_octet_string _save;\n");
889178825Sdfr	}
890178825Sdfr	space(level + 1);
891178825Sdfr	fprintf (headerfile, "enum {\n");
892178825Sdfr	m = have_ellipsis(t);
893178825Sdfr	if (m) {
894178825Sdfr	    space(level + 2);
895233294Sstas	    fprintf (headerfile, "%s = 0,\n", m->label);
896178825Sdfr	    first = 0;
897178825Sdfr	}
898178825Sdfr	ASN1_TAILQ_FOREACH(m, t->members, members) {
899178825Sdfr	    space(level + 2);
900178825Sdfr	    if (m->ellipsis)
901178825Sdfr		fprintf (headerfile, "/* ... */\n");
902178825Sdfr	    else
903233294Sstas		fprintf (headerfile, "%s%s%s\n", m->label,
904233294Sstas			 first ? " = 1" : "",
905178825Sdfr			 last_member_p(m));
906178825Sdfr	    first = 0;
907178825Sdfr	}
908178825Sdfr	space(level + 1);
909178825Sdfr	fprintf (headerfile, "} element;\n");
910178825Sdfr	space(level + 1);
911178825Sdfr	fprintf (headerfile, "union {\n");
912178825Sdfr	ASN1_TAILQ_FOREACH(m, t->members, members) {
913178825Sdfr	    if (m->ellipsis) {
914178825Sdfr		space(level + 2);
915178825Sdfr		fprintf(headerfile, "heim_octet_string asn1_ellipsis;\n");
916178825Sdfr	    } else if (m->optional) {
917233294Sstas		char *n = NULL;
918178825Sdfr
919233294Sstas		if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL)
920178825Sdfr		    errx(1, "malloc");
921233294Sstas		define_type (level + 2, n, newbasename, m->type, FALSE, FALSE);
922178825Sdfr		free (n);
923178825Sdfr	    } else
924233294Sstas		define_type (level + 2, m->gen_name, newbasename, m->type, FALSE, FALSE);
925178825Sdfr	}
926178825Sdfr	space(level + 1);
927178825Sdfr	fprintf (headerfile, "} u;\n");
928178825Sdfr	space(level);
929178825Sdfr	fprintf (headerfile, "} %s;\n", name);
930178825Sdfr	break;
931178825Sdfr    }
932178825Sdfr    case TUTCTime:
933178825Sdfr	space(level);
934178825Sdfr	fprintf (headerfile, "time_t %s;\n", name);
935178825Sdfr	break;
936178825Sdfr    case TUTF8String:
937178825Sdfr	space(level);
938178825Sdfr	fprintf (headerfile, "heim_utf8_string %s;\n", name);
939178825Sdfr	break;
940178825Sdfr    case TPrintableString:
941178825Sdfr	space(level);
942178825Sdfr	fprintf (headerfile, "heim_printable_string %s;\n", name);
943178825Sdfr	break;
944178825Sdfr    case TIA5String:
945178825Sdfr	space(level);
946178825Sdfr	fprintf (headerfile, "heim_ia5_string %s;\n", name);
947178825Sdfr	break;
948178825Sdfr    case TBMPString:
949178825Sdfr	space(level);
950178825Sdfr	fprintf (headerfile, "heim_bmp_string %s;\n", name);
951178825Sdfr	break;
952178825Sdfr    case TUniversalString:
953178825Sdfr	space(level);
954178825Sdfr	fprintf (headerfile, "heim_universal_string %s;\n", name);
955178825Sdfr	break;
956178825Sdfr    case TVisibleString:
957178825Sdfr	space(level);
958178825Sdfr	fprintf (headerfile, "heim_visible_string %s;\n", name);
959178825Sdfr	break;
960178825Sdfr    case TOID :
961178825Sdfr	space(level);
962178825Sdfr	fprintf (headerfile, "heim_oid %s;\n", name);
963178825Sdfr	break;
964178825Sdfr    case TNull:
965178825Sdfr	space(level);
966178825Sdfr	fprintf (headerfile, "int %s;\n", name);
967178825Sdfr	break;
96855682Smarkm    default:
96955682Smarkm	abort ();
97055682Smarkm    }
971233294Sstas    if (newbasename)
972233294Sstas	free(newbasename);
97355682Smarkm}
97455682Smarkm
97555682Smarkmstatic void
97655682Smarkmgenerate_type_header (const Symbol *s)
97755682Smarkm{
978178825Sdfr    int preservep = preserve_type(s->name) ? TRUE : FALSE;
979178825Sdfr
98055682Smarkm    fprintf (headerfile, "/*\n");
98155682Smarkm    fprintf (headerfile, "%s ::= ", s->name);
98255682Smarkm    define_asn1 (0, s->type);
98355682Smarkm    fprintf (headerfile, "\n*/\n\n");
98455682Smarkm
98555682Smarkm    fprintf (headerfile, "typedef ");
986233294Sstas    define_type (0, s->gen_name, s->gen_name, s->type, TRUE, preservep);
98755682Smarkm
98855682Smarkm    fprintf (headerfile, "\n");
98955682Smarkm}
99055682Smarkm
99155682Smarkmvoid
99255682Smarkmgenerate_type (const Symbol *s)
99355682Smarkm{
994233294Sstas    FILE *h;
995233294Sstas    const char * exp;
99655682Smarkm
997233294Sstas    if (!one_code_file)
998233294Sstas	generate_header_of_codefile(s->gen_name);
999233294Sstas
100055682Smarkm    generate_type_header (s);
1001233294Sstas
1002233294Sstas    if (template_flag)
1003233294Sstas	generate_template(s);
1004233294Sstas
1005233294Sstas    if (template_flag == 0 || is_template_compat(s) == 0) {
1006233294Sstas	generate_type_encode (s);
1007233294Sstas	generate_type_decode (s);
1008233294Sstas	generate_type_free (s);
1009233294Sstas	generate_type_length (s);
1010233294Sstas	generate_type_copy (s);
1011233294Sstas    }
1012178825Sdfr    generate_type_seq (s);
1013178825Sdfr    generate_glue (s->type, s->gen_name);
1014233294Sstas
1015233294Sstas    /* generate prototypes */
1016233294Sstas
1017233294Sstas    if (is_export(s->name)) {
1018233294Sstas	h = headerfile;
1019233294Sstas	exp = "ASN1EXP ";
1020233294Sstas    } else {
1021233294Sstas	h = privheaderfile;
1022233294Sstas	exp = "";
1023233294Sstas    }
1024233294Sstas
1025233294Sstas    fprintf (h,
1026233294Sstas	     "%sint    ASN1CALL "
1027233294Sstas	     "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n",
1028233294Sstas	     exp,
1029233294Sstas	     s->gen_name, s->gen_name);
1030233294Sstas    fprintf (h,
1031233294Sstas	     "%sint    ASN1CALL "
1032233294Sstas	     "encode_%s(unsigned char *, size_t, const %s *, size_t *);\n",
1033233294Sstas	     exp,
1034233294Sstas	     s->gen_name, s->gen_name);
1035233294Sstas    fprintf (h,
1036233294Sstas	     "%ssize_t ASN1CALL length_%s(const %s *);\n",
1037233294Sstas	     exp,
1038233294Sstas	     s->gen_name, s->gen_name);
1039233294Sstas    fprintf (h,
1040233294Sstas	     "%sint    ASN1CALL copy_%s  (const %s *, %s *);\n",
1041233294Sstas	     exp,
1042233294Sstas	     s->gen_name, s->gen_name, s->gen_name);
1043233294Sstas    fprintf (h,
1044233294Sstas	     "%svoid   ASN1CALL free_%s  (%s *);\n",
1045233294Sstas	     exp,
1046233294Sstas	     s->gen_name, s->gen_name);
1047233294Sstas
1048233294Sstas    fprintf(h, "\n\n");
1049233294Sstas
1050233294Sstas    if (!one_code_file) {
1051233294Sstas	fprintf(codefile, "\n\n");
1052233294Sstas	close_codefile();
1053233294Sstas	}
105455682Smarkm}
1055