Path: blob/main/crypto/heimdal/lib/asn1/gen_template.c
34914 views
/*1* Copyright (c) 1997 - 2005 Kungliga Tekniska H�gskolan2* (Royal Institute of Technology, Stockholm, Sweden).3* All rights reserved.4*5* Portions Copyright (c) 2009 Apple Inc. All rights reserved.6*7* Redistribution and use in source and binary forms, with or without8* modification, are permitted provided that the following conditions9* are met:10*11* 1. Redistributions of source code must retain the above copyright12* notice, this list of conditions and the following disclaimer.13*14* 2. Redistributions in binary form must reproduce the above copyright15* notice, this list of conditions and the following disclaimer in the16* documentation and/or other materials provided with the distribution.17*18* 3. Neither the name of the Institute nor the names of its contributors19* may be used to endorse or promote products derived from this software20* without specific prior written permission.21*22* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND23* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE24* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE25* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE26* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL27* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS28* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)29* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT30* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY31* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF32* SUCH DAMAGE.33*/3435#include "gen_locl.h"3637static const char *symbol_name(const char *, const Type *);38static void generate_template_type(const char *, const char **, const char *, const char *, const char *,39Type *, int, int, int);4041static const char *42ttype_symbol(const char *basename, const Type *t)43{44return t->symbol->gen_name;45}4647static const char *48integer_symbol(const char *basename, const Type *t)49{50if (t->members)51return "int"; /* XXX enum foo */52else if (t->range == NULL)53return "heim_integer";54else if (t->range->min < INT_MIN && t->range->max <= INT64_MAX)55return "int64_t";56else if (t->range->min >= 0 && t->range->max > UINT_MAX)57return "uint64_t";58else if (t->range->min >= INT_MIN && t->range->max <= INT_MAX)59return "int";60else if (t->range->min >= 0 && t->range->max <= UINT_MAX)61return "unsigned";62else {63abort();64UNREACHABLE(return NULL);65}66}6768static const char *69boolean_symbol(const char *basename, const Type *t)70{71return "int";72}737475static const char *76octetstring_symbol(const char *basename, const Type *t)77{78return "heim_octet_string";79}8081static const char *82sequence_symbol(const char *basename, const Type *t)83{84return basename;85}8687static const char *88time_symbol(const char *basename, const Type *t)89{90return "time_t";91}9293static const char *94tag_symbol(const char *basename, const Type *t)95{96return symbol_name(basename, t->subtype);97}9899static const char *100generalstring_symbol(const char *basename, const Type *t)101{102return "heim_general_string";103}104105static const char *106printablestring_symbol(const char *basename, const Type *t)107{108return "heim_printable_string";109}110111static const char *112ia5string_symbol(const char *basename, const Type *t)113{114return "heim_ia5_string";115}116117static const char *118visiblestring_symbol(const char *basename, const Type *t)119{120return "heim_visible_string";121}122123static const char *124utf8string_symbol(const char *basename, const Type *t)125{126return "heim_utf8_string";127}128129static const char *130bmpstring_symbol(const char *basename, const Type *t)131{132return "heim_bmp_string";133}134135static const char *136universalstring_symbol(const char *basename, const Type *t)137{138return "heim_universal_string";139}140141static const char *142oid_symbol(const char *basename, const Type *t)143{144return "heim_oid";145}146147static const char *148bitstring_symbol(const char *basename, const Type *t)149{150if (t->members)151return basename;152return "heim_bit_string";153}154155156157struct {158enum typetype type;159const char *(*symbol_name)(const char *, const Type *);160int is_struct;161} types[] = {162{ TBMPString, bmpstring_symbol, 0 },163{ TBitString, bitstring_symbol, 0 },164{ TBoolean, boolean_symbol, 0 },165{ TGeneralString, generalstring_symbol, 0 },166{ TGeneralizedTime, time_symbol, 0 },167{ TIA5String, ia5string_symbol, 0 },168{ TInteger, integer_symbol, 0 },169{ TOID, oid_symbol, 0 },170{ TOctetString, octetstring_symbol, 0 },171{ TPrintableString, printablestring_symbol, 0 },172{ TSequence, sequence_symbol, 1 },173{ TSequenceOf, tag_symbol, 1 },174{ TSetOf, tag_symbol, 1 },175{ TTag, tag_symbol, 1 },176{ TType, ttype_symbol, 1 },177{ TUTCTime, time_symbol, 0 },178{ TUniversalString, universalstring_symbol, 0 },179{ TVisibleString, visiblestring_symbol, 0 },180{ TUTF8String, utf8string_symbol, 0 },181{ TChoice, sequence_symbol, 1 },182{ TNull, integer_symbol, 1 }183};184185static FILE *186get_code_file(void)187{188if (!one_code_file)189return templatefile;190return codefile;191}192193194static int195is_supported_type_p(const Type *t)196{197size_t i;198199for (i = 0; i < sizeof(types)/sizeof(types[0]); i++)200if (t->type == types[i].type)201return 1;202return 0;203}204205int206is_template_compat (const Symbol *s)207{208return is_supported_type_p(s->type);209}210211static const char *212symbol_name(const char *basename, const Type *t)213{214size_t i;215216for (i = 0; i < sizeof(types)/sizeof(types[0]); i++)217if (t->type == types[i].type)218return (types[i].symbol_name)(basename, t);219printf("unknown der type: %d\n", t->type);220exit(1);221}222223224static char *225partial_offset(const char *basetype, const char *name, int need_offset)226{227char *str;228if (name == NULL || need_offset == 0)229return strdup("0");230if (asprintf(&str, "offsetof(struct %s, %s)", basetype, name) < 0 || str == NULL)231errx(1, "malloc");232return str;233}234235struct template {236char *line;237char *tt;238char *offset;239char *ptr;240ASN1_TAILQ_ENTRY(template) members;241};242243ASN1_TAILQ_HEAD(templatehead, template);244245struct tlist {246char *name;247char *header;248struct templatehead template;249ASN1_TAILQ_ENTRY(tlist) tmembers;250};251252ASN1_TAILQ_HEAD(tlisthead, tlist);253254static void tlist_header(struct tlist *, const char *, ...) __attribute__((__format__(__printf__, 2, 3)));255static struct template *256add_line(struct templatehead *, const char *, ...) __attribute__((__format__(__printf__, 2, 3)));257static int tlist_cmp(const struct tlist *, const struct tlist *);258259static void add_line_pointer(struct templatehead *, const char *, const char *, const char *, ...)260__attribute__((__format__(__printf__, 4, 5)));261262263static struct tlisthead tlistmaster = ASN1_TAILQ_HEAD_INITIALIZER(tlistmaster);264static unsigned long numdups = 0;265266static struct tlist *267tlist_new(const char *name)268{269struct tlist *tl = calloc(1, sizeof(*tl));270tl->name = strdup(name);271ASN1_TAILQ_INIT(&tl->template);272return tl;273}274275static void276tlist_header(struct tlist *t, const char *fmt, ...)277{278va_list ap;279va_start(ap, fmt);280if (vasprintf(&t->header, fmt, ap) < 0 || t->header == NULL)281errx(1, "malloc");282va_end(ap);283}284285static unsigned long286tlist_count(struct tlist *tl)287{288unsigned int count = 0;289struct template *q;290291ASN1_TAILQ_FOREACH(q, &tl->template, members) {292count++;293}294return count;295}296297static void298tlist_add(struct tlist *tl)299{300ASN1_TAILQ_INSERT_TAIL(&tlistmaster, tl, tmembers);301}302303static void304tlist_print(struct tlist *tl)305{306struct template *q;307unsigned int i = 1;308FILE *f = get_code_file();309310fprintf(f, "static const struct asn1_template asn1_%s[] = {\n", tl->name);311fprintf(f, "/* 0 */ %s,\n", tl->header);312ASN1_TAILQ_FOREACH(q, &tl->template, members) {313int last = (ASN1_TAILQ_LAST(&tl->template, templatehead) == q);314fprintf(f, "/* %lu */ %s%s\n", (unsigned long)i++, q->line, last ? "" : ",");315}316fprintf(f, "};\n");317}318319static struct tlist *320tlist_find_by_name(const char *name)321{322struct tlist *ql;323ASN1_TAILQ_FOREACH(ql, &tlistmaster, tmembers) {324if (strcmp(ql->name, name) == 0)325return ql;326}327return NULL;328}329330static int331tlist_cmp_name(const char *tname, const char *qname)332{333struct tlist *tl = tlist_find_by_name(tname);334struct tlist *ql = tlist_find_by_name(qname);335return tlist_cmp(tl, ql);336}337338static int339tlist_cmp(const struct tlist *tl, const struct tlist *ql)340{341int ret;342struct template *t, *q;343344ret = strcmp(tl->header, ql->header);345if (ret) return ret;346347q = ASN1_TAILQ_FIRST(&ql->template);348ASN1_TAILQ_FOREACH(t, &tl->template, members) {349if (q == NULL) return 1;350351if (t->ptr == NULL || q->ptr == NULL) {352ret = strcmp(t->line, q->line);353if (ret) return ret;354} else {355ret = strcmp(t->tt, q->tt);356if (ret) return ret;357358ret = strcmp(t->offset, q->offset);359if (ret) return ret;360361if ((ret = strcmp(t->ptr, q->ptr)) != 0 ||362(ret = tlist_cmp_name(t->ptr, q->ptr)) != 0)363return ret;364}365q = ASN1_TAILQ_NEXT(q, members);366}367if (q != NULL) return -1;368return 0;369}370371372static const char *373tlist_find_dup(const struct tlist *tl)374{375struct tlist *ql;376377ASN1_TAILQ_FOREACH(ql, &tlistmaster, tmembers) {378if (tlist_cmp(ql, tl) == 0) {379numdups++;380return ql->name;381}382}383return NULL;384}385386387/*388*389*/390391static struct template *392add_line(struct templatehead *t, const char *fmt, ...)393{394struct template *q = calloc(1, sizeof(*q));395va_list ap;396va_start(ap, fmt);397if (vasprintf(&q->line, fmt, ap) < 0 || q->line == NULL)398errx(1, "malloc");399va_end(ap);400ASN1_TAILQ_INSERT_TAIL(t, q, members);401return q;402}403404static void405add_line_pointer(struct templatehead *t,406const char *ptr,407const char *offset,408const char *ttfmt,409...)410{411struct template *q;412va_list ap;413char *tt = NULL;414415va_start(ap, ttfmt);416if (vasprintf(&tt, ttfmt, ap) < 0 || tt == NULL)417errx(1, "malloc");418va_end(ap);419420q = add_line(t, "{ %s, %s, asn1_%s }", tt, offset, ptr);421q->tt = tt;422q->offset = strdup(offset);423q->ptr = strdup(ptr);424}425426static int427use_extern(const Symbol *s)428{429if (s->type == NULL)430return 1;431return 0;432}433434static int435is_struct(Type *t, int isstruct)436{437size_t i;438439if (t->type == TType)440return 0;441if (t->type == TSequence || t->type == TSet || t->type == TChoice)442return 1;443if (t->type == TTag)444return is_struct(t->subtype, isstruct);445446for (i = 0; i < sizeof(types)/sizeof(types[0]); i++) {447if (t->type == types[i].type) {448if (types[i].is_struct == 0)449return 0;450else451break;452}453}454455return isstruct;456}457458static const Type *459compact_tag(const Type *t)460{461while (t->type == TTag)462t = t->subtype;463return t;464}465466static void467template_members(struct templatehead *temp, const char *basetype, const char *name, const Type *t, int optional, int isstruct, int need_offset)468{469char *poffset = NULL;470471if (optional && t->type != TTag && t->type != TType)472errx(1, "%s...%s is optional and not a (TTag or TType)", basetype, name);473474poffset = partial_offset(basetype, name, need_offset);475476switch (t->type) {477case TType:478if (use_extern(t->symbol)) {479add_line(temp, "{ A1_OP_TYPE_EXTERN %s, %s, &asn1_extern_%s}",480optional ? "|A1_FLAG_OPTIONAL" : "",481poffset, t->symbol->gen_name);482} else {483add_line_pointer(temp, t->symbol->gen_name, poffset,484"A1_OP_TYPE %s", optional ? "|A1_FLAG_OPTIONAL" : "");485}486break;487case TInteger: {488char *itype = NULL;489490if (t->members)491itype = "IMEMBER";492else if (t->range == NULL)493itype = "HEIM_INTEGER";494else if (t->range->min < INT_MIN && t->range->max <= INT64_MAX)495itype = "INTEGER64";496else if (t->range->min >= 0 && t->range->max > UINT_MAX)497itype = "UNSIGNED64";498else if (t->range->min >= INT_MIN && t->range->max <= INT_MAX)499itype = "INTEGER";500else if (t->range->min >= 0 && t->range->max <= UINT_MAX)501itype = "UNSIGNED";502else503errx(1, "%s: unsupported range %" PRId64 " -> %" PRId64,504name, t->range->min, t->range->max);505506add_line(temp, "{ A1_PARSE_T(A1T_%s), %s, NULL }", itype, poffset);507break;508}509case TGeneralString:510add_line(temp, "{ A1_PARSE_T(A1T_GENERAL_STRING), %s, NULL }", poffset);511break;512case TTeletexString:513add_line(temp, "{ A1_PARSE_T(A1T_TELETEX_STRING), %s, NULL }", poffset);514break;515case TPrintableString:516add_line(temp, "{ A1_PARSE_T(A1T_PRINTABLE_STRING), %s, NULL }", poffset);517break;518case TOctetString:519add_line(temp, "{ A1_PARSE_T(A1T_OCTET_STRING), %s, NULL }", poffset);520break;521case TIA5String:522add_line(temp, "{ A1_PARSE_T(A1T_IA5_STRING), %s, NULL }", poffset);523break;524case TBMPString:525add_line(temp, "{ A1_PARSE_T(A1T_BMP_STRING), %s, NULL }", poffset);526break;527case TUniversalString:528add_line(temp, "{ A1_PARSE_T(A1T_UNIVERSAL_STRING), %s, NULL }", poffset);529break;530case TVisibleString:531add_line(temp, "{ A1_PARSE_T(A1T_VISIBLE_STRING), %s, NULL }", poffset);532break;533case TUTF8String:534add_line(temp, "{ A1_PARSE_T(A1T_UTF8_STRING), %s, NULL }", poffset);535break;536case TGeneralizedTime:537add_line(temp, "{ A1_PARSE_T(A1T_GENERALIZED_TIME), %s, NULL }", poffset);538break;539case TUTCTime:540add_line(temp, "{ A1_PARSE_T(A1T_UTC_TIME), %s, NULL }", poffset);541break;542case TBoolean:543add_line(temp, "{ A1_PARSE_T(A1T_BOOLEAN), %s, NULL }", poffset);544break;545case TOID:546add_line(temp, "{ A1_PARSE_T(A1T_OID), %s, NULL }", poffset);547break;548case TNull:549break;550case TBitString: {551struct templatehead template = ASN1_TAILQ_HEAD_INITIALIZER(template);552struct template *q;553Member *m;554size_t count = 0, i;555char *bname = NULL;556FILE *f = get_code_file();557558if (ASN1_TAILQ_EMPTY(t->members)) {559add_line(temp, "{ A1_PARSE_T(A1T_HEIM_BIT_STRING), %s, NULL }", poffset);560break;561}562563if (asprintf(&bname, "bmember_%s_%p", name ? name : "", t) < 0 || bname == NULL)564errx(1, "malloc");565output_name(bname);566567ASN1_TAILQ_FOREACH(m, t->members, members) {568add_line(&template, "{ 0, %d, 0 } /* %s */", m->val, m->gen_name);569}570571ASN1_TAILQ_FOREACH(q, &template, members) {572count++;573}574575fprintf(f, "static const struct asn1_template asn1_%s_%s[] = {\n", basetype, bname);576fprintf(f, "/* 0 */ { 0%s, sizeof(%s), ((void *)%lu) },\n",577rfc1510_bitstring ? "|A1_HBF_RFC1510" : "",578basetype, (unsigned long)count);579i = 1;580ASN1_TAILQ_FOREACH(q, &template, members) {581int last = (ASN1_TAILQ_LAST(&template, templatehead) == q);582fprintf(f, "/* %lu */ %s%s\n", (unsigned long)i++, q->line, last ? "" : ",");583}584fprintf(f, "};\n");585586add_line(temp, "{ A1_OP_BMEMBER, %s, asn1_%s_%s }", poffset, basetype, bname);587588free(bname);589590break;591}592case TSequence: {593Member *m;594595ASN1_TAILQ_FOREACH(m, t->members, members) {596char *newbasename = NULL;597598if (m->ellipsis)599continue;600601if (name) {602if (asprintf(&newbasename, "%s_%s", basetype, name) < 0)603errx(1, "malloc");604} else605newbasename = strdup(basetype);606if (newbasename == NULL)607errx(1, "malloc");608609template_members(temp, newbasename, m->gen_name, m->type, m->optional, isstruct, 1);610611free(newbasename);612}613614break;615}616case TTag: {617char *tname = NULL, *elname = NULL;618const char *sename, *dupname;619int subtype_is_struct = is_struct(t->subtype, isstruct);620621if (subtype_is_struct)622sename = basetype;623else624sename = symbol_name(basetype, t->subtype);625626if (asprintf(&tname, "tag_%s_%p", name ? name : "", t) < 0 || tname == NULL)627errx(1, "malloc");628output_name(tname);629630if (asprintf(&elname, "%s_%s", basetype, tname) < 0 || elname == NULL)631errx(1, "malloc");632633generate_template_type(elname, &dupname, NULL, sename, name,634t->subtype, 0, subtype_is_struct, 0);635636add_line_pointer(temp, dupname, poffset,637"A1_TAG_T(%s,%s,%s)%s",638classname(t->tag.tagclass),639is_primitive_type(t->subtype->type) ? "PRIM" : "CONS",640valuename(t->tag.tagclass, t->tag.tagvalue),641optional ? "|A1_FLAG_OPTIONAL" : "");642643free(tname);644free(elname);645646break;647}648case TSetOf:649case TSequenceOf: {650const char *type = NULL, *tname, *dupname;651char *sename = NULL, *elname = NULL;652int subtype_is_struct = is_struct(t->subtype, 0);653654if (name && subtype_is_struct) {655tname = "seofTstruct";656if (asprintf(&sename, "%s_%s_val", basetype, name) < 0)657errx(1, "malloc");658} else if (subtype_is_struct) {659tname = "seofTstruct";660if (asprintf(&sename, "%s_val", symbol_name(basetype, t->subtype)) < 0)661errx(1, "malloc");662} else {663if (name)664tname = name;665else666tname = "seofTstruct";667sename = strdup(symbol_name(basetype, t->subtype));668}669if (sename == NULL)670errx(1, "malloc");671672if (t->type == TSetOf) type = "A1_OP_SETOF";673else if (t->type == TSequenceOf) type = "A1_OP_SEQOF";674else abort();675676if (asprintf(&elname, "%s_%s_%p", basetype, tname, t) < 0 || elname == NULL)677errx(1, "malloc");678679generate_template_type(elname, &dupname, NULL, sename, NULL, t->subtype,6800, subtype_is_struct, need_offset);681682add_line(temp, "{ %s, %s, asn1_%s }", type, poffset, dupname);683free(sename);684break;685}686case TChoice: {687struct templatehead template = ASN1_TAILQ_HEAD_INITIALIZER(template);688struct template *q;689size_t count = 0, i;690char *tname = NULL;691FILE *f = get_code_file();692Member *m;693int ellipsis = 0;694char *e;695696if (asprintf(&tname, "asn1_choice_%s_%s%x",697basetype, name ? name : "", (unsigned int)(uintptr_t)t) < 0 || tname == NULL)698errx(1, "malloc");699700ASN1_TAILQ_FOREACH(m, t->members, members) {701const char *dupname;702char *elname = NULL;703char *newbasename = NULL;704int subtype_is_struct;705706if (m->ellipsis) {707ellipsis = 1;708continue;709}710711subtype_is_struct = is_struct(m->type, 0);712713if (asprintf(&elname, "%s_choice_%s", basetype, m->gen_name) < 0 || elname == NULL)714errx(1, "malloc");715716if (subtype_is_struct) {717if (asprintf(&newbasename, "%s_%s", basetype, m->gen_name) < 0)718errx(1, "malloc");719} else720newbasename = strdup(basetype);721722if (newbasename == NULL)723errx(1, "malloc");724725726generate_template_type(elname, &dupname, NULL,727symbol_name(newbasename, m->type),728NULL, m->type, 0, subtype_is_struct, 1);729730add_line(&template, "{ %s, offsetof(%s%s, u.%s), asn1_%s }",731m->label, isstruct ? "struct " : "",732basetype, m->gen_name,733dupname);734735free(elname);736free(newbasename);737}738739e = NULL;740if (ellipsis) {741if (asprintf(&e, "offsetof(%s%s, u.asn1_ellipsis)", isstruct ? "struct " : "", basetype) < 0 || e == NULL)742errx(1, "malloc");743}744745ASN1_TAILQ_FOREACH(q, &template, members) {746count++;747}748749fprintf(f, "static const struct asn1_template %s[] = {\n", tname);750fprintf(f, "/* 0 */ { %s, offsetof(%s%s, element), ((void *)%lu) },\n",751e ? e : "0", isstruct ? "struct " : "", basetype, (unsigned long)count);752i = 1;753ASN1_TAILQ_FOREACH(q, &template, members) {754int last = (ASN1_TAILQ_LAST(&template, templatehead) == q);755fprintf(f, "/* %lu */ %s%s\n", (unsigned long)i++, q->line, last ? "" : ",");756}757fprintf(f, "};\n");758759add_line(temp, "{ A1_OP_CHOICE, %s, %s }", poffset, tname);760761free(e);762free(tname);763break;764}765default:766abort ();767}768if (poffset)769free(poffset);770}771772static void773gen_extern_stubs(FILE *f, const char *name)774{775fprintf(f,776"static const struct asn1_type_func asn1_extern_%s = {\n"777"\t(asn1_type_encode)encode_%s,\n"778"\t(asn1_type_decode)decode_%s,\n"779"\t(asn1_type_length)length_%s,\n"780"\t(asn1_type_copy)copy_%s,\n"781"\t(asn1_type_release)free_%s,\n"782"\tsizeof(%s)\n"783"};\n",784name, name, name, name,785name, name, name);786}787788void789gen_template_import(const Symbol *s)790{791FILE *f = get_code_file();792793if (template_flag == 0)794return;795796gen_extern_stubs(f, s->gen_name);797}798799static void800generate_template_type(const char *varname,801const char **dupname,802const char *symname,803const char *basetype,804const char *name,805Type *type,806int optional, int isstruct, int need_offset)807{808struct tlist *tl;809const char *dup;810int have_ellipsis = 0;811812tl = tlist_new(varname);813814template_members(&tl->template, basetype, name, type, optional, isstruct, need_offset);815816/* if its a sequence or set type, check if there is a ellipsis */817if (type->type == TSequence || type->type == TSet) {818Member *m;819ASN1_TAILQ_FOREACH(m, type->members, members) {820if (m->ellipsis)821have_ellipsis = 1;822}823}824825if (ASN1_TAILQ_EMPTY(&tl->template) && compact_tag(type)->type != TNull)826errx(1, "Tag %s...%s with no content ?", basetype, name ? name : "");827828tlist_header(tl, "{ 0%s%s, sizeof(%s%s), ((void *)%lu) }",829(symname && preserve_type(symname)) ? "|A1_HF_PRESERVE" : "",830have_ellipsis ? "|A1_HF_ELLIPSIS" : "",831isstruct ? "struct " : "", basetype, tlist_count(tl));832833dup = tlist_find_dup(tl);834if (dup) {835if (strcmp(dup, tl->name) == 0)836errx(1, "found dup of ourself");837*dupname = dup;838} else {839*dupname = tl->name;840tlist_print(tl);841tlist_add(tl);842}843}844845846void847generate_template(const Symbol *s)848{849FILE *f = get_code_file();850const char *dupname;851852if (use_extern(s)) {853gen_extern_stubs(f, s->gen_name);854return;855}856857generate_template_type(s->gen_name, &dupname, s->name, s->gen_name, NULL, s->type, 0, 0, 1);858859fprintf(f,860"\n"861"int\n"862"decode_%s(const unsigned char *p, size_t len, %s *data, size_t *size)\n"863"{\n"864" return _asn1_decode_top(asn1_%s, 0|%s, p, len, data, size);\n"865"}\n"866"\n",867s->gen_name,868s->gen_name,869dupname,870support_ber ? "A1_PF_ALLOW_BER" : "0");871872fprintf(f,873"\n"874"int\n"875"encode_%s(unsigned char *p, size_t len, const %s *data, size_t *size)\n"876"{\n"877" return _asn1_encode(asn1_%s, p, len, data, size);\n"878"}\n"879"\n",880s->gen_name,881s->gen_name,882dupname);883884fprintf(f,885"\n"886"size_t\n"887"length_%s(const %s *data)\n"888"{\n"889" return _asn1_length(asn1_%s, data);\n"890"}\n"891"\n",892s->gen_name,893s->gen_name,894dupname);895896897fprintf(f,898"\n"899"void\n"900"free_%s(%s *data)\n"901"{\n"902" _asn1_free(asn1_%s, data);\n"903"}\n"904"\n",905s->gen_name,906s->gen_name,907dupname);908909fprintf(f,910"\n"911"int\n"912"copy_%s(const %s *from, %s *to)\n"913"{\n"914" return _asn1_copy_top(asn1_%s, from, to);\n"915"}\n"916"\n",917s->gen_name,918s->gen_name,919s->gen_name,920dupname);921}922923924