1194955Strasz/* 2194955Strasz * Copyright (c) 1997 - 2005 Kungliga Tekniska H��gskolan 3194955Strasz * (Royal Institute of Technology, Stockholm, Sweden). 4194955Strasz * All rights reserved. 5194955Strasz * 6194955Strasz * Redistribution and use in source and binary forms, with or without 7194955Strasz * modification, are permitted provided that the following conditions 8194955Strasz * are met: 9194955Strasz * 10194955Strasz * 1. Redistributions of source code must retain the above copyright 11194955Strasz * notice, this list of conditions and the following disclaimer. 12194955Strasz * 13194955Strasz * 2. Redistributions in binary form must reproduce the above copyright 14194955Strasz * notice, this list of conditions and the following disclaimer in the 15194955Strasz * documentation and/or other materials provided with the distribution. 16194955Strasz * 17194955Strasz * 3. Neither the name of the Institute nor the names of its contributors 18194955Strasz * may be used to endorse or promote products derived from this software 19194955Strasz * without specific prior written permission. 20194955Strasz * 21194955Strasz * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22194955Strasz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23194955Strasz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24194955Strasz * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25194955Strasz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26194955Strasz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27194955Strasz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28194955Strasz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29194955Strasz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30194955Strasz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31194955Strasz * SUCH DAMAGE. 32194955Strasz */ 33194955Strasz 34194955Strasz#include "gen_locl.h" 35194955Strasz 36194955StraszRCSID("$Id$"); 37194955Strasz 38194955Straszstatic void 39194955Straszlength_primitive (const char *typename, 40194955Strasz const char *name, 41194955Strasz const char *variable) 42194955Strasz{ 43194955Strasz fprintf (codefile, "%s += der_length_%s(%s);\n", variable, typename, name); 44194955Strasz} 45194955Strasz 46194955Strasz/* XXX same as der_length_tag */ 47194955Straszstatic size_t 48194955Straszlength_tag(unsigned int tag) 49194955Strasz{ 50194955Strasz size_t len = 0; 51194955Strasz 52194955Strasz if(tag <= 30) 53208811Strasz return 1; 54194955Strasz while(tag) { 55194955Strasz tag /= 128; 56194955Strasz len++; 57194955Strasz } 58194955Strasz return len + 1; 59194955Strasz} 60194955Strasz 61194955Strasz 62194955Straszstatic int 63194955Straszlength_type (const char *name, const Type *t, 64194955Strasz const char *variable, const char *tmpstr) 65208811Strasz{ 66194955Strasz switch (t->type) { 67194955Strasz case TType: 68194955Strasz#if 0 69194955Strasz length_type (name, t->symbol->type); 70194955Strasz#endif 71194955Strasz fprintf (codefile, "%s += length_%s(%s);\n", 72194955Strasz variable, t->symbol->gen_name, name); 73194955Strasz break; 74194955Strasz case TInteger: 75194955Strasz if(t->members) { 76194955Strasz fprintf(codefile, 77194955Strasz "{\n" 78194955Strasz "int enumint = *%s;\n", name); 79194955Strasz length_primitive ("integer", "&enumint", variable); 80194955Strasz fprintf(codefile, "}\n"); 81194955Strasz } else if (t->range == NULL) { 82194955Strasz length_primitive ("heim_integer", name, variable); 83194955Strasz } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) { 84208811Strasz length_primitive ("integer", name, variable); 85194955Strasz } else if (t->range->min == 0 && t->range->max == UINT_MAX) { 86194955Strasz length_primitive ("unsigned", name, variable); 87194955Strasz } else if (t->range->min == 0 && t->range->max == INT_MAX) { 88194955Strasz length_primitive ("unsigned", name, variable); 89194955Strasz } else 90194955Strasz errx(1, "%s: unsupported range %d -> %d", 91194955Strasz name, t->range->min, t->range->max); 92194955Strasz 93194955Strasz break; 94194955Strasz case TBoolean: 95194955Strasz fprintf (codefile, "%s += 1;\n", variable); 96194955Strasz break; 97194955Strasz case TEnumerated : 98194955Strasz length_primitive ("enumerated", name, variable); 99194955Strasz break; 100194955Strasz case TOctetString: 101194955Strasz length_primitive ("octet_string", name, variable); 102194955Strasz break; 103194955Strasz case TBitString: { 104194955Strasz if (ASN1_TAILQ_EMPTY(t->members)) 105194955Strasz length_primitive("bit_string", name, variable); 106194955Strasz else { 107194955Strasz if (!rfc1510_bitstring) { 108194955Strasz Member *m; 109194955Strasz int pos = ASN1_TAILQ_LAST(t->members, memhead)->val; 110194955Strasz 111194955Strasz fprintf(codefile, 112194955Strasz "do {\n"); 113194955Strasz ASN1_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) { 114194955Strasz while (m->val / 8 < pos / 8) { 115194955Strasz pos -= 8; 116194955Strasz } 117194955Strasz fprintf (codefile, 118194955Strasz "if((%s)->%s) { %s += %d; break; }\n", 119194955Strasz name, m->gen_name, variable, (pos + 8) / 8); 120194955Strasz } 121194955Strasz fprintf(codefile, 122194955Strasz "} while(0);\n"); 123194955Strasz fprintf (codefile, "%s += 1;\n", variable); 124194955Strasz } else { 125194955Strasz fprintf (codefile, "%s += 5;\n", variable); 126194955Strasz } 127194955Strasz } 128194955Strasz break; 129194955Strasz } 130194955Strasz case TSet: 131194955Strasz case TSequence: 132194955Strasz case TChoice: { 133194955Strasz Member *m, *have_ellipsis = NULL; 134194955Strasz 135194955Strasz if (t->members == NULL) 136194955Strasz break; 137194955Strasz 138194955Strasz if(t->type == TChoice) 139194955Strasz fprintf (codefile, "switch((%s)->element) {\n", name); 140194955Strasz 141194955Strasz ASN1_TAILQ_FOREACH(m, t->members, members) { 142194955Strasz char *s; 143194955Strasz 144208811Strasz if (m->ellipsis) { 145194955Strasz have_ellipsis = m; 146194955Strasz continue; 147194955Strasz } 148194955Strasz 149194955Strasz if(t->type == TChoice) 150194955Strasz fprintf(codefile, "case %s:\n", m->label); 151194955Strasz 152194955Strasz if (asprintf (&s, "%s(%s)->%s%s", 153194955Strasz m->optional ? "" : "&", name, 154194955Strasz t->type == TChoice ? "u." : "", m->gen_name) < 0 || s == NULL) 155194955Strasz errx(1, "malloc"); 156194955Strasz if (m->optional) 157194955Strasz fprintf (codefile, "if(%s)", s); 158208811Strasz else if(m->defval) 159194955Strasz gen_compare_defval(s + 1, m->defval); 160194955Strasz fprintf (codefile, "{\n" 161194955Strasz "size_t %s_oldret = %s;\n" 162194955Strasz "%s = 0;\n", tmpstr, variable, variable); 163194955Strasz length_type (s, m->type, "ret", m->gen_name); 164194955Strasz fprintf (codefile, "ret += %s_oldret;\n", tmpstr); 165194955Strasz fprintf (codefile, "}\n"); 166194955Strasz free (s); 167194955Strasz if(t->type == TChoice) 168194955Strasz fprintf(codefile, "break;\n"); 169194955Strasz } 170205796Strasz if(t->type == TChoice) { 171194955Strasz if (have_ellipsis) 172194955Strasz fprintf(codefile, 173194955Strasz "case %s:\n" 174194955Strasz "ret += (%s)->u.%s.length;\n" 175194955Strasz "break;\n", 176194955Strasz have_ellipsis->label, 177194955Strasz name, 178194955Strasz have_ellipsis->gen_name); 179194955Strasz fprintf (codefile, "}\n"); /* switch */ 180194955Strasz } 181194955Strasz break; 182194955Strasz } 183194955Strasz case TSetOf: 184194955Strasz case TSequenceOf: { 185194955Strasz char *n = NULL; 186194955Strasz char *sname = NULL; 187194955Strasz 188194955Strasz fprintf (codefile, 189194955Strasz "{\n" 190194955Strasz "size_t %s_oldret = %s;\n" 191205796Strasz "int i;\n" 192205796Strasz "%s = 0;\n", 193205796Strasz tmpstr, variable, variable); 194194955Strasz 195194955Strasz fprintf (codefile, "for(i = (%s)->len - 1; i >= 0; --i){\n", name); 196194955Strasz fprintf (codefile, "size_t %s_for_oldret = %s;\n" 197194955Strasz "%s = 0;\n", tmpstr, variable, variable); 198194955Strasz if (asprintf (&n, "&(%s)->val[i]", name) < 0 || n == NULL) 199194955Strasz errx(1, "malloc"); 200194955Strasz if (asprintf (&sname, "%s_S_Of", tmpstr) < 0 || sname == NULL) 201194955Strasz errx(1, "malloc"); 202194955Strasz length_type(n, t->subtype, variable, sname); 203194955Strasz fprintf (codefile, "%s += %s_for_oldret;\n", 204194955Strasz variable, tmpstr); 205194955Strasz fprintf (codefile, "}\n"); 206194955Strasz 207194955Strasz fprintf (codefile, 208194955Strasz "%s += %s_oldret;\n" 209194955Strasz "}\n", variable, tmpstr); 210194955Strasz free(n); 211194955Strasz free(sname); 212194955Strasz break; 213194955Strasz } 214194955Strasz case TGeneralizedTime: 215194955Strasz length_primitive ("generalized_time", name, variable); 216194955Strasz break; 217194955Strasz case TGeneralString: 218194955Strasz length_primitive ("general_string", name, variable); 219194955Strasz break; 220194955Strasz case TTeletexString: 221194955Strasz length_primitive ("general_string", name, variable); 222194955Strasz break; 223194955Strasz case TUTCTime: 224194955Strasz length_primitive ("utctime", name, variable); 225194955Strasz break; 226194955Strasz case TUTF8String: 227194955Strasz length_primitive ("utf8string", name, variable); 228194955Strasz break; 229194955Strasz case TPrintableString: 230194955Strasz length_primitive ("printable_string", name, variable); 231194955Strasz break; 232194955Strasz case TIA5String: 233194955Strasz length_primitive ("ia5_string", name, variable); 234194955Strasz break; 235194955Strasz case TBMPString: 236194955Strasz length_primitive ("bmp_string", name, variable); 237194955Strasz break; 238194955Strasz case TUniversalString: 239194955Strasz length_primitive ("universal_string", name, variable); 240194955Strasz break; 241194955Strasz case TVisibleString: 242194955Strasz length_primitive ("visible_string", name, variable); 243194955Strasz break; 244194955Strasz case TNull: 245194955Strasz fprintf (codefile, "/* NULL */\n"); 246194955Strasz break; 247194955Strasz case TTag:{ 248194955Strasz char *tname = NULL; 249208786Strasz if (asprintf(&tname, "%s_tag", tmpstr) < 0 || tname == NULL) 250194955Strasz errx(1, "malloc"); 251194955Strasz length_type (name, t->subtype, variable, tname); 252194955Strasz fprintf (codefile, "ret += %lu + der_length_len (ret);\n", 253194955Strasz (unsigned long)length_tag(t->tag.tagvalue)); 254194955Strasz free(tname); 255194955Strasz break; 256194955Strasz } 257194955Strasz case TOID: 258194955Strasz length_primitive ("oid", name, variable); 259194955Strasz break; 260194955Strasz default : 261194955Strasz abort (); 262194955Strasz } 263194955Strasz return 0; 264194955Strasz} 265 266void 267generate_type_length (const Symbol *s) 268{ 269 fprintf (codefile, 270 "size_t ASN1CALL\n" 271 "length_%s(const %s *data)\n" 272 "{\n" 273 "size_t ret = 0;\n", 274 s->gen_name, s->gen_name); 275 276 length_type ("data", s->type, "ret", "Top"); 277 fprintf (codefile, "return ret;\n}\n\n"); 278} 279 280