diff options
Diffstat (limited to 'lib/asn1/gen.c')
| -rw-r--r-- | lib/asn1/gen.c | 479 | 
1 files changed, 368 insertions, 111 deletions
| diff --git a/lib/asn1/gen.c b/lib/asn1/gen.c index 499f8eab363b..2194b329ce1d 100644 --- a/lib/asn1/gen.c +++ b/lib/asn1/gen.c @@ -1,46 +1,48 @@  /* - * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden).  - * All rights reserved.  + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved.   * - * Redistribution and use in source and binary forms, with or without  - * modification, are permitted provided that the following conditions  - * are met:  + * Portions Copyright (c) 2009 Apple Inc. All rights reserved.   * - * 1. Redistributions of source code must retain the above copyright  - *    notice, this list of conditions and the following disclaimer.  + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met:   * - * 2. Redistributions in binary form must reproduce the above copyright  - *    notice, this list of conditions and the following disclaimer in the  - *    documentation and/or other materials provided with the distribution.  + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer.   * - * 3. Neither the name of the Institute nor the names of its contributors  - *    may be used to endorse or promote products derived from this software  - *    without specific prior written permission.  + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution.   * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND  - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE  - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE  - * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE  - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL  - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS  - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)  - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT  - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY  - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF  - * SUCH DAMAGE.  + * 3. Neither the name of the Institute nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE.   */  #include "gen_locl.h" -RCSID("$Id: gen.c 22429 2008-01-13 10:25:50Z lha $"); +RCSID("$Id$"); -FILE *headerfile, *codefile, *logfile; +FILE *privheaderfile, *headerfile, *codefile, *logfile, *templatefile;  #define STEM "asn1"  static const char *orig_filename; -static char *header; +static char *privheader, *header, *template;  static const char *headerbase = STEM;  /* @@ -66,6 +68,45 @@ add_import (const char *module)      fprintf (headerfile, "#include <%s_asn1.h>\n", module);  } +/* + * List of all exported symbols + */ + +struct sexport { +    const char *name; +    int defined; +    struct sexport *next; +}; + +static struct sexport *exports = NULL; + +void +add_export (const char *name) +{ +    struct sexport *tmp = emalloc (sizeof(*tmp)); + +    tmp->name   = name; +    tmp->next   = exports; +    exports     = tmp; +} + +int +is_export(const char *name) +{ +    struct sexport *tmp; + +    if (exports == NULL) /* no export list, all exported */ +	return 1; + +    for (tmp = exports; tmp != NULL; tmp = tmp->next) { +	if (strcmp(tmp->name, name) == 0) { +	    tmp->defined = 1; +	    return 1; +	} +    } +    return 0; +} +  const char *  get_filename (void)  { @@ -75,7 +116,7 @@ get_filename (void)  void  init_generate (const char *filename, const char *base)  { -    char *fn; +    char *fn = NULL;      orig_filename = filename;      if (base != NULL) { @@ -83,20 +124,40 @@ init_generate (const char *filename, const char *base)  	if (headerbase == NULL)  	    errx(1, "strdup");      } -    asprintf(&header, "%s.h", headerbase); -    if (header == NULL) + +    /* public header file */ +    if (asprintf(&header, "%s.h", headerbase) < 0 || header == NULL) +	errx(1, "malloc"); +    if (asprintf(&fn, "%s.hx", headerbase) < 0 || fn == NULL)  	errx(1, "malloc"); -    headerfile = fopen (header, "w"); +    headerfile = fopen (fn, "w");      if (headerfile == NULL) -	err (1, "open %s", header); +	err (1, "open %s", fn); +    free(fn); +    fn = NULL; + +    /* private header file */ +    if (asprintf(&privheader, "%s-priv.h", headerbase) < 0 || privheader == NULL) +	errx(1, "malloc"); +    if (asprintf(&fn, "%s-priv.hx", headerbase) < 0 || fn == NULL) +	errx(1, "malloc"); +    privheaderfile = fopen (fn, "w"); +    if (privheaderfile == NULL) +	err (1, "open %s", fn); +    free(fn); +    fn = NULL; + +    /* template file */ +    if (asprintf(&template, "%s-template.c", headerbase) < 0 || template == NULL) +	errx(1, "malloc");      fprintf (headerfile,  	     "/* Generated from %s */\n"  	     "/* Do not edit */\n\n",  	     filename); -    fprintf (headerfile,  +    fprintf (headerfile,  	     "#ifndef __%s_h__\n"  	     "#define __%s_h__\n\n", headerbase, headerbase); -    fprintf (headerfile,  +    fprintf (headerfile,  	     "#include <stddef.h>\n"  	     "#include <time.h>\n\n");      fprintf (headerfile, @@ -120,10 +181,10 @@ init_generate (const char *filename, const char *base)  	     "typedef char *heim_utf8_string;\n\n"  	     );      fprintf (headerfile, -	     "typedef char *heim_printable_string;\n\n" +	     "typedef struct heim_octet_string heim_printable_string;\n\n"  	     );      fprintf (headerfile, -	     "typedef char *heim_ia5_string;\n\n" +	     "typedef struct heim_octet_string heim_ia5_string;\n\n"  	     );      fprintf (headerfile,  	     "typedef struct heim_bmp_string {\n" @@ -167,14 +228,55 @@ init_generate (const char *filename, const char *base)  	  "    }                                                          \\\n"  	  "  } while (0)\n\n",  	  headerfile); +    fputs("#ifdef _WIN32\n" +	  "#ifndef ASN1_LIB\n" +	  "#define ASN1EXP  __declspec(dllimport)\n" +	  "#else\n" +	  "#define ASN1EXP\n" +	  "#endif\n" +	  "#define ASN1CALL __stdcall\n" +	  "#else\n" +	  "#define ASN1EXP\n" +	  "#define ASN1CALL\n" +	  "#endif\n", +	  headerfile);      fprintf (headerfile, "struct units;\n\n");      fprintf (headerfile, "#endif\n\n"); -    asprintf(&fn, "%s_files", base); -    if (fn == NULL) +    if (asprintf(&fn, "%s_files", base) < 0 || fn == NULL)  	errx(1, "malloc");      logfile = fopen(fn, "w");      if (logfile == NULL)  	err (1, "open %s", fn); + +    /* if one code file, write into the one codefile */ +    if (one_code_file) +	return; + +    templatefile = fopen (template, "w"); +    if (templatefile == NULL) +	err (1, "open %s", template); + +    fprintf (templatefile, +	     "/* Generated from %s */\n" +	     "/* Do not edit */\n\n" +	     "#include <stdio.h>\n" +	     "#include <stdlib.h>\n" +	     "#include <time.h>\n" +	     "#include <string.h>\n" +	     "#include <errno.h>\n" +	     "#include <limits.h>\n" +	     "#include <krb5-types.h>\n", +	     filename); + +    fprintf (templatefile, +	     "#include <%s>\n" +	     "#include <%s>\n" +	     "#include <der.h>\n" +	     "#include <der-private.h>\n" +	     "#include <asn1-template.h>\n", +	     header, privheader); + +  }  void @@ -182,9 +284,15 @@ close_generate (void)  {      fprintf (headerfile, "#endif /* __%s_h__ */\n", headerbase); -    fclose (headerfile); -    fprintf (logfile, "\n"); -    fclose (logfile); +    if (headerfile) +        fclose (headerfile); +    if (privheaderfile) +        fclose (privheaderfile); +    if (templatefile) +        fclose (templatefile); +    if (logfile) +        fprintf (logfile, "\n"); +        fclose (logfile);  }  void @@ -229,25 +337,26 @@ gen_compare_defval(const char *var, struct value *val)      }  } -static void +void  generate_header_of_codefile(const char *name)  { -    char *filename; +    char *filename = NULL;      if (codefile != NULL)  	abort(); -    asprintf (&filename, "%s_%s.x", STEM, name); -    if (filename == NULL) +    if (asprintf (&filename, "%s_%s.x", STEM, name) < 0 || filename == NULL)  	errx(1, "malloc");      codefile = fopen (filename, "w");      if (codefile == NULL)  	err (1, "fopen %s", filename);      fprintf(logfile, "%s ", filename);      free(filename); -    fprintf (codefile,  +    filename = NULL; +    fprintf (codefile,  	     "/* Generated from %s */\n"  	     "/* Do not edit */\n\n" +	     "#define  ASN1_LIB\n\n"  	     "#include <stdio.h>\n"  	     "#include <stdlib.h>\n"  	     "#include <time.h>\n" @@ -258,16 +367,19 @@ generate_header_of_codefile(const char *name)  	     orig_filename);      fprintf (codefile, -	     "#include <%s.h>\n", -	     headerbase); +	     "#include <%s>\n" +	     "#include <%s>\n", +	     header, privheader);      fprintf (codefile,  	     "#include <asn1_err.h>\n"  	     "#include <der.h>\n" +	     "#include <der-private.h>\n" +	     "#include <asn1-template.h>\n"  	     "#include <parse_units.h>\n\n");  } -static void +void  close_codefile(void)  {      if (codefile == NULL) @@ -294,13 +406,20 @@ generate_constant (const Symbol *s)  	break;      case objectidentifiervalue: {  	struct objid *o, **list; -	int i, len; +	unsigned int i, len; +	char *gen_upper; -	generate_header_of_codefile(s->gen_name); +	if (!one_code_file) +	    generate_header_of_codefile(s->gen_name);  	len = 0;  	for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next)  	    len++; +	if (len == 0) { +	    printf("s->gen_name: %s",s->gen_name); +	    fflush(stdout); +	    break; +	}  	list = emalloc(sizeof(*list) * len);  	i = 0; @@ -308,34 +427,44 @@ generate_constant (const Symbol *s)  	    list[i++] = o;  	fprintf (headerfile, "/* OBJECT IDENTIFIER %s ::= { ", s->name); -	for (i = len - 1 ; i >= 0; i--) { -	    o = list[i]; +	for (i = len ; i > 0; i--) { +	    o = list[i - 1];  	    fprintf(headerfile, "%s(%d) ",  		    o->label ? o->label : "label-less", o->value);  	} -	fprintf (headerfile, "} */\n"); -	fprintf (headerfile, "const heim_oid *oid_%s(void);\n\n", -		 s->gen_name); -  	fprintf (codefile, "static unsigned oid_%s_variable_num[%d] =  {",  		 s->gen_name, len); -	for (i = len - 1 ; i >= 0; i--) { -	    fprintf(codefile, "%d%s ", list[i]->value, i > 0 ? "," : ""); +	for (i = len ; i > 0; i--) { +	    fprintf(codefile, "%d%s ", list[i - 1]->value, i > 1 ? "," : "");  	}  	fprintf(codefile, "};\n"); -	fprintf (codefile, "static const heim_oid oid_%s_variable = " -		 "{ %d, oid_%s_variable_num };\n\n",  +	fprintf (codefile, "const heim_oid asn1_oid_%s = " +		 "{ %d, oid_%s_variable_num };\n\n",  		 s->gen_name, len, s->gen_name); -	fprintf (codefile, "const heim_oid *oid_%s(void)\n" -		 "{\n" -		 "return &oid_%s_variable;\n" -		 "}\n\n", -		 s->gen_name, s->gen_name); +	free(list); -	close_codefile(); +	/* header file */ + +	gen_upper = strdup(s->gen_name); +	len = strlen(gen_upper); +	for (i = 0; i < len; i++) +	    gen_upper[i] = toupper((int)s->gen_name[i]); + +	fprintf (headerfile, "} */\n"); +	fprintf (headerfile, +		 "extern ASN1EXP const heim_oid asn1_oid_%s;\n" +		 "#define ASN1_OID_%s (&asn1_oid_%s)\n\n", +		 s->gen_name, +		 gen_upper, +		 s->gen_name); + +	free(gen_upper); + +	if (!one_code_file) +	    close_codefile();  	break;      } @@ -344,6 +473,33 @@ generate_constant (const Symbol *s)      }  } +int +is_primitive_type(int type) +{ +    switch(type) { +    case TInteger: +    case TBoolean: +    case TOctetString: +    case TBitString: +    case TEnumerated: +    case TGeneralizedTime: +    case TGeneralString: +    case TTeletexString: +    case TOID: +    case TUTCTime: +    case TUTF8String: +    case TPrintableString: +    case TIA5String: +    case TBMPString: +    case TUniversalString: +    case TVisibleString: +    case TNull: +	return 1; +    default: +	return 0; +    } +} +  static void  space(int level)  { @@ -391,7 +547,7 @@ define_asn1 (int level, Type *t)              fprintf (headerfile, "INTEGER {\n");  	    ASN1_TAILQ_FOREACH(m, t->members, members) {                  space (level + 1); -		fprintf(headerfile, "%s(%d)%s\n", m->gen_name, m->val,  +		fprintf(headerfile, "%s(%d)%s\n", m->gen_name, m->val,  			last_member_p(m));              }  	    space(level); @@ -415,7 +571,7 @@ define_asn1 (int level, Type *t)  	    fprintf (headerfile, "ENUMERATED {\n");  	ASN1_TAILQ_FOREACH(m, t->members, members) {  	    space(level + 1); -	    fprintf (headerfile, "%s(%d)%s\n", m->name, m->val,  +	    fprintf (headerfile, "%s(%d)%s\n", m->name, m->val,  		     last_member_p(m));  	}  	space(level); @@ -474,11 +630,14 @@ define_asn1 (int level, Type *t)      case TGeneralString:  	fprintf (headerfile, "GeneralString");  	break; +    case TTeletexString: +	fprintf (headerfile, "TeletexString"); +	break;      case TTag: { -	const char *classnames[] = { "UNIVERSAL ", "APPLICATION ",  +	const char *classnames[] = { "UNIVERSAL ", "APPLICATION ",  				     "" /* CONTEXT */, "PRIVATE " };  	if(t->tag.tagclass != ASN1_C_UNIV) -	    fprintf (headerfile, "[%s%d] ",  +	    fprintf (headerfile, "[%s%d] ",  		     classnames[t->tag.tagclass],  		     t->tag.tagvalue);  	if(t->tag.tagenv == TE_IMPLICIT) @@ -527,8 +686,25 @@ define_asn1 (int level, Type *t)  }  static void -define_type (int level, const char *name, Type *t, int typedefp, int preservep) +getnewbasename(char **newbasename, int typedefp, const char *basename, const char *name) +{ +    if (typedefp) +	*newbasename = strdup(name); +    else { +	if (name[0] == '*') +	    name++; +	if (asprintf(newbasename, "%s_%s", basename, name) < 0) +	    errx(1, "malloc"); +    } +    if (*newbasename == NULL) +	err(1, "malloc"); +} + +static void +define_type (int level, const char *name, const char *basename, Type *t, int typedefp, int preservep)  { +    char *newbasename = NULL; +      switch (t->type) {      case TType:  	space(level); @@ -541,7 +717,7 @@ define_type (int level, const char *name, Type *t, int typedefp, int preservep)              fprintf (headerfile, "enum %s {\n", typedefp ? name : "");  	    ASN1_TAILQ_FOREACH(m, t->members, members) {                  space (level + 1); -                fprintf(headerfile, "%s = %d%s\n", m->gen_name, m->val,  +                fprintf(headerfile, "%s = %d%s\n", m->gen_name, m->val,                          last_member_p(m));              }              fprintf (headerfile, "} %s;\n", name); @@ -554,7 +730,7 @@ define_type (int level, const char *name, Type *t, int typedefp, int preservep)  	} else if (t->range->min == 0 && t->range->max == INT_MAX) {  	    fprintf (headerfile, "unsigned int %s;\n", name);  	} else -	    errx(1, "%s: unsupported range %d -> %d",  +	    errx(1, "%s: unsupported range %d -> %d",  		 name, t->range->min, t->range->max);  	break;      case TBoolean: @@ -576,19 +752,43 @@ define_type (int level, const char *name, Type *t, int typedefp, int preservep)  	i.constraint = NULL;  	space(level); -	if(ASN1_TAILQ_EMPTY(t->members))  +	if(ASN1_TAILQ_EMPTY(t->members))  	    fprintf (headerfile, "heim_bit_string %s;\n", name);  	else { -	    fprintf (headerfile, "struct %s {\n", typedefp ? name : ""); +	    int pos = 0; +	    getnewbasename(&newbasename, typedefp, basename, name); + +	    fprintf (headerfile, "struct %s {\n", newbasename);  	    ASN1_TAILQ_FOREACH(m, t->members, members) { -		char *n; -		 -		asprintf (&n, "%s:1", m->gen_name); -		if (n == NULL) +		char *n = NULL; + +		/* pad unused */ +		while (pos < m->val) { +		    if (asprintf (&n, "_unused%d:1", pos) < 0 || n == NULL) +			errx(1, "malloc"); +		    define_type (level + 1, n, newbasename, &i, FALSE, FALSE); +		    free(n); +		    pos++; +		} + +		n = NULL; +		if (asprintf (&n, "%s:1", m->gen_name) < 0 || n == NULL)  		    errx(1, "malloc"); -		define_type (level + 1, n, &i, FALSE, FALSE); +		define_type (level + 1, n, newbasename, &i, FALSE, FALSE);  		free (n); +		n = NULL; +		pos++; +	    } +	    /* pad to 32 elements */ +	    while (pos < 32) { +		char *n = NULL; +		if (asprintf (&n, "_unused%d:1", pos) < 0 || n == NULL) +		    errx(1, "malloc"); +		define_type (level + 1, n, newbasename, &i, FALSE, FALSE); +		free(n); +		pos++;  	    } +  	    space(level);  	    fprintf (headerfile, "} %s;\n\n", name);  	} @@ -615,8 +815,10 @@ define_type (int level, const char *name, Type *t, int typedefp, int preservep)      case TSequence: {  	Member *m; +	getnewbasename(&newbasename, typedefp, basename, name); +  	space(level); -	fprintf (headerfile, "struct %s {\n", typedefp ? name : ""); +	fprintf (headerfile, "struct %s {\n", newbasename);  	if (t->type == TSequence && preservep) {  	    space(level + 1);  	    fprintf(headerfile, "heim_octet_string _save;\n"); @@ -625,15 +827,14 @@ define_type (int level, const char *name, Type *t, int typedefp, int preservep)  	    if (m->ellipsis) {  		;  	    } else if (m->optional) { -		char *n; +		char *n = NULL; -		asprintf (&n, "*%s", m->gen_name); -		if (n == NULL) +		if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL)  		    errx(1, "malloc"); -		define_type (level + 1, n, m->type, FALSE, FALSE); +		define_type (level + 1, n, newbasename, m->type, FALSE, FALSE);  		free (n);  	    } else -		define_type (level + 1, m->gen_name, m->type, FALSE, FALSE); +		define_type (level + 1, m->gen_name, newbasename, m->type, FALSE, FALSE);  	}  	space(level);  	fprintf (headerfile, "} %s;\n", name); @@ -644,15 +845,17 @@ define_type (int level, const char *name, Type *t, int typedefp, int preservep)  	Type i;  	struct range range = { 0, INT_MAX }; +	getnewbasename(&newbasename, typedefp, basename, name); +  	i.type = TInteger;  	i.range = ⦥  	i.members = NULL;  	i.constraint = NULL;  	space(level); -	fprintf (headerfile, "struct %s {\n", typedefp ? name : ""); -	define_type (level + 1, "len", &i, FALSE, FALSE); -	define_type (level + 1, "*val", t->subtype, FALSE, FALSE); +	fprintf (headerfile, "struct %s {\n", newbasename); +	define_type (level + 1, "len", newbasename, &i, FALSE, FALSE); +	define_type (level + 1, "*val", newbasename, t->subtype, FALSE, FALSE);  	space(level);  	fprintf (headerfile, "} %s;\n", name);  	break; @@ -665,15 +868,21 @@ define_type (int level, const char *name, Type *t, int typedefp, int preservep)  	space(level);  	fprintf (headerfile, "heim_general_string %s;\n", name);  	break; +    case TTeletexString: +	space(level); +	fprintf (headerfile, "heim_general_string %s;\n", name); +	break;      case TTag: -	define_type (level, name, t->subtype, typedefp, preservep); +	define_type (level, name, basename, t->subtype, typedefp, preservep);  	break;      case TChoice: {  	int first = 1;  	Member *m; +	getnewbasename(&newbasename, typedefp, basename, name); +  	space(level); -	fprintf (headerfile, "struct %s {\n", typedefp ? name : ""); +	fprintf (headerfile, "struct %s {\n", newbasename);  	if (preservep) {  	    space(level + 1);  	    fprintf(headerfile, "heim_octet_string _save;\n"); @@ -683,7 +892,7 @@ define_type (int level, const char *name, Type *t, int typedefp, int preservep)  	m = have_ellipsis(t);  	if (m) {  	    space(level + 2); -	    fprintf (headerfile, "%s = 0,\n", m->label);  +	    fprintf (headerfile, "%s = 0,\n", m->label);  	    first = 0;  	}  	ASN1_TAILQ_FOREACH(m, t->members, members) { @@ -691,8 +900,8 @@ define_type (int level, const char *name, Type *t, int typedefp, int preservep)  	    if (m->ellipsis)  		fprintf (headerfile, "/* ... */\n");  	    else -		fprintf (headerfile, "%s%s%s\n", m->label,  -			 first ? " = 1" : "",  +		fprintf (headerfile, "%s%s%s\n", m->label, +			 first ? " = 1" : "",  			 last_member_p(m));  	    first = 0;  	} @@ -705,15 +914,14 @@ define_type (int level, const char *name, Type *t, int typedefp, int preservep)  		space(level + 2);  		fprintf(headerfile, "heim_octet_string asn1_ellipsis;\n");  	    } else if (m->optional) { -		char *n; +		char *n = NULL; -		asprintf (&n, "*%s", m->gen_name); -		if (n == NULL) +		if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL)  		    errx(1, "malloc"); -		define_type (level + 2, n, m->type, FALSE, FALSE); +		define_type (level + 2, n, newbasename, m->type, FALSE, FALSE);  		free (n);  	    } else -		define_type (level + 2, m->gen_name, m->type, FALSE, FALSE); +		define_type (level + 2, m->gen_name, newbasename, m->type, FALSE, FALSE);  	}  	space(level + 1);  	fprintf (headerfile, "} u;\n"); @@ -760,6 +968,8 @@ define_type (int level, const char *name, Type *t, int typedefp, int preservep)      default:  	abort ();      } +    if (newbasename) +	free(newbasename);  }  static void @@ -773,25 +983,72 @@ generate_type_header (const Symbol *s)      fprintf (headerfile, "\n*/\n\n");      fprintf (headerfile, "typedef "); -    define_type (0, s->gen_name, s->type, TRUE, preservep); +    define_type (0, s->gen_name, s->gen_name, s->type, TRUE, preservep);      fprintf (headerfile, "\n");  } -  void  generate_type (const Symbol *s)  { -    generate_header_of_codefile(s->gen_name); +    FILE *h; +    const char * exp; + +    if (!one_code_file) +	generate_header_of_codefile(s->gen_name);      generate_type_header (s); -    generate_type_encode (s); -    generate_type_decode (s); -    generate_type_free (s); -    generate_type_length (s); -    generate_type_copy (s); + +    if (template_flag) +	generate_template(s); + +    if (template_flag == 0 || is_template_compat(s) == 0) { +	generate_type_encode (s); +	generate_type_decode (s); +	generate_type_free (s); +	generate_type_length (s); +	generate_type_copy (s); +    }      generate_type_seq (s);      generate_glue (s->type, s->gen_name); -    fprintf(headerfile, "\n\n"); -    close_codefile(); + +    /* generate prototypes */ + +    if (is_export(s->name)) { +	h = headerfile; +	exp = "ASN1EXP "; +    } else { +	h = privheaderfile; +	exp = ""; +    } + +    fprintf (h, +	     "%sint    ASN1CALL " +	     "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n", +	     exp, +	     s->gen_name, s->gen_name); +    fprintf (h, +	     "%sint    ASN1CALL " +	     "encode_%s(unsigned char *, size_t, const %s *, size_t *);\n", +	     exp, +	     s->gen_name, s->gen_name); +    fprintf (h, +	     "%ssize_t ASN1CALL length_%s(const %s *);\n", +	     exp, +	     s->gen_name, s->gen_name); +    fprintf (h, +	     "%sint    ASN1CALL copy_%s  (const %s *, %s *);\n", +	     exp, +	     s->gen_name, s->gen_name, s->gen_name); +    fprintf (h, +	     "%svoid   ASN1CALL free_%s  (%s *);\n", +	     exp, +	     s->gen_name, s->gen_name); + +    fprintf(h, "\n\n"); + +    if (!one_code_file) { +	fprintf(codefile, "\n\n"); +	close_codefile(); +	}  } | 
