gen_length.c revision 178825
1256904Sray/*
2256904Sray * Copyright (c) 1997 - 2005 Kungliga Tekniska H�gskolan
3256904Sray * (Royal Institute of Technology, Stockholm, Sweden).
4256904Sray * All rights reserved.
5256904Sray *
6256904Sray * Redistribution and use in source and binary forms, with or without
7256904Sray * modification, are permitted provided that the following conditions
8256904Sray * are met:
9256904Sray *
10256904Sray * 1. Redistributions of source code must retain the above copyright
11256904Sray *    notice, this list of conditions and the following disclaimer.
12256904Sray *
13256904Sray * 2. Redistributions in binary form must reproduce the above copyright
14256904Sray *    notice, this list of conditions and the following disclaimer in the
15256904Sray *    documentation and/or other materials provided with the distribution.
16256904Sray *
17256904Sray * 3. Neither the name of the Institute nor the names of its contributors
18256904Sray *    may be used to endorse or promote products derived from this software
19256904Sray *    without specific prior written permission.
20256904Sray *
21256904Sray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22256904Sray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23256904Sray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24256904Sray * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25256904Sray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26256904Sray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27256904Sray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28256904Sray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29256904Sray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30256904Sray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31256904Sray * SUCH DAMAGE.
32256904Sray */
33256904Sray
34256904Sray#include "gen_locl.h"
35256904Sray
36256904SrayRCSID("$Id: gen_length.c 21503 2007-07-12 11:57:19Z lha $");
37256904Sray
38256904Sraystatic void
39256904Sraylength_primitive (const char *typename,
40256904Sray		  const char *name,
41256904Sray		  const char *variable)
42256904Sray{
43256904Sray    fprintf (codefile, "%s += der_length_%s(%s);\n", variable, typename, name);
44256904Sray}
45256904Sray
46256904Sraystatic size_t
47256904Sraylength_tag(unsigned int tag)
48256904Sray{
49256904Sray    size_t len = 0;
50256904Sray
51256904Sray    if(tag <= 30)
52256904Sray	return 1;
53256904Sray    while(tag) {
54256904Sray	tag /= 128;
55256904Sray	len++;
56256904Sray    }
57256904Sray    return len + 1;
58256904Sray}
59256904Sray
60256904Sray
61256904Sraystatic int
62256904Sraylength_type (const char *name, const Type *t,
63256904Sray	     const char *variable, const char *tmpstr)
64256904Sray{
65256904Sray    switch (t->type) {
66256904Sray    case TType:
67256904Sray#if 0
68256904Sray	length_type (name, t->symbol->type);
69256904Sray#endif
70256904Sray	fprintf (codefile, "%s += length_%s(%s);\n",
71256904Sray		 variable, t->symbol->gen_name, name);
72256904Sray	break;
73256904Sray    case TInteger:
74256904Sray	if(t->members) {
75256904Sray	    fprintf(codefile,
76256904Sray		    "{\n"
77256904Sray		    "int enumint = *%s;\n", name);
78256904Sray	    length_primitive ("integer", "&enumint", variable);
79256904Sray	    fprintf(codefile, "}\n");
80256904Sray	} else if (t->range == NULL) {
81256904Sray	    length_primitive ("heim_integer", name, variable);
82256904Sray	} else if (t->range->min == INT_MIN && t->range->max == INT_MAX) {
83256904Sray	    length_primitive ("integer", name, variable);
84256904Sray	} else if (t->range->min == 0 && t->range->max == UINT_MAX) {
85256904Sray	    length_primitive ("unsigned", name, variable);
86256904Sray	} else if (t->range->min == 0 && t->range->max == INT_MAX) {
87256904Sray	    length_primitive ("unsigned", name, variable);
88256904Sray	} else
89256904Sray	    errx(1, "%s: unsupported range %d -> %d",
90256904Sray		 name, t->range->min, t->range->max);
91256904Sray
92256904Sray	break;
93257013Sray    case TBoolean:
94257013Sray	fprintf (codefile, "%s += 1;\n", variable);
95256904Sray	break;
96256904Sray    case TEnumerated :
97256904Sray	length_primitive ("enumerated", name, variable);
98256904Sray	break;
99256904Sray    case TOctetString:
100256904Sray	length_primitive ("octet_string", name, variable);
101256904Sray	break;
102256904Sray    case TBitString: {
103256904Sray	if (ASN1_TAILQ_EMPTY(t->members))
104256904Sray	    length_primitive("bit_string", name, variable);
105256904Sray	else {
106256904Sray	    if (!rfc1510_bitstring) {
107256904Sray		Member *m;
108256904Sray		int pos = ASN1_TAILQ_LAST(t->members, memhead)->val;
109256904Sray
110256904Sray		fprintf(codefile,
111256904Sray			"do {\n");
112256904Sray		ASN1_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) {
113256904Sray		    while (m->val / 8 < pos / 8) {
114256904Sray			pos -= 8;
115256904Sray		    }
116256904Sray		    fprintf (codefile,
117256904Sray			     "if((%s)->%s) { %s += %d; break; }\n",
118256904Sray			     name, m->gen_name, variable, (pos + 8) / 8);
119256904Sray		}
120256904Sray		fprintf(codefile,
121256904Sray			"} while(0);\n");
122256904Sray		fprintf (codefile, "%s += 1;\n", variable);
123256904Sray	    } else {
124256904Sray		fprintf (codefile, "%s += 5;\n", variable);
125256904Sray	    }
126256904Sray	}
127256904Sray	break;
128256904Sray    }
129256904Sray    case TSet:
130256904Sray    case TSequence:
131256904Sray    case TChoice: {
132256904Sray	Member *m, *have_ellipsis = NULL;
133256904Sray
134256904Sray	if (t->members == NULL)
135256904Sray	    break;
136256904Sray
137256904Sray	if(t->type == TChoice)
138256904Sray	    fprintf (codefile, "switch((%s)->element) {\n", name);
139256904Sray
140256904Sray	ASN1_TAILQ_FOREACH(m, t->members, members) {
141256904Sray	    char *s;
142256904Sray
143256904Sray	    if (m->ellipsis) {
144256904Sray		have_ellipsis = m;
145256904Sray		continue;
146256904Sray	    }
147256904Sray
148256904Sray	    if(t->type == TChoice)
149256904Sray		fprintf(codefile, "case %s:\n", m->label);
150256904Sray
151256904Sray	    asprintf (&s, "%s(%s)->%s%s",
152256904Sray		      m->optional ? "" : "&", name,
153256904Sray		      t->type == TChoice ? "u." : "", m->gen_name);
154256904Sray	    if (s == NULL)
155256904Sray		errx(1, "malloc");
156256904Sray	    if (m->optional)
157256904Sray		fprintf (codefile, "if(%s)", s);
158256904Sray	    else if(m->defval)
159256904Sray		gen_compare_defval(s + 1, m->defval);
160256904Sray	    fprintf (codefile, "{\n"
161256904Sray		     "size_t %s_oldret = %s;\n"
162256904Sray		     "%s = 0;\n", tmpstr, variable, variable);
163256904Sray	    length_type (s, m->type, "ret", m->gen_name);
164256904Sray	    fprintf (codefile, "ret += %s_oldret;\n", tmpstr);
165256904Sray	    fprintf (codefile, "}\n");
166256904Sray	    free (s);
167256904Sray	    if(t->type == TChoice)
168256904Sray		fprintf(codefile, "break;\n");
169256904Sray	}
170256904Sray	if(t->type == TChoice) {
171256904Sray	    if (have_ellipsis)
172256904Sray		fprintf(codefile,
173256904Sray			"case %s:\n"
174256904Sray			"ret += (%s)->u.%s.length;\n"
175256904Sray			"break;\n",
176256904Sray			have_ellipsis->label,
177256904Sray			name,
178256904Sray			have_ellipsis->gen_name);
179256904Sray	    fprintf (codefile, "}\n"); /* switch */
180256904Sray	}
181256904Sray	break;
182256904Sray    }
183256904Sray    case TSetOf:
184256904Sray    case TSequenceOf: {
185256904Sray	char *n;
186256904Sray	char *sname;
187256904Sray
188256904Sray	fprintf (codefile,
189256904Sray		 "{\n"
190256904Sray		 "int %s_oldret = %s;\n"
191256904Sray		 "int i;\n"
192256904Sray		 "%s = 0;\n",
193256904Sray		 tmpstr, variable, variable);
194256904Sray
195256904Sray	fprintf (codefile, "for(i = (%s)->len - 1; i >= 0; --i){\n", name);
196256904Sray	fprintf (codefile, "int %s_for_oldret = %s;\n"
197256904Sray		 "%s = 0;\n", tmpstr, variable, variable);
198256904Sray	asprintf (&n, "&(%s)->val[i]", name);
199256904Sray	if (n == NULL)
200256904Sray	    errx(1, "malloc");
201256904Sray	asprintf (&sname, "%s_S_Of", tmpstr);
202256904Sray	if (sname == NULL)
203256904Sray	    errx(1, "malloc");
204256904Sray	length_type(n, t->subtype, variable, sname);
205256904Sray	fprintf (codefile, "%s += %s_for_oldret;\n",
206256904Sray		 variable, tmpstr);
207256904Sray	fprintf (codefile, "}\n");
208256904Sray
209256904Sray	fprintf (codefile,
210256904Sray		 "%s += %s_oldret;\n"
211256904Sray		 "}\n", variable, tmpstr);
212256904Sray	free(n);
213256904Sray	free(sname);
214256904Sray	break;
215256904Sray    }
216256904Sray    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