BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file NCDInterpProcess.c
3 * @author Ambroz Bizjak <ambrop7@gmail.com>
4 *
5 * @section LICENSE
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29  
30 #include <stdint.h>
31 #include <limits.h>
32 #include <string.h>
33 #include <stdlib.h>
34  
35 #include <misc/balloc.h>
36 #include <misc/maxalign.h>
37 #include <misc/strdup.h>
38 #include <base/BLog.h>
39 #include <ncd/make_name_indices.h>
40  
41 #include "NCDInterpProcess.h"
42  
43 #include <generated/blog_channel_ncd.h>
44  
45 struct NCDInterpProcess__stmt {
46 NCD_string_id_t name;
47 NCD_string_id_t cmdname;
48 NCD_string_id_t *objnames;
49 size_t num_objnames;
50 union {
51 const struct NCDInterpModule *simple_module;
52 int method_name_id;
53 } binding;
54 NCDEvaluatorExpr arg_expr;
55 int alloc_size;
56 int prealloc_offset;
57 int hash_next;
58 };
59  
60 static int compute_prealloc (NCDInterpProcess *o)
61 {
62 int size = 0;
63  
64 for (int i = 0; i < o->num_stmts; i++) {
65 int mod = size % BMAX_ALIGN;
66 int align_size = (mod == 0 ? 0 : BMAX_ALIGN - mod);
67  
68 if (align_size + o->stmts[i].alloc_size > INT_MAX - size) {
69 return 0;
70 }
71  
72 o->stmts[i].prealloc_offset = size + align_size;
73 size += align_size + o->stmts[i].alloc_size;
74 }
75  
76 ASSERT(size >= 0)
77  
78 o->prealloc_size = size;
79  
80 return 1;
81 }
82  
83 int NCDInterpProcess_Init (NCDInterpProcess *o, NCDProcess *process, NCDStringIndex *string_index, NCDEvaluator *eval, NCDModuleIndex *module_index)
84 {
85 ASSERT(process)
86 ASSERT(string_index)
87 ASSERT(eval)
88 ASSERT(module_index)
89  
90 NCDBlock *block = NCDProcess_Block(process);
91  
92 if (NCDBlock_NumStatements(block) > INT_MAX) {
93 BLog(BLOG_ERROR, "too many statements");
94 goto fail0;
95 }
96 int num_stmts = NCDBlock_NumStatements(block);
97  
98 if (!(o->stmts = BAllocArray(num_stmts, sizeof(o->stmts[0])))) {
99 BLog(BLOG_ERROR, "BAllocArray failed");
100 goto fail0;
101 }
102  
103 o->num_hash_buckets = num_stmts;
104  
105 if (!(o->hash_buckets = BAllocArray(o->num_hash_buckets, sizeof(o->hash_buckets[0])))) {
106 BLog(BLOG_ERROR, "BAllocArray failed");
107 goto fail1;
108 }
109  
110 for (size_t i = 0; i < o->num_hash_buckets; i++) {
111 o->hash_buckets[i] = -1;
112 }
113  
114 if (!(o->name = b_strdup(NCDProcess_Name(process)))) {
115 BLog(BLOG_ERROR, "b_strdup failed");
116 goto fail2;
117 }
118  
119 o->num_stmts = 0;
120 o->prealloc_size = -1;
121 o->is_template = NCDProcess_IsTemplate(process);
122 o->cache = NULL;
123  
124 for (NCDStatement *s = NCDBlock_FirstStatement(block); s; s = NCDBlock_NextStatement(block, s)) {
125 ASSERT(NCDStatement_Type(s) == NCDSTATEMENT_REG)
126 struct NCDInterpProcess__stmt *e = &o->stmts[o->num_stmts];
127  
128 e->name = -1;
129 e->objnames = NULL;
130 e->num_objnames = 0;
131 e->alloc_size = 0;
132  
133 if (NCDStatement_Name(s)) {
134 e->name = NCDStringIndex_Get(string_index, NCDStatement_Name(s));
135 if (e->name < 0) {
136 BLog(BLOG_ERROR, "NCDStringIndex_Get failed");
137 goto loop_fail0;
138 }
139 }
140  
141 e->cmdname = NCDStringIndex_Get(string_index, NCDStatement_RegCmdName(s));
142 if (e->cmdname < 0) {
143 BLog(BLOG_ERROR, "NCDStringIndex_Get failed");
144 goto loop_fail0;
145 }
146  
147 if (!NCDEvaluatorExpr_Init(&e->arg_expr, eval, NCDStatement_RegArgs(s))) {
148 BLog(BLOG_ERROR, "NCDEvaluatorExpr_Init failed");
149 goto loop_fail0;
150 }
151  
152 if (NCDStatement_RegObjName(s)) {
153 if (!ncd_make_name_indices(string_index, NCDStatement_RegObjName(s), &e->objnames, &e->num_objnames)) {
154 BLog(BLOG_ERROR, "ncd_make_name_indices failed");
155 goto loop_fail1;
156 }
157  
158 e->binding.method_name_id = NCDModuleIndex_GetMethodNameId(module_index, NCDStatement_RegCmdName(s));
159 if (e->binding.method_name_id == -1) {
160 BLog(BLOG_ERROR, "NCDModuleIndex_GetMethodNameId failed");
161 goto loop_fail2;
162 }
163 } else {
164 e->binding.simple_module = NCDModuleIndex_FindModule(module_index, NCDStatement_RegCmdName(s));
165 }
166  
167 if (e->name >= 0) {
168 size_t bucket_idx = e->name % o->num_hash_buckets;
169 e->hash_next = o->hash_buckets[bucket_idx];
170 o->hash_buckets[bucket_idx] = o->num_stmts;
171 }
172  
173 o->num_stmts++;
174 continue;
175  
176 loop_fail2:
177 BFree(e->objnames);
178 loop_fail1:
179 NCDEvaluatorExpr_Free(&e->arg_expr);
180 loop_fail0:
181 goto fail3;
182 }
183  
184 ASSERT(o->num_stmts == num_stmts)
185  
186 DebugObject_Init(&o->d_obj);
187 return 1;
188  
189 fail3:
190 while (o->num_stmts-- > 0) {
191 struct NCDInterpProcess__stmt *e = &o->stmts[o->num_stmts];
192 BFree(e->objnames);
193 NCDEvaluatorExpr_Free(&e->arg_expr);
194 }
195 free(o->name);
196 fail2:
197 BFree(o->hash_buckets);
198 fail1:
199 BFree(o->stmts);
200 fail0:
201 return 0;
202 }
203  
204 void NCDInterpProcess_Free (NCDInterpProcess *o)
205 {
206 DebugObject_Free(&o->d_obj);
207  
208 while (o->num_stmts-- > 0) {
209 struct NCDInterpProcess__stmt *e = &o->stmts[o->num_stmts];
210 BFree(e->objnames);
211 NCDEvaluatorExpr_Free(&e->arg_expr);
212 }
213  
214 free(o->name);
215 BFree(o->hash_buckets);
216 BFree(o->stmts);
217 }
218  
219 int NCDInterpProcess_FindStatement (NCDInterpProcess *o, int from_index, NCD_string_id_t name)
220 {
221 DebugObject_Access(&o->d_obj);
222 ASSERT(from_index >= 0)
223 ASSERT(from_index <= o->num_stmts)
224  
225 size_t bucket_idx = name % o->num_hash_buckets;
226 int stmt_idx = o->hash_buckets[bucket_idx];
227 ASSERT(stmt_idx >= -1)
228 ASSERT(stmt_idx < o->num_stmts)
229  
230 while (stmt_idx >= 0) {
231 if (stmt_idx < from_index && o->stmts[stmt_idx].name == name) {
232 return stmt_idx;
233 }
234  
235 stmt_idx = o->stmts[stmt_idx].hash_next;
236 ASSERT(stmt_idx >= -1)
237 ASSERT(stmt_idx < o->num_stmts)
238 }
239  
240 return -1;
241 }
242  
243 const char * NCDInterpProcess_StatementCmdName (NCDInterpProcess *o, int i, NCDStringIndex *string_index)
244 {
245 DebugObject_Access(&o->d_obj);
246 ASSERT(i >= 0)
247 ASSERT(i < o->num_stmts)
248 ASSERT(string_index)
249  
250 return NCDStringIndex_Value(string_index, o->stmts[i].cmdname).ptr;
251 }
252  
253 void NCDInterpProcess_StatementObjNames (NCDInterpProcess *o, int i, const NCD_string_id_t **out_objnames, size_t *out_num_objnames)
254 {
255 DebugObject_Access(&o->d_obj);
256 ASSERT(i >= 0)
257 ASSERT(i < o->num_stmts)
258 ASSERT(out_objnames)
259 ASSERT(out_num_objnames)
260  
261 *out_objnames = o->stmts[i].objnames;
262 *out_num_objnames = o->stmts[i].num_objnames;
263 }
264  
265 const struct NCDInterpModule * NCDInterpProcess_StatementGetSimpleModule (NCDInterpProcess *o, int i, NCDStringIndex *string_index, NCDModuleIndex *module_index)
266 {
267 DebugObject_Access(&o->d_obj);
268 ASSERT(i >= 0)
269 ASSERT(i < o->num_stmts)
270 ASSERT(!o->stmts[i].objnames)
271  
272 struct NCDInterpProcess__stmt *e = &o->stmts[i];
273  
274 if (!e->binding.simple_module) {
275 const char *cmdname = NCDStringIndex_Value(string_index, e->cmdname).ptr;
276 e->binding.simple_module = NCDModuleIndex_FindModule(module_index, cmdname);
277 }
278  
279 return e->binding.simple_module;
280 }
281  
282 const struct NCDInterpModule * NCDInterpProcess_StatementGetMethodModule (NCDInterpProcess *o, int i, NCD_string_id_t obj_type, NCDModuleIndex *module_index)
283 {
284 DebugObject_Access(&o->d_obj);
285 ASSERT(i >= 0)
286 ASSERT(i < o->num_stmts)
287 ASSERT(o->stmts[i].objnames)
288 ASSERT(obj_type >= 0)
289 ASSERT(module_index)
290  
291 return NCDModuleIndex_GetMethodModule(module_index, obj_type, o->stmts[i].binding.method_name_id);
292 }
293  
294 NCDEvaluatorExpr * NCDInterpProcess_GetStatementArgsExpr (NCDInterpProcess *o, int i)
295 {
296 DebugObject_Access(&o->d_obj);
297 ASSERT(i >= 0)
298 ASSERT(i < o->num_stmts)
299  
300 struct NCDInterpProcess__stmt *e = &o->stmts[i];
301  
302 return &e->arg_expr;
303 }
304  
305 void NCDInterpProcess_StatementBumpAllocSize (NCDInterpProcess *o, int i, int alloc_size)
306 {
307 DebugObject_Access(&o->d_obj);
308 ASSERT(i >= 0)
309 ASSERT(i < o->num_stmts)
310 ASSERT(alloc_size >= 0)
311  
312 if (alloc_size > o->stmts[i].alloc_size) {
313 o->stmts[i].alloc_size = alloc_size;
314 o->prealloc_size = -1;
315 }
316 }
317  
318 int NCDInterpProcess_PreallocSize (NCDInterpProcess *o)
319 {
320 DebugObject_Access(&o->d_obj);
321 ASSERT(o->prealloc_size == -1 || o->prealloc_size >= 0)
322  
323 if (o->prealloc_size < 0 && !compute_prealloc(o)) {
324 return -1;
325 }
326  
327 return o->prealloc_size;
328 }
329  
330 int NCDInterpProcess_StatementPreallocSize (NCDInterpProcess *o, int i)
331 {
332 DebugObject_Access(&o->d_obj);
333 ASSERT(i >= 0)
334 ASSERT(i < o->num_stmts)
335 ASSERT(o->prealloc_size >= 0)
336  
337 return o->stmts[i].alloc_size;
338 }
339  
340 int NCDInterpProcess_StatementPreallocOffset (NCDInterpProcess *o, int i)
341 {
342 DebugObject_Access(&o->d_obj);
343 ASSERT(i >= 0)
344 ASSERT(i < o->num_stmts)
345 ASSERT(o->prealloc_size >= 0)
346  
347 return o->stmts[i].prealloc_offset;
348 }
349  
350 const char * NCDInterpProcess_Name (NCDInterpProcess *o)
351 {
352 DebugObject_Access(&o->d_obj);
353  
354 return o->name;
355 }
356  
357 int NCDInterpProcess_IsTemplate (NCDInterpProcess *o)
358 {
359 DebugObject_Access(&o->d_obj);
360  
361 return o->is_template;
362 }
363  
364 int NCDInterpProcess_NumStatements (NCDInterpProcess *o)
365 {
366 DebugObject_Access(&o->d_obj);
367  
368 return o->num_stmts;
369 }
370  
371 int NCDInterpProcess_CachePush (NCDInterpProcess *o, void *elem)
372 {
373 DebugObject_Access(&o->d_obj);
374 ASSERT(elem)
375  
376 if (o->cache) {
377 return 0;
378 }
379  
380 o->cache = elem;
381  
382 return 1;
383 }
384  
385 void * NCDInterpProcess_CachePull (NCDInterpProcess *o)
386 {
387 DebugObject_Access(&o->d_obj);
388  
389 void *elem = o->cache;
390 o->cache = NULL;
391  
392 return elem;
393 }