1 | /*
|
---|
2 | * Copyright (c) 2010 Jiri Svoboda
|
---|
3 | * All rights reserved.
|
---|
4 | *
|
---|
5 | * Redistribution and use in source and binary forms, with or without
|
---|
6 | * modification, are permitted provided that the following conditions
|
---|
7 | * are met:
|
---|
8 | *
|
---|
9 | * - Redistributions of source code must retain the above copyright
|
---|
10 | * notice, this list of conditions and the following disclaimer.
|
---|
11 | * - 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 | * - The name of the author may not be used to endorse or promote products
|
---|
15 | * derived from this software without specific prior written permission.
|
---|
16 | *
|
---|
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
---|
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
---|
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
---|
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
---|
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
---|
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
---|
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
---|
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
---|
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
---|
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
---|
27 | */
|
---|
28 |
|
---|
29 | /** @file Runner (executes the code). */
|
---|
30 |
|
---|
31 | #include <stdio.h>
|
---|
32 | #include <stdlib.h>
|
---|
33 | #include <assert.h>
|
---|
34 | #include "debug.h"
|
---|
35 | #include "list.h"
|
---|
36 | #include "mytypes.h"
|
---|
37 | #include "rdata.h"
|
---|
38 | #include "run.h"
|
---|
39 | #include "symbol.h"
|
---|
40 | #include "strtab.h"
|
---|
41 |
|
---|
42 | #include "run_expr.h"
|
---|
43 |
|
---|
44 | static void run_nameref(run_t *run, stree_nameref_t *nameref,
|
---|
45 | rdata_item_t **res);
|
---|
46 | static void run_literal(run_t *run, stree_literal_t *literal,
|
---|
47 | rdata_item_t **res);
|
---|
48 | static void run_lit_int(run_t *run, stree_lit_int_t *lit_int,
|
---|
49 | rdata_item_t **res);
|
---|
50 | static void run_lit_string(run_t *run, stree_lit_string_t *lit_string,
|
---|
51 | rdata_item_t **res);
|
---|
52 | static void run_binop(run_t *run, stree_binop_t *binop, rdata_item_t **res);
|
---|
53 | static void run_unop(run_t *run, stree_unop_t *unop, rdata_item_t **res);
|
---|
54 | static void run_access(run_t *run, stree_access_t *access, rdata_item_t **res);
|
---|
55 | static void run_call(run_t *run, stree_call_t *call, rdata_item_t **res);
|
---|
56 | static void run_assign(run_t *run, stree_assign_t *assign, rdata_item_t **res);
|
---|
57 |
|
---|
58 | static void run_address_read(run_t *run, rdata_address_t *address,
|
---|
59 | rdata_item_t **ritem);
|
---|
60 | static void run_address_write(run_t *run, rdata_address_t *address,
|
---|
61 | rdata_value_t *value);
|
---|
62 |
|
---|
63 | /** Evaluate expression. */
|
---|
64 | void run_expr(run_t *run, stree_expr_t *expr, rdata_item_t **res)
|
---|
65 | {
|
---|
66 | #ifdef DEBUG_RUN_TRACE
|
---|
67 | printf("Executing expression.\n");
|
---|
68 | #endif
|
---|
69 |
|
---|
70 | switch (expr->ec) {
|
---|
71 | case ec_nameref:
|
---|
72 | run_nameref(run, expr->u.nameref, res);
|
---|
73 | break;
|
---|
74 | case ec_literal:
|
---|
75 | run_literal(run, expr->u.literal, res);
|
---|
76 | break;
|
---|
77 | case ec_binop:
|
---|
78 | run_binop(run, expr->u.binop, res);
|
---|
79 | break;
|
---|
80 | case ec_unop:
|
---|
81 | run_unop(run, expr->u.unop, res);
|
---|
82 | break;
|
---|
83 | case ec_access:
|
---|
84 | run_access(run, expr->u.access, res);
|
---|
85 | break;
|
---|
86 | case ec_call:
|
---|
87 | run_call(run, expr->u.call, res);
|
---|
88 | break;
|
---|
89 | case ec_assign:
|
---|
90 | run_assign(run, expr->u.assign, res);
|
---|
91 | break;
|
---|
92 | }
|
---|
93 |
|
---|
94 | #ifdef DEBUG_RUN_TRACE
|
---|
95 | printf("Expression result: ");
|
---|
96 | rdata_item_print(*res);
|
---|
97 | printf(".\n");
|
---|
98 | #endif
|
---|
99 | }
|
---|
100 |
|
---|
101 | /** Evaluate name reference expression. */
|
---|
102 | static void run_nameref(run_t *run, stree_nameref_t *nameref,
|
---|
103 | rdata_item_t **res)
|
---|
104 | {
|
---|
105 | stree_symbol_t *sym;
|
---|
106 | rdata_item_t *item;
|
---|
107 | rdata_address_t *address;
|
---|
108 | rdata_value_t *val;
|
---|
109 | rdata_var_t *var;
|
---|
110 | rdata_deleg_t *deleg_v;
|
---|
111 |
|
---|
112 | #ifdef DEBUG_RUN_TRACE
|
---|
113 | printf("Run nameref.\n");
|
---|
114 | #endif
|
---|
115 |
|
---|
116 | /*
|
---|
117 | * Look for a local variable.
|
---|
118 | */
|
---|
119 | var = run_local_vars_lookup(run, nameref->name->sid);
|
---|
120 | if (var != NULL) {
|
---|
121 | /* Found a local variable. */
|
---|
122 | item = rdata_item_new(ic_address);
|
---|
123 | address = rdata_address_new();
|
---|
124 |
|
---|
125 | item->u.address = address;
|
---|
126 | address->vref = var;
|
---|
127 |
|
---|
128 | *res = item;
|
---|
129 | #ifdef DEBUG_RUN_TRACE
|
---|
130 | printf("Found local variable.\n");
|
---|
131 | #endif
|
---|
132 | return;
|
---|
133 | }
|
---|
134 |
|
---|
135 | /*
|
---|
136 | * Look for a class-wide or global symbol.
|
---|
137 | */
|
---|
138 |
|
---|
139 | /* XXX Start lookup in currently active CSI. */
|
---|
140 | sym = symbol_lookup_in_csi(run->program, NULL, nameref->name);
|
---|
141 |
|
---|
142 | switch (sym->sc) {
|
---|
143 | case sc_csi:
|
---|
144 | #ifdef DEBUG_RUN_TRACE
|
---|
145 | printf("Referencing class.\n");
|
---|
146 | #endif
|
---|
147 | item = rdata_item_new(ic_value);
|
---|
148 | val = rdata_value_new();
|
---|
149 | var = rdata_var_new(vc_deleg);
|
---|
150 | deleg_v = rdata_deleg_new();
|
---|
151 |
|
---|
152 | item->u.value = val;
|
---|
153 | val->var = var;
|
---|
154 | var->u.deleg_v = deleg_v;
|
---|
155 |
|
---|
156 | deleg_v->obj = NULL;
|
---|
157 | deleg_v->sym = sym;
|
---|
158 | *res = item;
|
---|
159 | break;
|
---|
160 | default:
|
---|
161 | printf("Referencing symbol class %d unimplemented.\n", sym->sc);
|
---|
162 | *res = NULL;
|
---|
163 | break;
|
---|
164 | }
|
---|
165 | }
|
---|
166 |
|
---|
167 | /** Evaluate literal. */
|
---|
168 | static void run_literal(run_t *run, stree_literal_t *literal,
|
---|
169 | rdata_item_t **res)
|
---|
170 | {
|
---|
171 | #ifdef DEBUG_RUN_TRACE
|
---|
172 | printf("Run literal.\n");
|
---|
173 | #endif
|
---|
174 |
|
---|
175 | switch (literal->ltc) {
|
---|
176 | case ltc_int:
|
---|
177 | run_lit_int(run, &literal->u.lit_int, res);
|
---|
178 | break;
|
---|
179 | case ltc_string:
|
---|
180 | run_lit_string(run, &literal->u.lit_string, res);
|
---|
181 | break;
|
---|
182 | default:
|
---|
183 | assert(b_false);
|
---|
184 | }
|
---|
185 | }
|
---|
186 |
|
---|
187 | /** Evaluate integer literal. */
|
---|
188 | static void run_lit_int(run_t *run, stree_lit_int_t *lit_int,
|
---|
189 | rdata_item_t **res)
|
---|
190 | {
|
---|
191 | rdata_item_t *item;
|
---|
192 | rdata_value_t *value;
|
---|
193 | rdata_var_t *var;
|
---|
194 | rdata_int_t *int_v;
|
---|
195 |
|
---|
196 | #ifdef DEBUG_RUN_TRACE
|
---|
197 | printf("Run integer literal.\n");
|
---|
198 | #endif
|
---|
199 |
|
---|
200 | item = rdata_item_new(ic_value);
|
---|
201 | value = rdata_value_new();
|
---|
202 | var = rdata_var_new(vc_int);
|
---|
203 | int_v = rdata_int_new();
|
---|
204 |
|
---|
205 | item->u.value = value;
|
---|
206 | value->var = var;
|
---|
207 | var->u.int_v = int_v;
|
---|
208 | int_v->value = lit_int->value;
|
---|
209 |
|
---|
210 | *res = item;
|
---|
211 | }
|
---|
212 |
|
---|
213 | /** Evaluate string literal. */
|
---|
214 | static void run_lit_string(run_t *run, stree_lit_string_t *lit_string,
|
---|
215 | rdata_item_t **res)
|
---|
216 | {
|
---|
217 | rdata_item_t *item;
|
---|
218 | rdata_value_t *value;
|
---|
219 | rdata_var_t *var;
|
---|
220 | rdata_string_t *string_v;
|
---|
221 |
|
---|
222 | #ifdef DEBUG_RUN_TRACE
|
---|
223 | printf("Run integer literal.\n");
|
---|
224 | #endif
|
---|
225 | item = rdata_item_new(ic_value);
|
---|
226 | value = rdata_value_new();
|
---|
227 | var = rdata_var_new(vc_string);
|
---|
228 | string_v = rdata_string_new();
|
---|
229 |
|
---|
230 | item->u.value = value;
|
---|
231 | value->var = var;
|
---|
232 | var->u.string_v = string_v;
|
---|
233 | string_v->value = lit_string->value;
|
---|
234 |
|
---|
235 | *res = item;
|
---|
236 | }
|
---|
237 |
|
---|
238 |
|
---|
239 | /** Evaluate binary operation. */
|
---|
240 | static void run_binop(run_t *run, stree_binop_t *binop, rdata_item_t **res)
|
---|
241 | {
|
---|
242 | rdata_item_t *rarg1_i, *rarg2_i;
|
---|
243 | rdata_item_t *rarg1_vi, *rarg2_vi;
|
---|
244 | rdata_value_t *v1, *v2;
|
---|
245 | int i1, i2;
|
---|
246 |
|
---|
247 | rdata_item_t *item;
|
---|
248 | rdata_value_t *value;
|
---|
249 | rdata_var_t *var;
|
---|
250 | rdata_int_t *int_v;
|
---|
251 |
|
---|
252 | #ifdef DEBUG_RUN_TRACE
|
---|
253 | printf("Run binary operation.\n");
|
---|
254 | #endif
|
---|
255 | run_expr(run, binop->arg1, &rarg1_i);
|
---|
256 | run_expr(run, binop->arg2, &rarg2_i);
|
---|
257 |
|
---|
258 | switch (binop->bc) {
|
---|
259 | case bo_plus:
|
---|
260 | case bo_equal:
|
---|
261 | case bo_notequal:
|
---|
262 | case bo_lt:
|
---|
263 | case bo_gt:
|
---|
264 | case bo_lt_equal:
|
---|
265 | case bo_gt_equal:
|
---|
266 | /* These are implemented so far. */
|
---|
267 | break;
|
---|
268 | default:
|
---|
269 | printf("Unimplemented: Binary operation type %d.\n",
|
---|
270 | binop->bc);
|
---|
271 | exit(1);
|
---|
272 | }
|
---|
273 |
|
---|
274 | #ifdef DEBUG_RUN_TRACE
|
---|
275 | printf("Check binop argument results.\n");
|
---|
276 | #endif
|
---|
277 |
|
---|
278 | run_cvt_value_item(run, rarg1_i, &rarg1_vi);
|
---|
279 | run_cvt_value_item(run, rarg2_i, &rarg2_vi);
|
---|
280 |
|
---|
281 | v1 = rarg1_vi->u.value;
|
---|
282 | v2 = rarg2_vi->u.value;
|
---|
283 |
|
---|
284 | if (v1->var->vc != vc_int || v2->var->vc != vc_int) {
|
---|
285 | printf("Unimplemented: Binary operation arguments are not "
|
---|
286 | "integer values.\n");
|
---|
287 | exit(1);
|
---|
288 | }
|
---|
289 |
|
---|
290 | item = rdata_item_new(ic_value);
|
---|
291 | value = rdata_value_new();
|
---|
292 | var = rdata_var_new(vc_int);
|
---|
293 | int_v = rdata_int_new();
|
---|
294 |
|
---|
295 | item->u.value = value;
|
---|
296 | value->var = var;
|
---|
297 | var->u.int_v = int_v;
|
---|
298 |
|
---|
299 | i1 = v1->var->u.int_v->value;
|
---|
300 | i2 = v2->var->u.int_v->value;
|
---|
301 |
|
---|
302 | switch (binop->bc) {
|
---|
303 | case bo_plus:
|
---|
304 | int_v->value = i1 + i2;
|
---|
305 | break;
|
---|
306 |
|
---|
307 | /* XXX We should have a real boolean type. */
|
---|
308 | case bo_equal:
|
---|
309 | int_v->value = (i1 == i2) ? 1 : 0;
|
---|
310 | break;
|
---|
311 | case bo_notequal:
|
---|
312 | int_v->value = (i1 != i2) ? 1 : 0;
|
---|
313 | break;
|
---|
314 | case bo_lt:
|
---|
315 | int_v->value = (i1 < i2) ? 1 : 0;
|
---|
316 | break;
|
---|
317 | case bo_gt:
|
---|
318 | int_v->value = (i1 > i2) ? 1 : 0;
|
---|
319 | break;
|
---|
320 | case bo_lt_equal:
|
---|
321 | int_v->value = (i1 <= i2) ? 1 : 0;
|
---|
322 | break;
|
---|
323 | case bo_gt_equal:
|
---|
324 | int_v->value = (i1 >= i2) ? 1 : 0;
|
---|
325 | break;
|
---|
326 | default:
|
---|
327 | assert(b_false);
|
---|
328 | }
|
---|
329 |
|
---|
330 | *res = item;
|
---|
331 | }
|
---|
332 |
|
---|
333 | /** Evaluate unary operation. */
|
---|
334 | static void run_unop(run_t *run, stree_unop_t *unop, rdata_item_t **res)
|
---|
335 | {
|
---|
336 | rdata_item_t *rarg;
|
---|
337 |
|
---|
338 | #ifdef DEBUG_RUN_TRACE
|
---|
339 | printf("Run unary operation.\n");
|
---|
340 | #endif
|
---|
341 | run_expr(run, unop->arg, &rarg);
|
---|
342 | *res = NULL;
|
---|
343 | }
|
---|
344 |
|
---|
345 | /** Evaluate member acccess. */
|
---|
346 | static void run_access(run_t *run, stree_access_t *access, rdata_item_t **res)
|
---|
347 | {
|
---|
348 | rdata_item_t *rarg;
|
---|
349 | rdata_deleg_t *deleg_v;
|
---|
350 | stree_symbol_t *member;
|
---|
351 |
|
---|
352 | #ifdef DEBUG_RUN_TRACE
|
---|
353 | printf("Run access operation.\n");
|
---|
354 | #endif
|
---|
355 | run_expr(run, access->arg, &rarg);
|
---|
356 |
|
---|
357 | if (rarg->ic == ic_value && rarg->u.value->var->vc == vc_deleg) {
|
---|
358 | #ifdef DEBUG_RUN_TRACE
|
---|
359 | printf("Accessing delegate.\n");
|
---|
360 | #endif
|
---|
361 | deleg_v = rarg->u.value->var->u.deleg_v;
|
---|
362 | if (deleg_v->obj != NULL || deleg_v->sym->sc != sc_csi) {
|
---|
363 | printf("Error: Using '.' with symbol of wrong "
|
---|
364 | "type (%d).\n", deleg_v->sym->sc);
|
---|
365 | exit(1);
|
---|
366 | }
|
---|
367 |
|
---|
368 | member = symbol_search_csi(run->program, deleg_v->sym->u.csi,
|
---|
369 | access->member_name);
|
---|
370 |
|
---|
371 | if (member == NULL) {
|
---|
372 | printf("Error: No such member.\n");
|
---|
373 | exit(1);
|
---|
374 | }
|
---|
375 |
|
---|
376 | #ifdef DEBUG_RUN_TRACE
|
---|
377 | printf("Found member '%s'.\n",
|
---|
378 | strtab_get_str(access->member_name->sid));
|
---|
379 | #endif
|
---|
380 |
|
---|
381 | /* Reuse existing item, value, var, deleg. */
|
---|
382 | deleg_v->sym = member;
|
---|
383 |
|
---|
384 | *res = rarg;
|
---|
385 | return;
|
---|
386 | }
|
---|
387 |
|
---|
388 | *res = NULL;
|
---|
389 | }
|
---|
390 |
|
---|
391 | /** Call a function. */
|
---|
392 | static void run_call(run_t *run, stree_call_t *call, rdata_item_t **res)
|
---|
393 | {
|
---|
394 | rdata_item_t *rfun;
|
---|
395 | rdata_deleg_t *deleg_v;
|
---|
396 | list_t arg_vals;
|
---|
397 | list_node_t *node;
|
---|
398 | stree_expr_t *arg;
|
---|
399 | rdata_item_t *rarg_i, *rarg_vi;
|
---|
400 |
|
---|
401 | #ifdef DEBUG_RUN_TRACE
|
---|
402 | printf("Run call operation.\n");
|
---|
403 | #endif
|
---|
404 | run_expr(run, call->fun, &rfun);
|
---|
405 |
|
---|
406 | if (rfun->ic != ic_value || rfun->u.value->var->vc != vc_deleg) {
|
---|
407 | printf("Unimplemented: Call expression of this type.\n");
|
---|
408 | *res = NULL;
|
---|
409 | return;
|
---|
410 | }
|
---|
411 |
|
---|
412 | deleg_v = rfun->u.value->var->u.deleg_v;
|
---|
413 |
|
---|
414 | if (deleg_v->sym->sc != sc_fun) {
|
---|
415 | printf("Error: Called symbol is not a function.\n");
|
---|
416 | exit(1);
|
---|
417 | }
|
---|
418 |
|
---|
419 | #ifdef DEBUG_RUN_TRACE
|
---|
420 | printf("Call function '");
|
---|
421 | symbol_print_fqn(run->program, deleg_v->sym);
|
---|
422 | printf("'\n");
|
---|
423 | #endif
|
---|
424 |
|
---|
425 | /* Evaluate function arguments. */
|
---|
426 | list_init(&arg_vals);
|
---|
427 | node = list_first(&call->args);
|
---|
428 |
|
---|
429 | while (node != NULL) {
|
---|
430 | arg = list_node_data(node, stree_expr_t *);
|
---|
431 | run_expr(run, arg, &rarg_i);
|
---|
432 | run_cvt_value_item(run, rarg_i, &rarg_vi);
|
---|
433 |
|
---|
434 | list_append(&arg_vals, rarg_vi);
|
---|
435 | node = list_next(&call->args, node);
|
---|
436 | }
|
---|
437 |
|
---|
438 | run_fun(run, deleg_v->sym->u.fun, &arg_vals);
|
---|
439 |
|
---|
440 | #ifdef DEBUG_RUN_TRACE
|
---|
441 | printf("Returned from function call.\n");
|
---|
442 | #endif
|
---|
443 | *res = NULL;
|
---|
444 | }
|
---|
445 |
|
---|
446 | /** Execute assignment. */
|
---|
447 | static void run_assign(run_t *run, stree_assign_t *assign, rdata_item_t **res)
|
---|
448 | {
|
---|
449 | rdata_item_t *rdest_i, *rsrc_i;
|
---|
450 | rdata_item_t *rsrc_vi;
|
---|
451 | rdata_value_t *src_val;
|
---|
452 |
|
---|
453 | #ifdef DEBUG_RUN_TRACE
|
---|
454 | printf("Run assign operation.\n");
|
---|
455 | #endif
|
---|
456 | run_expr(run, assign->dest, &rdest_i);
|
---|
457 | run_expr(run, assign->src, &rsrc_i);
|
---|
458 |
|
---|
459 | run_cvt_value_item(run, rsrc_i, &rsrc_vi);
|
---|
460 | src_val = rsrc_vi->u.value;
|
---|
461 |
|
---|
462 | if (rdest_i->ic != ic_address) {
|
---|
463 | printf("Error: Address expression required on left side of "
|
---|
464 | "assignment operator.\n");
|
---|
465 | exit(1);
|
---|
466 | }
|
---|
467 |
|
---|
468 | run_address_write(run, rdest_i->u.address, rsrc_vi->u.value);
|
---|
469 |
|
---|
470 | *res = NULL;
|
---|
471 | }
|
---|
472 |
|
---|
473 | /** Return boolean value of an item.
|
---|
474 | *
|
---|
475 | * Tries to interpret @a item as a boolean value. If it is not a boolean
|
---|
476 | * value, this generates an error.
|
---|
477 | *
|
---|
478 | * XXX Currently int supplants the role of a true boolean type.
|
---|
479 | */
|
---|
480 | bool_t run_item_boolean_value(run_t *run, rdata_item_t *item)
|
---|
481 | {
|
---|
482 | rdata_item_t *vitem;
|
---|
483 | rdata_var_t *var;
|
---|
484 |
|
---|
485 | run_cvt_value_item(run, item, &vitem);
|
---|
486 |
|
---|
487 | assert(vitem->ic == ic_value);
|
---|
488 | var = vitem->u.value->var;
|
---|
489 |
|
---|
490 | if (var->vc != vc_int) {
|
---|
491 | printf("Error: Boolean (int) expression expected.\n");
|
---|
492 | exit(1);
|
---|
493 | }
|
---|
494 |
|
---|
495 | return (var->u.int_v->value != 0);
|
---|
496 | }
|
---|
497 |
|
---|
498 | /** Convert item to value item.
|
---|
499 | *
|
---|
500 | * If @a item is a value, we just return a copy. If @a item is an address,
|
---|
501 | * we read from the address.
|
---|
502 | */
|
---|
503 | void run_cvt_value_item(run_t *run, rdata_item_t *item,
|
---|
504 | rdata_item_t **ritem)
|
---|
505 | {
|
---|
506 | rdata_value_t *value;
|
---|
507 |
|
---|
508 | /* Address item. Perform read operation. */
|
---|
509 | if (item->ic == ic_address) {
|
---|
510 | run_address_read(run, item->u.address, ritem);
|
---|
511 | return;
|
---|
512 | }
|
---|
513 |
|
---|
514 | /* It already is a value, we can share the @c var. */
|
---|
515 | value = rdata_value_new();
|
---|
516 | value->var = item->u.value->var;
|
---|
517 | *ritem = rdata_item_new(ic_value);
|
---|
518 | (*ritem)->u.value = value;
|
---|
519 | }
|
---|
520 |
|
---|
521 | /** Read data from an address.
|
---|
522 | *
|
---|
523 | * Return value stored in a variable at the specified address.
|
---|
524 | */
|
---|
525 | static void run_address_read(run_t *run, rdata_address_t *address,
|
---|
526 | rdata_item_t **ritem)
|
---|
527 | {
|
---|
528 | rdata_value_t *value;
|
---|
529 | rdata_var_t *rvar;
|
---|
530 | (void) run;
|
---|
531 |
|
---|
532 | /* Perform a shallow copy of @c var. */
|
---|
533 | rdata_var_copy(address->vref, &rvar);
|
---|
534 |
|
---|
535 | value = rdata_value_new();
|
---|
536 | value->var = rvar;
|
---|
537 | *ritem = rdata_item_new(ic_value);
|
---|
538 | (*ritem)->u.value = value;
|
---|
539 | }
|
---|
540 |
|
---|
541 | /** Write data to an address.
|
---|
542 | *
|
---|
543 | * Store @a value to the variable at @a address.
|
---|
544 | */
|
---|
545 | static void run_address_write(run_t *run, rdata_address_t *address,
|
---|
546 | rdata_value_t *value)
|
---|
547 | {
|
---|
548 | rdata_var_t *nvar;
|
---|
549 | rdata_var_t *orig_var;
|
---|
550 |
|
---|
551 | /* Perform a shallow copy of @c value->var. */
|
---|
552 | rdata_var_copy(value->var, &nvar);
|
---|
553 | orig_var = address->vref;
|
---|
554 |
|
---|
555 | /* XXX do this in a prettier way. */
|
---|
556 |
|
---|
557 | orig_var->vc = nvar->vc;
|
---|
558 | switch (nvar->vc) {
|
---|
559 | case vc_int: orig_var->u.int_v = nvar->u.int_v; break;
|
---|
560 | case vc_ref: orig_var->u.ref_v = nvar->u.ref_v; break;
|
---|
561 | case vc_deleg: orig_var->u.deleg_v = nvar->u.deleg_v; break;
|
---|
562 | case vc_object: orig_var->u.object_v = nvar->u.object_v; break;
|
---|
563 | default: assert(b_false);
|
---|
564 | }
|
---|
565 |
|
---|
566 | /* XXX We should free some stuff around here. */
|
---|
567 | }
|
---|