xref: /freebsd/crypto/heimdal/lib/asn1/gen_length.c (revision 9336e0699bda8a301cd2bfa37106b6ec5e32012e)
1 /*
2  * Copyright (c) 1997 - 2000 Kungliga Tekniska H�gskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the Institute nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include "gen_locl.h"
35 
36 RCSID("$Id: gen_length.c,v 1.11.6.1 2004/01/26 09:26:10 lha Exp $");
37 
38 static void
39 length_primitive (const char *typename,
40 		  const char *name,
41 		  const char *variable)
42 {
43     fprintf (codefile, "%s += length_%s(%s);\n", variable, typename, name);
44 }
45 
46 static void
47 length_type (const char *name, const Type *t, const char *variable)
48 {
49     switch (t->type) {
50     case TType:
51 #if 0
52 	length_type (name, t->symbol->type);
53 #endif
54 	fprintf (codefile, "%s += length_%s(%s);\n",
55 		 variable, t->symbol->gen_name, name);
56 	break;
57     case TInteger:
58         if(t->members == NULL)
59             length_primitive ("integer", name, variable);
60         else {
61             char *s;
62             asprintf(&s, "(const int*)%s", name);
63             if(s == NULL)
64 		errx (1, "out of memory");
65             length_primitive ("integer", s, variable);
66             free(s);
67         }
68 	break;
69     case TUInteger:
70 	length_primitive ("unsigned", name, variable);
71 	break;
72     case TEnumerated :
73 	length_primitive ("enumerated", name, variable);
74 	break;
75     case TOctetString:
76 	length_primitive ("octet_string", name, variable);
77 	break;
78     case TOID :
79 	length_primitive ("oid", name, variable);
80 	break;
81     case TBitString: {
82 	/*
83 	 * XXX - Hope this is correct
84 	 * look at TBitString case in `encode_type'
85 	 */
86 	fprintf (codefile, "%s += 7;\n", variable);
87 	break;
88     }
89     case TSequence: {
90 	Member *m;
91 	int tag = -1;
92 
93 	if (t->members == NULL)
94 	    break;
95 
96 	for (m = t->members; m && tag != m->val; m = m->next) {
97 	    char *s;
98 
99 	    asprintf (&s, "%s(%s)->%s",
100 		      m->optional ? "" : "&", name, m->gen_name);
101 	    if (m->optional)
102 		fprintf (codefile, "if(%s)", s);
103 	    fprintf (codefile, "{\n"
104 		     "int oldret = %s;\n"
105 		     "%s = 0;\n", variable, variable);
106 	    length_type (s, m->type, "ret");
107 	    fprintf (codefile, "%s += 1 + length_len(%s) + oldret;\n",
108 		     variable, variable);
109 	    fprintf (codefile, "}\n");
110 	    if (tag == -1)
111 		tag = m->val;
112 	    free (s);
113 	}
114 	fprintf (codefile,
115 		 "%s += 1 + length_len(%s);\n", variable, variable);
116 	break;
117     }
118     case TSequenceOf: {
119 	char *n;
120 
121 	fprintf (codefile,
122 		 "{\n"
123 		 "int oldret = %s;\n"
124 		 "int i;\n"
125 		 "%s = 0;\n",
126 		 variable, variable);
127 
128 	fprintf (codefile, "for(i = (%s)->len - 1; i >= 0; --i){\n", name);
129 	fprintf (codefile, "int oldret = %s;\n"
130 		 "%s = 0;\n", variable, variable);
131 	asprintf (&n, "&(%s)->val[i]", name);
132 	length_type(n, t->subtype, variable);
133 	fprintf (codefile, "%s += oldret;\n",
134 		 variable);
135 	fprintf (codefile, "}\n");
136 
137 	fprintf (codefile,
138 		 "%s += 1 + length_len(%s) + oldret;\n"
139 		 "}\n", variable, variable);
140 	free(n);
141 	break;
142     }
143     case TGeneralizedTime:
144 	length_primitive ("generalized_time", name, variable);
145 	break;
146     case TGeneralString:
147 	length_primitive ("general_string", name, variable);
148 	break;
149     case TApplication:
150 	length_type (name, t->subtype, variable);
151 	fprintf (codefile, "ret += 1 + length_len (ret);\n");
152 	break;
153     default :
154 	abort ();
155     }
156 }
157 
158 void
159 generate_type_length (const Symbol *s)
160 {
161   fprintf (headerfile,
162 	   "size_t length_%s(const %s *);\n",
163 	   s->gen_name, s->gen_name);
164 
165   fprintf (codefile,
166 	   "size_t\n"
167 	   "length_%s(const %s *data)\n"
168 	   "{\n"
169 	   "size_t ret = 0;\n",
170 	   s->gen_name, s->gen_name);
171 
172   length_type ("data", s->type, "ret");
173   fprintf (codefile, "return ret;\n}\n\n");
174 }
175 
176