xref: /freebsd/crypto/heimdal/lib/asn1/gen_length.c (revision 5521ff5a4d1929056e7ffc982fac3341ca54df7c)
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.10 2000/06/21 22:40:53 assar 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 TOctetString:
73 	length_primitive ("octet_string", name, variable);
74 	break;
75     case TBitString: {
76 	/*
77 	 * XXX - Hope this is correct
78 	 * look at TBitString case in `encode_type'
79 	 */
80 	fprintf (codefile, "%s += 7;\n", variable);
81 	break;
82     }
83     case TSequence: {
84 	Member *m;
85 	int tag = -1;
86 
87 	if (t->members == NULL)
88 	    break;
89 
90 	for (m = t->members; m && tag != m->val; m = m->next) {
91 	    char *s;
92 
93 	    asprintf (&s, "%s(%s)->%s",
94 		      m->optional ? "" : "&", name, m->gen_name);
95 	    if (m->optional)
96 		fprintf (codefile, "if(%s)", s);
97 	    fprintf (codefile, "{\n"
98 		     "int oldret = %s;\n"
99 		     "%s = 0;\n", variable, variable);
100 	    length_type (s, m->type, "ret");
101 	    fprintf (codefile, "%s += 1 + length_len(%s) + oldret;\n",
102 		     variable, variable);
103 	    fprintf (codefile, "}\n");
104 	    if (tag == -1)
105 		tag = m->val;
106 	    free (s);
107 	}
108 	fprintf (codefile,
109 		 "%s += 1 + length_len(%s);\n", variable, variable);
110 	break;
111     }
112     case TSequenceOf: {
113 	char *n;
114 
115 	fprintf (codefile,
116 		 "{\n"
117 		 "int oldret = %s;\n"
118 		 "int i;\n"
119 		 "%s = 0;\n",
120 		 variable, variable);
121 
122 	fprintf (codefile, "for(i = (%s)->len - 1; i >= 0; --i){\n", name);
123 	asprintf (&n, "&(%s)->val[i]", name);
124 	length_type(n, t->subtype, variable);
125 	fprintf (codefile, "}\n");
126 
127 	fprintf (codefile,
128 		 "%s += 1 + length_len(%s) + oldret;\n"
129 		 "}\n", variable, variable);
130 	free(n);
131 	break;
132     }
133     case TGeneralizedTime:
134 	length_primitive ("generalized_time", name, variable);
135 	break;
136     case TGeneralString:
137 	length_primitive ("general_string", name, variable);
138 	break;
139     case TApplication:
140 	length_type (name, t->subtype, variable);
141 	fprintf (codefile, "ret += 1 + length_len (ret);\n");
142 	break;
143     default :
144 	abort ();
145     }
146 }
147 
148 void
149 generate_type_length (const Symbol *s)
150 {
151   fprintf (headerfile,
152 	   "size_t length_%s(const %s *);\n",
153 	   s->gen_name, s->gen_name);
154 
155   fprintf (codefile,
156 	   "size_t\n"
157 	   "length_%s(const %s *data)\n"
158 	   "{\n"
159 	   "size_t ret = 0;\n",
160 	   s->gen_name, s->gen_name);
161 
162   length_type ("data", s->type, "ret");
163   fprintf (codefile, "return ret;\n}\n\n");
164 }
165 
166