gen_length.c revision 178826
1227896Sjkim/* 2227896Sjkim * Copyright (c) 1997 - 2005 Kungliga Tekniska H�gskolan 3227896Sjkim * (Royal Institute of Technology, Stockholm, Sweden). 4227896Sjkim * All rights reserved. 5227896Sjkim * 6227896Sjkim * Redistribution and use in source and binary forms, with or without 7227896Sjkim * modification, are permitted provided that the following conditions 8298714Sjkim * are met: 9227896Sjkim * 10227896Sjkim * 1. Redistributions of source code must retain the above copyright 11227896Sjkim * notice, this list of conditions and the following disclaimer. 12227896Sjkim * 13227896Sjkim * 2. Redistributions in binary form must reproduce the above copyright 14227896Sjkim * notice, this list of conditions and the following disclaimer in the 15227896Sjkim * documentation and/or other materials provided with the distribution. 16227896Sjkim * 17227896Sjkim * 3. Neither the name of the Institute nor the names of its contributors 18227896Sjkim * may be used to endorse or promote products derived from this software 19227896Sjkim * without specific prior written permission. 20227896Sjkim * 21227896Sjkim * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22227896Sjkim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23227896Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24227896Sjkim * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25227896Sjkim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26227896Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27227896Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28227896Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29227896Sjkim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30227896Sjkim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31227896Sjkim * SUCH DAMAGE. 32227896Sjkim */ 33227896Sjkim 34227896Sjkim#include "gen_locl.h" 35227896Sjkim 36227896SjkimRCSID("$Id: gen_length.c 21503 2007-07-12 11:57:19Z lha $"); 37227896Sjkim 38227896Sjkimstatic void 39227896Sjkimlength_primitive (const char *typename, 40227896Sjkim const char *name, 41227896Sjkim const char *variable) 42227896Sjkim{ 43227896Sjkim fprintf (codefile, "%s += der_length_%s(%s);\n", variable, typename, name); 44228110Sjkim} 45228110Sjkim 46228110Sjkimstatic size_t 47227896Sjkimlength_tag(unsigned int tag) 48227896Sjkim{ 49227896Sjkim size_t len = 0; 50227896Sjkim 51227896Sjkim if(tag <= 30) 52227896Sjkim return 1; 53227896Sjkim while(tag) { 54227896Sjkim tag /= 128; 55227896Sjkim len++; 56227896Sjkim } 57227896Sjkim return len + 1; 58227896Sjkim} 59227896Sjkim 60227896Sjkim 61227896Sjkimstatic int 62227896Sjkimlength_type (const char *name, const Type *t, 63227896Sjkim const char *variable, const char *tmpstr) 64227896Sjkim{ 65227896Sjkim switch (t->type) { 66227896Sjkim case TType: 67227896Sjkim#if 0 68227896Sjkim length_type (name, t->symbol->type); 69227896Sjkim#endif 70227896Sjkim fprintf (codefile, "%s += length_%s(%s);\n", 71227896Sjkim variable, t->symbol->gen_name, name); 72227896Sjkim break; 73227896Sjkim case TInteger: 74227896Sjkim if(t->members) { 75227896Sjkim fprintf(codefile, 76227896Sjkim "{\n" 77227896Sjkim "int enumint = *%s;\n", name); 78227896Sjkim length_primitive ("integer", "&enumint", variable); 79227896Sjkim fprintf(codefile, "}\n"); 80227896Sjkim } else if (t->range == NULL) { 81227896Sjkim length_primitive ("heim_integer", name, variable); 82227896Sjkim } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) { 83227896Sjkim length_primitive ("integer", name, variable); 84227896Sjkim } else if (t->range->min == 0 && t->range->max == UINT_MAX) { 85227896Sjkim length_primitive ("unsigned", name, variable); 86227896Sjkim } else if (t->range->min == 0 && t->range->max == INT_MAX) { 87227896Sjkim length_primitive ("unsigned", name, variable); 88227896Sjkim } else 89227896Sjkim errx(1, "%s: unsupported range %d -> %d", 90227896Sjkim name, t->range->min, t->range->max); 91227896Sjkim 92227896Sjkim break; 93227896Sjkim case TBoolean: 94227896Sjkim fprintf (codefile, "%s += 1;\n", variable); 95227896Sjkim break; 96227896Sjkim case TEnumerated : 97227896Sjkim length_primitive ("enumerated", name, variable); 98227896Sjkim break; 99227896Sjkim case TOctetString: 100227896Sjkim length_primitive ("octet_string", name, variable); 101298714Sjkim break; 102298714Sjkim case TBitString: { 103227896Sjkim if (ASN1_TAILQ_EMPTY(t->members)) 104227896Sjkim length_primitive("bit_string", name, variable); 105227896Sjkim else { 106227896Sjkim if (!rfc1510_bitstring) { 107227896Sjkim Member *m; 108227896Sjkim int pos = ASN1_TAILQ_LAST(t->members, memhead)->val; 109227896Sjkim 110227896Sjkim fprintf(codefile, 111227896Sjkim "do {\n"); 112227896Sjkim ASN1_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) { 113227896Sjkim while (m->val / 8 < pos / 8) { 114227896Sjkim pos -= 8; 115227896Sjkim } 116227896Sjkim fprintf (codefile, 117227896Sjkim "if((%s)->%s) { %s += %d; break; }\n", 118227896Sjkim name, m->gen_name, variable, (pos + 8) / 8); 119227896Sjkim } 120227896Sjkim fprintf(codefile, 121227896Sjkim "} while(0);\n"); 122227896Sjkim fprintf (codefile, "%s += 1;\n", variable); 123227896Sjkim } else { 124227896Sjkim fprintf (codefile, "%s += 5;\n", variable); 125227896Sjkim } 126227896Sjkim } 127227896Sjkim break; 128227896Sjkim } 129227896Sjkim case TSet: 130227896Sjkim case TSequence: 131227896Sjkim case TChoice: { 132227896Sjkim Member *m, *have_ellipsis = NULL; 133227896Sjkim 134227896Sjkim if (t->members == NULL) 135227896Sjkim break; 136227896Sjkim 137227896Sjkim if(t->type == TChoice) 138227896Sjkim fprintf (codefile, "switch((%s)->element) {\n", name); 139227896Sjkim 140227896Sjkim ASN1_TAILQ_FOREACH(m, t->members, members) { 141227896Sjkim char *s; 142227896Sjkim 143227896Sjkim if (m->ellipsis) { 144227896Sjkim have_ellipsis = m; 145227896Sjkim continue; 146227896Sjkim } 147227896Sjkim 148227896Sjkim if(t->type == TChoice) 149227896Sjkim fprintf(codefile, "case %s:\n", m->label); 150227896Sjkim 151227896Sjkim asprintf (&s, "%s(%s)->%s%s", 152227896Sjkim m->optional ? "" : "&", name, 153227896Sjkim t->type == TChoice ? "u." : "", m->gen_name); 154227896Sjkim if (s == NULL) 155227896Sjkim errx(1, "malloc"); 156227896Sjkim if (m->optional) 157227896Sjkim fprintf (codefile, "if(%s)", s); 158227896Sjkim else if(m->defval) 159227896Sjkim gen_compare_defval(s + 1, m->defval); 160227896Sjkim fprintf (codefile, "{\n" 161227896Sjkim "size_t %s_oldret = %s;\n" 162227896Sjkim "%s = 0;\n", tmpstr, variable, variable); 163227896Sjkim length_type (s, m->type, "ret", m->gen_name); 164227896Sjkim fprintf (codefile, "ret += %s_oldret;\n", tmpstr); 165227896Sjkim fprintf (codefile, "}\n"); 166227896Sjkim free (s); 167227896Sjkim if(t->type == TChoice) 168227896Sjkim fprintf(codefile, "break;\n"); 169227896Sjkim } 170227896Sjkim if(t->type == TChoice) { 171227896Sjkim if (have_ellipsis) 172227896Sjkim fprintf(codefile, 173227896Sjkim "case %s:\n" 174227896Sjkim "ret += (%s)->u.%s.length;\n" 175227896Sjkim "break;\n", 176227896Sjkim have_ellipsis->label, 177227896Sjkim name, 178227896Sjkim have_ellipsis->gen_name); 179227896Sjkim fprintf (codefile, "}\n"); /* switch */ 180227896Sjkim } 181227896Sjkim break; 182227896Sjkim } 183227896Sjkim case TSetOf: 184227896Sjkim case TSequenceOf: { 185227896Sjkim char *n; 186227896Sjkim char *sname; 187227896Sjkim 188227896Sjkim fprintf (codefile, 189227896Sjkim "{\n" 190227896Sjkim "int %s_oldret = %s;\n" 191227896Sjkim "int i;\n" 192227896Sjkim "%s = 0;\n", 193227896Sjkim tmpstr, variable, variable); 194227896Sjkim 195227896Sjkim fprintf (codefile, "for(i = (%s)->len - 1; i >= 0; --i){\n", name); 196227896Sjkim fprintf (codefile, "int %s_for_oldret = %s;\n" 197227896Sjkim "%s = 0;\n", tmpstr, variable, variable); 198227896Sjkim asprintf (&n, "&(%s)->val[i]", name); 199227896Sjkim if (n == NULL) 200227896Sjkim errx(1, "malloc"); 201227896Sjkim asprintf (&sname, "%s_S_Of", tmpstr); 202227896Sjkim if (sname == NULL) 203227896Sjkim errx(1, "malloc"); 204227896Sjkim length_type(n, t->subtype, variable, sname); 205227896Sjkim fprintf (codefile, "%s += %s_for_oldret;\n", 206227896Sjkim variable, tmpstr); 207227896Sjkim fprintf (codefile, "}\n"); 208227896Sjkim 209227896Sjkim fprintf (codefile, 210227896Sjkim "%s += %s_oldret;\n" 211227896Sjkim "}\n", variable, tmpstr); 212 free(n); 213 free(sname); 214 break; 215 } 216 case TGeneralizedTime: 217 length_primitive ("generalized_time", name, variable); 218 break; 219 case TGeneralString: 220 length_primitive ("general_string", name, variable); 221 break; 222 case TUTCTime: 223 length_primitive ("utctime", name, variable); 224 break; 225 case TUTF8String: 226 length_primitive ("utf8string", name, variable); 227 break; 228 case TPrintableString: 229 length_primitive ("printable_string", name, variable); 230 break; 231 case TIA5String: 232 length_primitive ("ia5_string", name, variable); 233 break; 234 case TBMPString: 235 length_primitive ("bmp_string", name, variable); 236 break; 237 case TUniversalString: 238 length_primitive ("universal_string", name, variable); 239 break; 240 case TVisibleString: 241 length_primitive ("visible_string", name, variable); 242 break; 243 case TNull: 244 fprintf (codefile, "/* NULL */\n"); 245 break; 246 case TTag:{ 247 char *tname; 248 asprintf(&tname, "%s_tag", tmpstr); 249 if (tname == NULL) 250 errx(1, "malloc"); 251 length_type (name, t->subtype, variable, tname); 252 fprintf (codefile, "ret += %lu + der_length_len (ret);\n", 253 (unsigned long)length_tag(t->tag.tagvalue)); 254 free(tname); 255 break; 256 } 257 case TOID: 258 length_primitive ("oid", name, variable); 259 break; 260 default : 261 abort (); 262 } 263 return 0; 264} 265 266void 267generate_type_length (const Symbol *s) 268{ 269 fprintf (headerfile, 270 "size_t length_%s(const %s *);\n", 271 s->gen_name, s->gen_name); 272 273 fprintf (codefile, 274 "size_t\n" 275 "length_%s(const %s *data)\n" 276 "{\n" 277 "size_t ret = 0;\n", 278 s->gen_name, s->gen_name); 279 280 length_type ("data", s->type, "ret", "Top"); 281 fprintf (codefile, "return ret;\n}\n\n"); 282} 283 284