source: mainline/uspace/app/sbi/src/rdata.c@ 7bbc389

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 7bbc389 was c5cb943d, checked in by Jiri Svoboda <jiri@…>, 15 years ago

Update SBI to rev. 291.

  • Property mode set to 100644
File size: 18.4 KB
Line 
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 Run-time data representation.
30 *
31 * At run time SBI represents all data as a graph of interconnected @c var
32 * nodes (variable nodes). Any piece of memory addressable by the program
33 * (i.e. all variables) are stored in var nodes. However, var nodes are also
34 * used internally to implement value items. (I.e. values in value items
35 * have exactly the same structure as program variables).
36 *
37 * Unlike byte- or word-oriented memory on a real machine, var nodes provide
38 * structured and typed storage. (This typing is dynamic, however and has
39 * nothing to do with the static type system).
40 *
41 * There are several types of var nodes, one for each primitive type,
42 * reference, delegate, array, and object. A reference var node contains
43 * a pointer to another var node. Delegate var node points to some stree
44 * declaration. Array and object var nodes refer to a collection of child
45 * nodes (fields, elements).
46 */
47
48#include <stdlib.h>
49#include <assert.h>
50#include "bigint.h"
51#include "mytypes.h"
52#include "stree.h"
53#include "symbol.h"
54#include "strtab.h"
55
56#include "rdata.h"
57
58static void rdata_bool_copy(rdata_bool_t *src, rdata_bool_t **dest);
59static void rdata_char_copy(rdata_char_t *src, rdata_char_t **dest);
60static void rdata_int_copy(rdata_int_t *src, rdata_int_t **dest);
61static void rdata_string_copy(rdata_string_t *src, rdata_string_t **dest);
62static void rdata_ref_copy(rdata_ref_t *src, rdata_ref_t **dest);
63static void rdata_deleg_copy(rdata_deleg_t *src, rdata_deleg_t **dest);
64static void rdata_enum_copy(rdata_enum_t *src, rdata_enum_t **dest);
65static void rdata_array_copy(rdata_array_t *src, rdata_array_t **dest);
66static void rdata_object_copy(rdata_object_t *src, rdata_object_t **dest);
67static void rdata_resource_copy(rdata_resource_t *src,
68 rdata_resource_t **dest);
69static void rdata_symbol_copy(rdata_symbol_t *src, rdata_symbol_t **dest);
70
71static int rdata_array_get_dim(rdata_array_t *array);
72
73static void rdata_address_print(rdata_address_t *address);
74static void rdata_var_print(rdata_var_t *var);
75
76/** Allocate new data item.
77 *
78 * @param ic Item class.
79 * @return New item.
80 */
81rdata_item_t *rdata_item_new(item_class_t ic)
82{
83 rdata_item_t *item;
84
85 item = calloc(1, sizeof(rdata_item_t));
86 if (item == NULL) {
87 printf("Memory allocation failed.\n");
88 exit(1);
89 }
90
91 item->ic = ic;
92 return item;
93}
94
95/** Allocate new address.
96 *
97 * @return New address.
98 */
99rdata_addr_var_t *rdata_addr_var_new(void)
100{
101 rdata_addr_var_t *addr_var;
102
103 addr_var = calloc(1, sizeof(rdata_addr_var_t));
104 if (addr_var == NULL) {
105 printf("Memory allocation failed.\n");
106 exit(1);
107 }
108
109 return addr_var;
110}
111
112/** Allocate new named property address.
113 *
114 * @return New named property address.
115 */
116rdata_aprop_named_t *rdata_aprop_named_new(void)
117{
118 rdata_aprop_named_t *aprop_named;
119
120 aprop_named = calloc(1, sizeof(rdata_aprop_named_t));
121 if (aprop_named == NULL) {
122 printf("Memory allocation failed.\n");
123 exit(1);
124 }
125
126 return aprop_named;
127}
128
129/** Allocate new indexed property address.
130 *
131 * @return New indexed property address.
132 */
133rdata_aprop_indexed_t *rdata_aprop_indexed_new(void)
134{
135 rdata_aprop_indexed_t *aprop_indexed;
136
137 aprop_indexed = calloc(1, sizeof(rdata_aprop_indexed_t));
138 if (aprop_indexed == NULL) {
139 printf("Memory allocation failed.\n");
140 exit(1);
141 }
142
143 return aprop_indexed;
144}
145
146/** Allocate new property address.
147 *
148 * @param apc Property address class.
149 * @return New property address.
150 */
151rdata_addr_prop_t *rdata_addr_prop_new(aprop_class_t apc)
152{
153 rdata_addr_prop_t *addr_prop;
154
155 addr_prop = calloc(1, sizeof(rdata_addr_prop_t));
156 if (addr_prop == NULL) {
157 printf("Memory allocation failed.\n");
158 exit(1);
159 }
160
161 addr_prop->apc = apc;
162 return addr_prop;
163}
164
165/** Allocate new address.
166 *
167 * @param ac Address class.
168 * @return New address.
169 */
170rdata_address_t *rdata_address_new(address_class_t ac)
171{
172 rdata_address_t *address;
173
174 address = calloc(1, sizeof(rdata_address_t));
175 if (address == NULL) {
176 printf("Memory allocation failed.\n");
177 exit(1);
178 }
179
180 address->ac = ac;
181 return address;
182}
183
184/** Allocate new value.
185 *
186 * @return New value.
187 */
188rdata_value_t *rdata_value_new(void)
189{
190 rdata_value_t *value;
191
192 value = calloc(1, sizeof(rdata_value_t));
193 if (value == NULL) {
194 printf("Memory allocation failed.\n");
195 exit(1);
196 }
197
198 return value;
199}
200
201/** Allocate new var node.
202 *
203 * @param vc Var node class (varclass).
204 * @return New var node.
205 */
206rdata_var_t *rdata_var_new(var_class_t vc)
207{
208 rdata_var_t *var;
209
210 var = calloc(1, sizeof(rdata_var_t));
211 if (var == NULL) {
212 printf("Memory allocation failed.\n");
213 exit(1);
214 }
215
216 var->vc = vc;
217 return var;
218}
219
220/** Allocate new reference.
221 *
222 * @return New reference.
223 */
224rdata_ref_t *rdata_ref_new(void)
225{
226 rdata_ref_t *ref;
227
228 ref = calloc(1, sizeof(rdata_ref_t));
229 if (ref == NULL) {
230 printf("Memory allocation failed.\n");
231 exit(1);
232 }
233
234 return ref;
235}
236
237/** Allocate new delegate.
238 *
239 * @return New delegate.
240 */
241rdata_deleg_t *rdata_deleg_new(void)
242{
243 rdata_deleg_t *deleg;
244
245 deleg = calloc(1, sizeof(rdata_deleg_t));
246 if (deleg == NULL) {
247 printf("Memory allocation failed.\n");
248 exit(1);
249 }
250
251 return deleg;
252}
253
254/** Allocate new enum value.
255 *
256 * @return New enum value.
257 */
258rdata_enum_t *rdata_enum_new(void)
259{
260 rdata_enum_t *enum_v;
261
262 enum_v = calloc(1, sizeof(rdata_enum_t));
263 if (enum_v == NULL) {
264 printf("Memory allocation failed.\n");
265 exit(1);
266 }
267
268 return enum_v;
269}
270
271/** Allocate new array.
272 *
273 * @return New array.
274 */
275rdata_array_t *rdata_array_new(int rank)
276{
277 rdata_array_t *array;
278
279 array = calloc(1, sizeof(rdata_array_t));
280 if (array == NULL) {
281 printf("Memory allocation failed.\n");
282 exit(1);
283 }
284
285 array->rank = rank;
286 array->extent = calloc(rank, sizeof(int));
287 if (array == NULL) {
288 printf("Memory allocation failed.\n");
289 exit(1);
290 }
291
292 return array;
293}
294
295/** Allocate new object.
296 *
297 * @return New object.
298 */
299rdata_object_t *rdata_object_new(void)
300{
301 rdata_object_t *object;
302
303 object = calloc(1, sizeof(rdata_object_t));
304 if (object == NULL) {
305 printf("Memory allocation failed.\n");
306 exit(1);
307 }
308
309 return object;
310}
311
312/** Allocate new boolean.
313 *
314 * @return New boolean.
315 */
316rdata_bool_t *rdata_bool_new(void)
317{
318 rdata_bool_t *bool_v;
319
320 bool_v = calloc(1, sizeof(rdata_bool_t));
321 if (bool_v == NULL) {
322 printf("Memory allocation failed.\n");
323 exit(1);
324 }
325
326 return bool_v;
327}
328
329/** Allocate new character.
330 *
331 * @return New character.
332 */
333rdata_char_t *rdata_char_new(void)
334{
335 rdata_char_t *char_v;
336
337 char_v = calloc(1, sizeof(rdata_char_t));
338 if (char_v == NULL) {
339 printf("Memory allocation failed.\n");
340 exit(1);
341 }
342
343 return char_v;
344}
345
346/** Allocate new integer.
347 *
348 * @return New integer.
349 */
350rdata_int_t *rdata_int_new(void)
351{
352 rdata_int_t *int_v;
353
354 int_v = calloc(1, sizeof(rdata_int_t));
355 if (int_v == NULL) {
356 printf("Memory allocation failed.\n");
357 exit(1);
358 }
359
360 return int_v;
361}
362
363/** Allocate new string.
364 *
365 * @return New string.
366 */
367rdata_string_t *rdata_string_new(void)
368{
369 rdata_string_t *string_v;
370
371 string_v = calloc(1, sizeof(rdata_string_t));
372 if (string_v == NULL) {
373 printf("Memory allocation failed.\n");
374 exit(1);
375 }
376
377 return string_v;
378}
379
380/** Allocate new resource.
381 *
382 * @return New resource.
383 */
384rdata_resource_t *rdata_resource_new(void)
385{
386 rdata_resource_t *resource_v;
387
388 resource_v = calloc(1, sizeof(rdata_resource_t));
389 if (resource_v == NULL) {
390 printf("Memory allocation failed.\n");
391 exit(1);
392 }
393
394 return resource_v;
395}
396
397/** Allocate new symbol reference.
398 *
399 * @return New symbol reference.
400 */
401rdata_symbol_t *rdata_symbol_new(void)
402{
403 rdata_symbol_t *symbol_v;
404
405 symbol_v = calloc(1, sizeof(rdata_symbol_t));
406 if (symbol_v == NULL) {
407 printf("Memory allocation failed.\n");
408 exit(1);
409 }
410
411 return symbol_v;
412}
413
414/** Allocate array elements.
415 *
416 * Allocates var nodes for elements of @a array.
417 *
418 * @param array Array.
419 */
420void rdata_array_alloc_element(rdata_array_t *array)
421{
422 int dim, idx;
423
424 dim = rdata_array_get_dim(array);
425
426 array->element = calloc(dim, sizeof(rdata_var_t *));
427 if (array->element == NULL) {
428 printf("Memory allocation failed.\n");
429 exit(1);
430 }
431
432 for (idx = 0; idx < dim; ++idx) {
433 array->element[idx] = calloc(1, sizeof(rdata_var_t));
434 if (array->element[idx] == NULL) {
435 printf("Memory allocation failed.\n");
436 exit(1);
437 }
438 }
439}
440
441/** Get array dimension.
442 *
443 * Dimension is the total number of elements in an array, in other words,
444 * the product of all extents.
445 *
446 * @param array Array.
447 */
448static int rdata_array_get_dim(rdata_array_t *array)
449{
450 int didx, dim;
451
452 dim = 1;
453 for (didx = 0; didx < array->rank; ++didx)
454 dim = dim * array->extent[didx];
455
456 return dim;
457}
458
459/** Make copy of a variable.
460 *
461 * Creates a new var node that is an exact copy of an existing var node.
462 * This can be thought of as a shallow copy.
463 *
464 * @param src Source var node.
465 * @param dest Place to store pointer to new var node.
466 */
467void rdata_var_copy(rdata_var_t *src, rdata_var_t **dest)
468{
469 rdata_var_t *nvar;
470
471 nvar = rdata_var_new(src->vc);
472
473 switch (src->vc) {
474 case vc_bool:
475 rdata_bool_copy(src->u.bool_v, &nvar->u.bool_v);
476 break;
477 case vc_char:
478 rdata_char_copy(src->u.char_v, &nvar->u.char_v);
479 break;
480 case vc_int:
481 rdata_int_copy(src->u.int_v, &nvar->u.int_v);
482 break;
483 case vc_string:
484 rdata_string_copy(src->u.string_v, &nvar->u.string_v);
485 break;
486 case vc_ref:
487 rdata_ref_copy(src->u.ref_v, &nvar->u.ref_v);
488 break;
489 case vc_deleg:
490 rdata_deleg_copy(src->u.deleg_v, &nvar->u.deleg_v);
491 break;
492 case vc_enum:
493 rdata_enum_copy(src->u.enum_v, &nvar->u.enum_v);
494 break;
495 case vc_array:
496 rdata_array_copy(src->u.array_v, &nvar->u.array_v);
497 break;
498 case vc_object:
499 rdata_object_copy(src->u.object_v, &nvar->u.object_v);
500 break;
501 case vc_resource:
502 rdata_resource_copy(src->u.resource_v, &nvar->u.resource_v);
503 break;
504 case vc_symbol:
505 rdata_symbol_copy(src->u.symbol_v, &nvar->u.symbol_v);
506 break;
507 }
508
509 *dest = nvar;
510}
511
512/** Copy boolean.
513 *
514 * @param src Source boolean.
515 * @param dest Place to store pointer to new boolean.
516 */
517static void rdata_bool_copy(rdata_bool_t *src, rdata_bool_t **dest)
518{
519 *dest = rdata_bool_new();
520 (*dest)->value = src->value;
521}
522
523/** Copy character.
524 *
525 * @param src Source character.
526 * @param dest Place to store pointer to new character.
527 */
528static void rdata_char_copy(rdata_char_t *src, rdata_char_t **dest)
529{
530 *dest = rdata_char_new();
531 bigint_clone(&src->value, &(*dest)->value);
532}
533
534/** Copy integer.
535 *
536 * @param src Source integer.
537 * @param dest Place to store pointer to new integer.
538 */
539static void rdata_int_copy(rdata_int_t *src, rdata_int_t **dest)
540{
541 *dest = rdata_int_new();
542 bigint_clone(&src->value, &(*dest)->value);
543}
544
545/** Copy string.
546 *
547 * @param src Source string.
548 * @param dest Place to store pointer to new string.
549 */
550static void rdata_string_copy(rdata_string_t *src, rdata_string_t **dest)
551{
552 *dest = rdata_string_new();
553 (*dest)->value = src->value;
554}
555
556/** Copy reference.
557 *
558 * @param src Source reference.
559 * @param dest Place to store pointer to new reference.
560 */
561static void rdata_ref_copy(rdata_ref_t *src, rdata_ref_t **dest)
562{
563 *dest = rdata_ref_new();
564 (*dest)->vref = src->vref;
565}
566
567/** Copy delegate.
568 *
569 * @param src Source delegate.
570 * @param dest Place to store pointer to new delegate.
571 */
572static void rdata_deleg_copy(rdata_deleg_t *src, rdata_deleg_t **dest)
573{
574 *dest = rdata_deleg_new();
575 (*dest)->obj = src->obj;
576 (*dest)->sym = src->sym;
577}
578
579/** Copy enum value.
580 *
581 * @param src Source enum value.
582 * @param dest Place to store pointer to new enum value.
583 */
584static void rdata_enum_copy(rdata_enum_t *src, rdata_enum_t **dest)
585{
586 *dest = rdata_enum_new();
587 (*dest)->value = src->value;
588}
589
590/** Copy array.
591 *
592 * @param src Source array.
593 * @param dest Place to store pointer to new array.
594 */
595static void rdata_array_copy(rdata_array_t *src, rdata_array_t **dest)
596{
597 (void) src; (void) dest;
598 printf("Unimplemented: Copy array.\n");
599 exit(1);
600}
601
602/** Copy object.
603 *
604 * @param src Source object.
605 * @param dest Place to store pointer to new object.
606 */
607static void rdata_object_copy(rdata_object_t *src, rdata_object_t **dest)
608{
609 (void) src; (void) dest;
610 printf("Unimplemented: Copy object.\n");
611 abort();
612}
613
614/** Copy resource.
615 *
616 * @param src Source resource.
617 * @param dest Place to store pointer to new resource.
618 */
619static void rdata_resource_copy(rdata_resource_t *src, rdata_resource_t **dest)
620{
621 *dest = rdata_resource_new();
622 (*dest)->data = src->data;
623}
624
625/** Copy symbol.
626 *
627 * @param src Source symbol.
628 * @param dest Place to store pointer to new symbol.
629 */
630static void rdata_symbol_copy(rdata_symbol_t *src, rdata_symbol_t **dest)
631{
632 *dest = rdata_symbol_new();
633 (*dest)->sym = src->sym;
634}
635
636/** Read data from a variable.
637 *
638 * This copies data from the variable to a value item. Ideally any read access
639 * to a program variable should go through this function. (Keep in mind
640 * that although values are composed of var nodes internally, but are not
641 * variables per se. Therefore this function is not used to read from values)
642 *
643 * @param var Variable to read from (var node where it is stored).
644 * @param ritem Place to store pointer to new value item read from
645 * the variable.
646 */
647void rdata_var_read(rdata_var_t *var, rdata_item_t **ritem)
648{
649 rdata_value_t *value;
650 rdata_var_t *rvar;
651
652 /* Perform a shallow copy of @a var. */
653 rdata_var_copy(var, &rvar);
654
655 value = rdata_value_new();
656 value->var = rvar;
657 *ritem = rdata_item_new(ic_value);
658 (*ritem)->u.value = value;
659}
660
661/** Write data to a variable.
662 *
663 * This copies data to the variable from a value. Ideally any write access
664 * to a program variable should go through this function. (Keep in mind
665 * that even though values are composed of var nodes internally, but are not
666 * variables per se. Therefore this function is not used to write to values)
667 *
668 * @param var Variable to write to (var node where it is stored).
669 * @param value The value to write.
670 */
671void rdata_var_write(rdata_var_t *var, rdata_value_t *value)
672{
673 rdata_var_t *nvar;
674
675 /* Perform a shallow copy of @c value->var. */
676 rdata_var_copy(value->var, &nvar);
677
678 /* XXX do this in a prettier way. */
679
680 var->vc = nvar->vc;
681 switch (nvar->vc) {
682 case vc_bool: var->u.bool_v = nvar->u.bool_v; break;
683 case vc_char: var->u.char_v = nvar->u.char_v; break;
684 case vc_int: var->u.int_v = nvar->u.int_v; break;
685 case vc_string: var->u.string_v = nvar->u.string_v; break;
686 case vc_ref: var->u.ref_v = nvar->u.ref_v; break;
687 case vc_deleg: var->u.deleg_v = nvar->u.deleg_v; break;
688 case vc_enum: var->u.enum_v = nvar->u.enum_v; break;
689 case vc_array: var->u.array_v = nvar->u.array_v; break;
690 case vc_object: var->u.object_v = nvar->u.object_v; break;
691 case vc_resource: var->u.resource_v = nvar->u.resource_v; break;
692 case vc_symbol: var->u.symbol_v = nvar->u.symbol_v; break;
693 }
694
695 /* XXX We should free some stuff around here. */
696}
697
698/** Print data item in human-readable form.
699 *
700 * @param item Item to print.
701 */
702void rdata_item_print(rdata_item_t *item)
703{
704 if (item == NULL) {
705 printf("none");
706 return;
707 }
708
709 switch (item->ic) {
710 case ic_address:
711 printf("address:");
712 rdata_address_print(item->u.address);
713 break;
714 case ic_value:
715 printf("value:");
716 rdata_value_print(item->u.value);
717 break;
718 }
719}
720
721/** Print address in human-readable form.
722 *
723 * Actually this displays contents of the var node that is being addressed.
724 *
725 * XXX Maybe we should really rather print the address and not the data
726 * it is pointing to?
727 *
728 * @param item Address to print.
729 */
730static void rdata_address_print(rdata_address_t *address)
731{
732 switch (address->ac) {
733 case ac_var:
734 rdata_var_print(address->u.var_a->vref);
735 break;
736 case ac_prop:
737 printf("Warning: Unimplemented: Print property address.\n");
738 break;
739 }
740}
741
742/** Print value in human-readable form.
743 *
744 * @param value Value to print.
745 */
746void rdata_value_print(rdata_value_t *value)
747{
748 rdata_var_print(value->var);
749}
750
751/** Print contents of var node in human-readable form.
752 *
753 * @param item Var node to print.
754 */
755static void rdata_var_print(rdata_var_t *var)
756{
757 int val;
758
759 switch (var->vc) {
760 case vc_bool:
761 printf("bool(%s)", var->u.bool_v->value ? "true" : "false");
762 break;
763 case vc_char:
764 printf("char(");
765 if (bigint_get_value_int(&var->u.char_v->value, &val) == EOK)
766 printf("'%c'", val);
767 else
768 printf("???:x%x\n", (unsigned) val);
769 printf(")");
770 break;
771 case vc_int:
772 printf("int(");
773 bigint_print(&var->u.int_v->value);
774 printf(")");
775 break;
776 case vc_string:
777 printf("string(\"%s\")", var->u.string_v->value);
778 break;
779 case vc_ref:
780 if (var->u.ref_v->vref != NULL) {
781 printf("ref(");
782 rdata_var_print(var->u.ref_v->vref);
783 printf(")");
784 } else {
785 printf("nil");
786 }
787 break;
788 case vc_deleg:
789 printf("deleg(");
790 if (var->u.deleg_v->sym != NULL) {
791 if (var->u.deleg_v->obj != NULL) {
792 rdata_var_print(var->u.deleg_v->obj);
793 printf(",");
794 }
795 symbol_print_fqn(var->u.deleg_v->sym);
796 } else {
797 printf("nil");
798 }
799 printf(")");
800 break;
801 case vc_enum:
802 symbol_print_fqn(
803 enum_to_symbol(var->u.enum_v->value->outer_enum));
804 printf(".%s",
805 strtab_get_str(var->u.enum_v->value->name->sid));
806 break;
807 case vc_array:
808 printf("array");
809 break;
810 case vc_object:
811 printf("object");
812 break;
813 case vc_resource:
814 printf("resource(%p)", var->u.resource_v->data);
815 break;
816 case vc_symbol:
817 printf("symbol(");
818 if (var->u.symbol_v->sym != NULL) {
819 symbol_print_fqn(var->u.symbol_v->sym);
820 } else {
821 printf("nil");
822 }
823 printf(")");
824 break;
825 }
826}
Note: See TracBrowser for help on using the repository browser.