155682Smarkm/* 2233294Sstas * Copyright (c) 1997 - 2005 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 955682Smarkm * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 1655682Smarkm * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 2055682Smarkm * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "gen_locl.h" 3555682Smarkm 36233294SstasRCSID("$Id$"); 3755682Smarkm 3855682Smarkmstatic void 3955682Smarkmlength_primitive (const char *typename, 4055682Smarkm const char *name, 4155682Smarkm const char *variable) 4255682Smarkm{ 43178825Sdfr fprintf (codefile, "%s += der_length_%s(%s);\n", variable, typename, name); 4455682Smarkm} 4555682Smarkm 46233294Sstas/* XXX same as der_length_tag */ 47178825Sdfrstatic size_t 48178825Sdfrlength_tag(unsigned int tag) 4955682Smarkm{ 50178825Sdfr size_t len = 0; 51233294Sstas 52178825Sdfr if(tag <= 30) 53178825Sdfr return 1; 54178825Sdfr while(tag) { 55178825Sdfr tag /= 128; 56178825Sdfr len++; 57178825Sdfr } 58178825Sdfr return len + 1; 59178825Sdfr} 60178825Sdfr 61178825Sdfr 62178825Sdfrstatic int 63233294Sstaslength_type (const char *name, const Type *t, 64178825Sdfr const char *variable, const char *tmpstr) 65178825Sdfr{ 6672445Sassar switch (t->type) { 6772445Sassar case TType: 6855682Smarkm#if 0 6972445Sassar length_type (name, t->symbol->type); 7055682Smarkm#endif 7172445Sassar fprintf (codefile, "%s += length_%s(%s);\n", 7272445Sassar variable, t->symbol->gen_name, name); 7372445Sassar break; 7472445Sassar case TInteger: 75178825Sdfr if(t->members) { 76178825Sdfr fprintf(codefile, 77178825Sdfr "{\n" 78178825Sdfr "int enumint = *%s;\n", name); 79178825Sdfr length_primitive ("integer", "&enumint", variable); 80178825Sdfr fprintf(codefile, "}\n"); 81178825Sdfr } else if (t->range == NULL) { 82178825Sdfr length_primitive ("heim_integer", name, variable); 83178825Sdfr } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) { 84178825Sdfr length_primitive ("integer", name, variable); 85178825Sdfr } else if (t->range->min == 0 && t->range->max == UINT_MAX) { 86178825Sdfr length_primitive ("unsigned", name, variable); 87178825Sdfr } else if (t->range->min == 0 && t->range->max == INT_MAX) { 88178825Sdfr length_primitive ("unsigned", name, variable); 89178825Sdfr } else 90233294Sstas errx(1, "%s: unsupported range %d -> %d", 91178825Sdfr name, t->range->min, t->range->max); 92178825Sdfr 9372445Sassar break; 94178825Sdfr case TBoolean: 95178825Sdfr fprintf (codefile, "%s += 1;\n", variable); 9672445Sassar break; 9790926Snectar case TEnumerated : 9890926Snectar length_primitive ("enumerated", name, variable); 9990926Snectar break; 10072445Sassar case TOctetString: 10172445Sassar length_primitive ("octet_string", name, variable); 10272445Sassar break; 10372445Sassar case TBitString: { 104178825Sdfr if (ASN1_TAILQ_EMPTY(t->members)) 105178825Sdfr length_primitive("bit_string", name, variable); 106178825Sdfr else { 107178825Sdfr if (!rfc1510_bitstring) { 108178825Sdfr Member *m; 109178825Sdfr int pos = ASN1_TAILQ_LAST(t->members, memhead)->val; 110178825Sdfr 111178825Sdfr fprintf(codefile, 112178825Sdfr "do {\n"); 113178825Sdfr ASN1_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) { 114178825Sdfr while (m->val / 8 < pos / 8) { 115178825Sdfr pos -= 8; 116178825Sdfr } 117178825Sdfr fprintf (codefile, 118178825Sdfr "if((%s)->%s) { %s += %d; break; }\n", 119178825Sdfr name, m->gen_name, variable, (pos + 8) / 8); 120178825Sdfr } 121178825Sdfr fprintf(codefile, 122178825Sdfr "} while(0);\n"); 123178825Sdfr fprintf (codefile, "%s += 1;\n", variable); 124178825Sdfr } else { 125178825Sdfr fprintf (codefile, "%s += 5;\n", variable); 126178825Sdfr } 127178825Sdfr } 12872445Sassar break; 12972445Sassar } 130178825Sdfr case TSet: 131178825Sdfr case TSequence: 132178825Sdfr case TChoice: { 133178825Sdfr Member *m, *have_ellipsis = NULL; 13455682Smarkm 13572445Sassar if (t->members == NULL) 13672445Sassar break; 137233294Sstas 138178825Sdfr if(t->type == TChoice) 139178825Sdfr fprintf (codefile, "switch((%s)->element) {\n", name); 140178825Sdfr 141178825Sdfr ASN1_TAILQ_FOREACH(m, t->members, members) { 14272445Sassar char *s; 143233294Sstas 144178825Sdfr if (m->ellipsis) { 145178825Sdfr have_ellipsis = m; 146178825Sdfr continue; 147178825Sdfr } 14855682Smarkm 149178825Sdfr if(t->type == TChoice) 150178825Sdfr fprintf(codefile, "case %s:\n", m->label); 151178825Sdfr 152233294Sstas if (asprintf (&s, "%s(%s)->%s%s", 153233294Sstas m->optional ? "" : "&", name, 154233294Sstas t->type == TChoice ? "u." : "", m->gen_name) < 0 || s == NULL) 155178825Sdfr errx(1, "malloc"); 15672445Sassar if (m->optional) 15772445Sassar fprintf (codefile, "if(%s)", s); 158178825Sdfr else if(m->defval) 159178825Sdfr gen_compare_defval(s + 1, m->defval); 16072445Sassar fprintf (codefile, "{\n" 161178825Sdfr "size_t %s_oldret = %s;\n" 162178825Sdfr "%s = 0;\n", tmpstr, variable, variable); 163178825Sdfr length_type (s, m->type, "ret", m->gen_name); 164178825Sdfr fprintf (codefile, "ret += %s_oldret;\n", tmpstr); 16572445Sassar fprintf (codefile, "}\n"); 16672445Sassar free (s); 167178825Sdfr if(t->type == TChoice) 168178825Sdfr fprintf(codefile, "break;\n"); 16972445Sassar } 170178825Sdfr if(t->type == TChoice) { 171178825Sdfr if (have_ellipsis) 172178825Sdfr fprintf(codefile, 173178825Sdfr "case %s:\n" 174178825Sdfr "ret += (%s)->u.%s.length;\n" 175178825Sdfr "break;\n", 176178825Sdfr have_ellipsis->label, 177178825Sdfr name, 178178825Sdfr have_ellipsis->gen_name); 179178825Sdfr fprintf (codefile, "}\n"); /* switch */ 180178825Sdfr } 18172445Sassar break; 18272445Sassar } 183178825Sdfr case TSetOf: 18472445Sassar case TSequenceOf: { 185233294Sstas char *n = NULL; 186233294Sstas char *sname = NULL; 18755682Smarkm 18872445Sassar fprintf (codefile, 18972445Sassar "{\n" 190233294Sstas "size_t %s_oldret = %s;\n" 19172445Sassar "int i;\n" 19272445Sassar "%s = 0;\n", 193178825Sdfr tmpstr, variable, variable); 19455682Smarkm 19572445Sassar fprintf (codefile, "for(i = (%s)->len - 1; i >= 0; --i){\n", name); 196233294Sstas fprintf (codefile, "size_t %s_for_oldret = %s;\n" 197178825Sdfr "%s = 0;\n", tmpstr, variable, variable); 198233294Sstas if (asprintf (&n, "&(%s)->val[i]", name) < 0 || n == NULL) 199178825Sdfr errx(1, "malloc"); 200233294Sstas if (asprintf (&sname, "%s_S_Of", tmpstr) < 0 || sname == NULL) 201178825Sdfr errx(1, "malloc"); 202178825Sdfr length_type(n, t->subtype, variable, sname); 203178825Sdfr fprintf (codefile, "%s += %s_for_oldret;\n", 204178825Sdfr variable, tmpstr); 20572445Sassar fprintf (codefile, "}\n"); 20655682Smarkm 20772445Sassar fprintf (codefile, 208178825Sdfr "%s += %s_oldret;\n" 209178825Sdfr "}\n", variable, tmpstr); 21072445Sassar free(n); 211178825Sdfr free(sname); 21272445Sassar break; 21372445Sassar } 21472445Sassar case TGeneralizedTime: 21572445Sassar length_primitive ("generalized_time", name, variable); 21672445Sassar break; 21772445Sassar case TGeneralString: 21872445Sassar length_primitive ("general_string", name, variable); 21972445Sassar break; 220233294Sstas case TTeletexString: 221233294Sstas length_primitive ("general_string", name, variable); 222233294Sstas break; 223178825Sdfr case TUTCTime: 224178825Sdfr length_primitive ("utctime", name, variable); 22572445Sassar break; 226178825Sdfr case TUTF8String: 227178825Sdfr length_primitive ("utf8string", name, variable); 228178825Sdfr break; 229178825Sdfr case TPrintableString: 230178825Sdfr length_primitive ("printable_string", name, variable); 231178825Sdfr break; 232178825Sdfr case TIA5String: 233178825Sdfr length_primitive ("ia5_string", name, variable); 234178825Sdfr break; 235178825Sdfr case TBMPString: 236178825Sdfr length_primitive ("bmp_string", name, variable); 237178825Sdfr break; 238178825Sdfr case TUniversalString: 239178825Sdfr length_primitive ("universal_string", name, variable); 240178825Sdfr break; 241178825Sdfr case TVisibleString: 242178825Sdfr length_primitive ("visible_string", name, variable); 243178825Sdfr break; 244178825Sdfr case TNull: 245178825Sdfr fprintf (codefile, "/* NULL */\n"); 246178825Sdfr break; 247178825Sdfr case TTag:{ 248233294Sstas char *tname = NULL; 249233294Sstas if (asprintf(&tname, "%s_tag", tmpstr) < 0 || tname == NULL) 250178825Sdfr errx(1, "malloc"); 251178825Sdfr length_type (name, t->subtype, variable, tname); 252233294Sstas fprintf (codefile, "ret += %lu + der_length_len (ret);\n", 253178825Sdfr (unsigned long)length_tag(t->tag.tagvalue)); 254178825Sdfr free(tname); 255178825Sdfr break; 256178825Sdfr } 257178825Sdfr case TOID: 258178825Sdfr length_primitive ("oid", name, variable); 259178825Sdfr break; 26072445Sassar default : 26172445Sassar abort (); 26272445Sassar } 263178825Sdfr return 0; 26455682Smarkm} 26555682Smarkm 26655682Smarkmvoid 26755682Smarkmgenerate_type_length (const Symbol *s) 26855682Smarkm{ 269178825Sdfr fprintf (codefile, 270233294Sstas "size_t ASN1CALL\n" 271178825Sdfr "length_%s(const %s *data)\n" 272178825Sdfr "{\n" 273178825Sdfr "size_t ret = 0;\n", 274178825Sdfr s->gen_name, s->gen_name); 275233294Sstas 276178825Sdfr length_type ("data", s->type, "ret", "Top"); 277178825Sdfr fprintf (codefile, "return ret;\n}\n\n"); 27855682Smarkm} 27955682Smarkm 280