]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/common/hw-properties.c
sim: common: trim trailing whitespace
[thirdparty/binutils-gdb.git] / sim / common / hw-properties.c
1 /* The common simulator framework for GDB, the GNU Debugger.
2
3 Copyright 2002, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4
5 Contributed by Andrew Cagney and Red Hat.
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21
22 #include "hw-main.h"
23 #include "hw-base.h"
24
25 #include "sim-io.h"
26 #include "sim-assert.h"
27
28 #ifdef HAVE_STRING_H
29 #include <string.h>
30 #else
31 #ifdef HAVE_STRINGS_H
32 #include <strings.h>
33 #endif
34 #endif
35
36 /* property entries */
37
38 struct hw_property_data {
39 struct hw_property_data *next;
40 struct hw_property *property;
41 const void *init_array;
42 unsigned sizeof_init_array;
43 };
44
45 void
46 create_hw_property_data (struct hw *me)
47 {
48 }
49
50 void
51 delete_hw_property_data (struct hw *me)
52 {
53 }
54
55
56 /* Device Properties: */
57
58 static struct hw_property_data *
59 find_property_data (struct hw *me,
60 const char *property)
61 {
62 struct hw_property_data *entry;
63 ASSERT (property != NULL);
64 entry = me->properties_of_hw;
65 while (entry != NULL)
66 {
67 if (strcmp (entry->property->name, property) == 0)
68 return entry;
69 entry = entry->next;
70 }
71 return NULL;
72 }
73
74
75 static void
76 hw_add_property (struct hw *me,
77 const char *property,
78 hw_property_type type,
79 const void *init_array,
80 unsigned sizeof_init_array,
81 const void *array,
82 unsigned sizeof_array,
83 const struct hw_property *original,
84 object_disposition disposition)
85 {
86 struct hw_property_data *new_entry = NULL;
87 struct hw_property *new_value = NULL;
88
89 /* find the list end */
90 struct hw_property_data **insertion_point = &me->properties_of_hw;
91 while (*insertion_point != NULL)
92 {
93 if (strcmp ((*insertion_point)->property->name, property) == 0)
94 return;
95 insertion_point = &(*insertion_point)->next;
96 }
97
98 /* create a new value */
99 new_value = HW_ZALLOC (me, struct hw_property);
100 new_value->name = (char *) strdup (property);
101 new_value->type = type;
102 if (sizeof_array > 0)
103 {
104 void *new_array = hw_zalloc (me, sizeof_array);
105 memcpy (new_array, array, sizeof_array);
106 new_value->array = new_array;
107 new_value->sizeof_array = sizeof_array;
108 }
109 new_value->owner = me;
110 new_value->original = original;
111 new_value->disposition = disposition;
112
113 /* insert the value into the list */
114 new_entry = HW_ZALLOC (me, struct hw_property_data);
115 *insertion_point = new_entry;
116 if (sizeof_init_array > 0)
117 {
118 void *new_init_array = hw_zalloc (me, sizeof_init_array);
119 memcpy (new_init_array, init_array, sizeof_init_array);
120 new_entry->init_array = new_init_array;
121 new_entry->sizeof_init_array = sizeof_init_array;
122 }
123 new_entry->property = new_value;
124 }
125
126
127 static void
128 hw_set_property (struct hw *me,
129 const char *property,
130 hw_property_type type,
131 const void *array,
132 int sizeof_array)
133 {
134 /* find the property */
135 struct hw_property_data *entry = find_property_data (me, property);
136 if (entry != NULL)
137 {
138 /* existing property - update it */
139 void *new_array = 0;
140 struct hw_property *value = entry->property;
141 /* check the type matches */
142 if (value->type != type)
143 hw_abort (me, "conflict between type of new and old value for property %s", property);
144 /* replace its value */
145 if (value->array != NULL)
146 hw_free (me, (void*)value->array);
147 new_array = (sizeof_array > 0
148 ? hw_zalloc (me, sizeof_array)
149 : (void*)0);
150 value->array = new_array;
151 value->sizeof_array = sizeof_array;
152 if (sizeof_array > 0)
153 memcpy (new_array, array, sizeof_array);
154 return;
155 }
156 else
157 {
158 /* new property - create it */
159 hw_add_property (me, property, type,
160 NULL, 0, array, sizeof_array,
161 NULL, temporary_object);
162 }
163 }
164
165
166 #if 0
167 static void
168 clean_hw_properties (struct hw *me)
169 {
170 struct hw_property_data **delete_point = &me->properties_of_hw;
171 while (*delete_point != NULL)
172 {
173 struct hw_property_data *current = *delete_point;
174 switch (current->property->disposition)
175 {
176 case permenant_object:
177 /* zap the current value, will be initialized later */
178 ASSERT (current->init_array != NULL);
179 if (current->property->array != NULL)
180 {
181 hw_free (me, (void*)current->property->array);
182 current->property->array = NULL;
183 }
184 delete_point = &(*delete_point)->next;
185 break;
186 case temporary_object:
187 /* zap the actual property, was created during simulation run */
188 ASSERT (current->init_array == NULL);
189 *delete_point = current->next;
190 if (current->property->array != NULL)
191 hw_free (me, (void*)current->property->array);
192 hw_free (me, current->property);
193 hw_free (me, current);
194 break;
195 }
196 }
197 }
198 #endif
199
200 #if 0
201 void
202 hw_init_static_properties (SIM_DESC sd,
203 struct hw *me,
204 void *data)
205 {
206 struct hw_property_data *property;
207 for (property = me->properties_of_hw;
208 property != NULL;
209 property = property->next)
210 {
211 ASSERT (property->init_array != NULL);
212 ASSERT (property->property->array == NULL);
213 ASSERT(property->property->disposition == permenant_object);
214 switch (property->property->type)
215 {
216 case array_property:
217 case boolean_property:
218 case range_array_property:
219 case reg_array_property:
220 case string_property:
221 case string_array_property:
222 case integer_property:
223 /* delete the property, and replace it with the original */
224 hw_set_property (me, property->property->name,
225 property->property->type,
226 property->init_array,
227 property->sizeof_init_array);
228 break;
229 #if 0
230 case ihandle_property:
231 break;
232 #endif
233 }
234 }
235 }
236 #endif
237
238
239 #if 0
240 void
241 hw_init_runtime_properties (SIM_DESC sd,
242 struct hw *me,
243 void *data)
244 {
245 struct hw_property_data *property;
246 for (property = me->properties_of_hw;
247 property != NULL;
248 property = property->next)
249 {
250 switch (property->property->disposition)
251 {
252 case permenant_object:
253 switch (property->property->type)
254 {
255 #if 0
256 case ihandle_property:
257 {
258 struct hw_instance *ihandle;
259 ihandle_runtime_property_spec spec;
260 ASSERT (property->init_array != NULL);
261 ASSERT (property->property->array == NULL);
262 hw_find_ihandle_runtime_property (me, property->property->name, &spec);
263 ihandle = tree_instance (me, spec.full_path);
264 hw_set_ihandle_property (me, property->property->name, ihandle);
265 break;
266 }
267 #endif
268 case array_property:
269 case boolean_property:
270 case range_array_property:
271 case integer_property:
272 case reg_array_property:
273 case string_property:
274 case string_array_property:
275 ASSERT (property->init_array != NULL);
276 ASSERT (property->property->array != NULL);
277 break;
278 }
279 break;
280 case temporary_object:
281 ASSERT (property->init_array == NULL);
282 ASSERT (property->property->array != NULL);
283 break;
284 }
285 }
286 }
287 #endif
288
289
290
291 const struct hw_property *
292 hw_next_property (const struct hw_property *property)
293 {
294 /* find the property in the list */
295 struct hw *owner = property->owner;
296 struct hw_property_data *entry = owner->properties_of_hw;
297 while (entry != NULL && entry->property != property)
298 entry = entry->next;
299 /* now return the following property */
300 ASSERT (entry != NULL); /* must be a member! */
301 if (entry->next != NULL)
302 return entry->next->property;
303 else
304 return NULL;
305 }
306
307
308 const struct hw_property *
309 hw_find_property (struct hw *me,
310 const char *property)
311 {
312 if (me == NULL)
313 {
314 return NULL;
315 }
316 else if (property == NULL || strcmp (property, "") == 0)
317 {
318 if (me->properties_of_hw == NULL)
319 return NULL;
320 else
321 return me->properties_of_hw->property;
322 }
323 else
324 {
325 struct hw_property_data *entry = find_property_data (me, property);
326 if (entry != NULL)
327 return entry->property;
328 }
329 return NULL;
330 }
331
332
333 void
334 hw_add_array_property (struct hw *me,
335 const char *property,
336 const void *array,
337 int sizeof_array)
338 {
339 hw_add_property (me, property, array_property,
340 array, sizeof_array, array, sizeof_array,
341 NULL, permenant_object);
342 }
343
344 void
345 hw_set_array_property (struct hw *me,
346 const char *property,
347 const void *array,
348 int sizeof_array)
349 {
350 hw_set_property (me, property, array_property, array, sizeof_array);
351 }
352
353 const struct hw_property *
354 hw_find_array_property (struct hw *me,
355 const char *property)
356 {
357 const struct hw_property *node;
358 node = hw_find_property (me, property);
359 if (node == NULL)
360 hw_abort (me, "property \"%s\" not found", property);
361 if (node->type != array_property)
362 hw_abort (me, "property \"%s\" of wrong type (array)", property);
363 return node;
364 }
365
366
367
368 void
369 hw_add_boolean_property (struct hw *me,
370 const char *property,
371 int boolean)
372 {
373 signed32 new_boolean = (boolean ? -1 : 0);
374 hw_add_property (me, property, boolean_property,
375 &new_boolean, sizeof(new_boolean),
376 &new_boolean, sizeof(new_boolean),
377 NULL, permenant_object);
378 }
379
380 int
381 hw_find_boolean_property (struct hw *me,
382 const char *property)
383 {
384 const struct hw_property *node;
385 unsigned_cell boolean;
386 node = hw_find_property (me, property);
387 if (node == NULL)
388 hw_abort (me, "property \"%s\" not found", property);
389 if (node->type != boolean_property)
390 hw_abort (me, "property \"%s\" of wrong type (boolean)", property);
391 ASSERT (sizeof (boolean) == node->sizeof_array);
392 memcpy (&boolean, node->array, sizeof (boolean));
393 return boolean;
394 }
395
396
397
398 #if 0
399 void
400 hw_add_ihandle_runtime_property (struct hw *me,
401 const char *property,
402 const ihandle_runtime_property_spec *ihandle)
403 {
404 /* enter the full path as the init array */
405 hw_add_property (me, property, ihandle_property,
406 ihandle->full_path, strlen(ihandle->full_path) + 1,
407 NULL, 0,
408 NULL, permenant_object);
409 }
410 #endif
411
412 #if 0
413 void
414 hw_find_ihandle_runtime_property (struct hw *me,
415 const char *property,
416 ihandle_runtime_property_spec *ihandle)
417 {
418 struct hw_property_data *entry = find_property_data (me, property);
419 HW_TRACE ((me, "hw_find_ihandle_runtime_property(property=%s)\n", property));
420 if (entry == NULL)
421 hw_abort (me, "property \"%s\" not found", property);
422 if (entry->property->type != ihandle_property
423 || entry->property->disposition != permenant_object)
424 hw_abort (me, "property \"%s\" of wrong type", property);
425 ASSERT (entry->init_array != NULL);
426 /* the full path */
427 ihandle->full_path = entry->init_array;
428 }
429 #endif
430
431
432
433 #if 0
434 void
435 hw_set_ihandle_property (struct hw *me,
436 const char *property,
437 hw_instance *ihandle)
438 {
439 unsigned_cell cells;
440 cells = H2BE_cell (hw_instance_to_external (ihandle));
441 hw_set_property (me, property, ihandle_property,
442 &cells, sizeof (cells));
443
444 }
445 #endif
446
447 #if 0
448 hw_instance *
449 hw_find_ihandle_property (struct hw *me,
450 const char *property)
451 {
452 const hw_property_data *node;
453 unsigned_cell ihandle;
454 hw_instance *instance;
455
456 node = hw_find_property (me, property);
457 if (node == NULL)
458 hw_abort (me, "property \"%s\" not found", property);
459 if (node->type != ihandle_property)
460 hw_abort(me, "property \"%s\" of wrong type (ihandle)", property);
461 if (node->array == NULL)
462 hw_abort(me, "runtime property \"%s\" not yet initialized", property);
463
464 ASSERT (sizeof(ihandle) == node->sizeof_array);
465 memcpy (&ihandle, node->array, sizeof(ihandle));
466 instance = external_to_hw_instance (me, BE2H_cell(ihandle));
467 ASSERT (instance != NULL);
468 return instance;
469 }
470 #endif
471
472
473 void
474 hw_add_integer_property (struct hw *me,
475 const char *property,
476 signed_cell integer)
477 {
478 H2BE (integer);
479 hw_add_property (me, property, integer_property,
480 &integer, sizeof(integer),
481 &integer, sizeof(integer),
482 NULL, permenant_object);
483 }
484
485 signed_cell
486 hw_find_integer_property (struct hw *me,
487 const char *property)
488 {
489 const struct hw_property *node;
490 signed_cell integer;
491 HW_TRACE ((me, "hw_find_integer(property=%s)\n", property));
492 node = hw_find_property (me, property);
493 if (node == NULL)
494 hw_abort (me, "property \"%s\" not found", property);
495 if (node->type != integer_property)
496 hw_abort (me, "property \"%s\" of wrong type (integer)", property);
497 ASSERT (sizeof(integer) == node->sizeof_array);
498 memcpy (&integer, node->array, sizeof (integer));
499 return BE2H_cell (integer);
500 }
501
502 int
503 hw_find_integer_array_property (struct hw *me,
504 const char *property,
505 unsigned index,
506 signed_cell *integer)
507 {
508 const struct hw_property *node;
509 int sizeof_integer = sizeof (*integer);
510 signed_cell *cell;
511 HW_TRACE ((me, "hw_find_integer(property=%s)\n", property));
512
513 /* check things sane */
514 node = hw_find_property (me, property);
515 if (node == NULL)
516 hw_abort (me, "property \"%s\" not found", property);
517 if (node->type != integer_property
518 && node->type != array_property)
519 hw_abort (me, "property \"%s\" of wrong type (integer or array)", property);
520 if ((node->sizeof_array % sizeof_integer) != 0)
521 hw_abort (me, "property \"%s\" contains an incomplete number of cells", property);
522 if (node->sizeof_array <= sizeof_integer * index)
523 return 0;
524
525 /* Find and convert the value */
526 cell = ((signed_cell*)node->array) + index;
527 *integer = BE2H_cell (*cell);
528
529 return node->sizeof_array / sizeof_integer;
530 }
531
532
533 static unsigned_cell *
534 unit_address_to_cells (const hw_unit *unit,
535 unsigned_cell *cell,
536 int nr_cells)
537 {
538 int i;
539 ASSERT(nr_cells == unit->nr_cells);
540 for (i = 0; i < unit->nr_cells; i++)
541 {
542 *cell = H2BE_cell (unit->cells[i]);
543 cell += 1;
544 }
545 return cell;
546 }
547
548
549 static const unsigned_cell *
550 cells_to_unit_address (const unsigned_cell *cell,
551 hw_unit *unit,
552 int nr_cells)
553 {
554 int i;
555 memset(unit, 0, sizeof(*unit));
556 unit->nr_cells = nr_cells;
557 for (i = 0; i < unit->nr_cells; i++)
558 {
559 unit->cells[i] = BE2H_cell (*cell);
560 cell += 1;
561 }
562 return cell;
563 }
564
565
566 static unsigned
567 nr_range_property_cells (struct hw *me,
568 int nr_ranges)
569 {
570 return ((hw_unit_nr_address_cells (me)
571 + hw_unit_nr_address_cells (hw_parent (me))
572 + hw_unit_nr_size_cells (me))
573 ) * nr_ranges;
574 }
575
576 void
577 hw_add_range_array_property (struct hw *me,
578 const char *property,
579 const range_property_spec *ranges,
580 unsigned nr_ranges)
581 {
582 unsigned sizeof_cells = (nr_range_property_cells (me, nr_ranges)
583 * sizeof (unsigned_cell));
584 unsigned_cell *cells = hw_zalloc (me, sizeof_cells);
585 unsigned_cell *cell;
586 int i;
587
588 /* copy the property elements over */
589 cell = cells;
590 for (i = 0; i < nr_ranges; i++)
591 {
592 const range_property_spec *range = &ranges[i];
593 /* copy the child address */
594 cell = unit_address_to_cells (&range->child_address, cell,
595 hw_unit_nr_address_cells (me));
596 /* copy the parent address */
597 cell = unit_address_to_cells (&range->parent_address, cell,
598 hw_unit_nr_address_cells (hw_parent (me)));
599 /* copy the size */
600 cell = unit_address_to_cells (&range->size, cell,
601 hw_unit_nr_size_cells (me));
602 }
603 ASSERT (cell == &cells[nr_range_property_cells (me, nr_ranges)]);
604
605 /* add it */
606 hw_add_property (me, property, range_array_property,
607 cells, sizeof_cells,
608 cells, sizeof_cells,
609 NULL, permenant_object);
610
611 hw_free (me, cells);
612 }
613
614 int
615 hw_find_range_array_property (struct hw *me,
616 const char *property,
617 unsigned index,
618 range_property_spec *range)
619 {
620 const struct hw_property *node;
621 unsigned sizeof_entry = (nr_range_property_cells (me, 1)
622 * sizeof (unsigned_cell));
623 const unsigned_cell *cells;
624
625 /* locate the property */
626 node = hw_find_property (me, property);
627 if (node == NULL)
628 hw_abort (me, "property \"%s\" not found", property);
629 if (node->type != range_array_property)
630 hw_abort (me, "property \"%s\" of wrong type (range array)", property);
631
632 /* aligned ? */
633 if ((node->sizeof_array % sizeof_entry) != 0)
634 hw_abort (me, "property \"%s\" contains an incomplete number of entries",
635 property);
636
637 /* within bounds? */
638 if (node->sizeof_array < sizeof_entry * (index + 1))
639 return 0;
640
641 /* find the range of interest */
642 cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index);
643
644 /* copy the child address out - converting as we go */
645 cells = cells_to_unit_address (cells, &range->child_address,
646 hw_unit_nr_address_cells (me));
647
648 /* copy the parent address out - converting as we go */
649 cells = cells_to_unit_address (cells, &range->parent_address,
650 hw_unit_nr_address_cells (hw_parent (me)));
651
652 /* copy the size - converting as we go */
653 cells = cells_to_unit_address (cells, &range->size,
654 hw_unit_nr_size_cells (me));
655
656 return node->sizeof_array / sizeof_entry;
657 }
658
659
660 static unsigned
661 nr_reg_property_cells (struct hw *me,
662 int nr_regs)
663 {
664 return (hw_unit_nr_address_cells (hw_parent(me))
665 + hw_unit_nr_size_cells (hw_parent(me))
666 ) * nr_regs;
667 }
668
669 void
670 hw_add_reg_array_property (struct hw *me,
671 const char *property,
672 const reg_property_spec *regs,
673 unsigned nr_regs)
674 {
675 unsigned sizeof_cells = (nr_reg_property_cells (me, nr_regs)
676 * sizeof (unsigned_cell));
677 unsigned_cell *cells = hw_zalloc (me, sizeof_cells);
678 unsigned_cell *cell;
679 int i;
680
681 /* copy the property elements over */
682 cell = cells;
683 for (i = 0; i < nr_regs; i++)
684 {
685 const reg_property_spec *reg = &regs[i];
686 /* copy the address */
687 cell = unit_address_to_cells (&reg->address, cell,
688 hw_unit_nr_address_cells (hw_parent (me)));
689 /* copy the size */
690 cell = unit_address_to_cells (&reg->size, cell,
691 hw_unit_nr_size_cells (hw_parent (me)));
692 }
693 ASSERT (cell == &cells[nr_reg_property_cells (me, nr_regs)]);
694
695 /* add it */
696 hw_add_property (me, property, reg_array_property,
697 cells, sizeof_cells,
698 cells, sizeof_cells,
699 NULL, permenant_object);
700
701 hw_free (me, cells);
702 }
703
704 int
705 hw_find_reg_array_property (struct hw *me,
706 const char *property,
707 unsigned index,
708 reg_property_spec *reg)
709 {
710 const struct hw_property *node;
711 unsigned sizeof_entry = (nr_reg_property_cells (me, 1)
712 * sizeof (unsigned_cell));
713 const unsigned_cell *cells;
714
715 /* locate the property */
716 node = hw_find_property (me, property);
717 if (node == NULL)
718 hw_abort (me, "property \"%s\" not found", property);
719 if (node->type != reg_array_property)
720 hw_abort (me, "property \"%s\" of wrong type (reg array)", property);
721
722 /* aligned ? */
723 if ((node->sizeof_array % sizeof_entry) != 0)
724 hw_abort (me, "property \"%s\" contains an incomplete number of entries",
725 property);
726
727 /* within bounds? */
728 if (node->sizeof_array < sizeof_entry * (index + 1))
729 return 0;
730
731 /* find the range of interest */
732 cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index);
733
734 /* copy the address out - converting as we go */
735 cells = cells_to_unit_address (cells, &reg->address,
736 hw_unit_nr_address_cells (hw_parent (me)));
737
738 /* copy the size out - converting as we go */
739 cells = cells_to_unit_address (cells, &reg->size,
740 hw_unit_nr_size_cells (hw_parent (me)));
741
742 return node->sizeof_array / sizeof_entry;
743 }
744
745
746 void
747 hw_add_string_property (struct hw *me,
748 const char *property,
749 const char *string)
750 {
751 hw_add_property (me, property, string_property,
752 string, strlen(string) + 1,
753 string, strlen(string) + 1,
754 NULL, permenant_object);
755 }
756
757 const char *
758 hw_find_string_property (struct hw *me,
759 const char *property)
760 {
761 const struct hw_property *node;
762 const char *string;
763 node = hw_find_property (me, property);
764 if (node == NULL)
765 hw_abort (me, "property \"%s\" not found", property);
766 if (node->type != string_property)
767 hw_abort (me, "property \"%s\" of wrong type (string)", property);
768 string = node->array;
769 ASSERT (strlen(string) + 1 == node->sizeof_array);
770 return string;
771 }
772
773 void
774 hw_add_string_array_property (struct hw *me,
775 const char *property,
776 const string_property_spec *strings,
777 unsigned nr_strings)
778 {
779 int sizeof_array;
780 int string_nr;
781 char *array;
782 char *chp;
783 if (nr_strings == 0)
784 hw_abort (me, "property \"%s\" must be non-null", property);
785 /* total up the size of the needed array */
786 for (sizeof_array = 0, string_nr = 0;
787 string_nr < nr_strings;
788 string_nr ++)
789 {
790 sizeof_array += strlen (strings[string_nr]) + 1;
791 }
792 /* create the array */
793 array = (char*) hw_zalloc (me, sizeof_array);
794 chp = array;
795 for (string_nr = 0;
796 string_nr < nr_strings;
797 string_nr++)
798 {
799 strcpy (chp, strings[string_nr]);
800 chp += strlen (chp) + 1;
801 }
802 ASSERT (chp == array + sizeof_array);
803 /* now enter it */
804 hw_add_property (me, property, string_array_property,
805 array, sizeof_array,
806 array, sizeof_array,
807 NULL, permenant_object);
808 }
809
810 int
811 hw_find_string_array_property (struct hw *me,
812 const char *property,
813 unsigned index,
814 string_property_spec *string)
815 {
816 const struct hw_property *node;
817 node = hw_find_property (me, property);
818 if (node == NULL)
819 hw_abort (me, "property \"%s\" not found", property);
820 switch (node->type)
821 {
822 default:
823 hw_abort (me, "property \"%s\" of wrong type", property);
824 break;
825 case string_property:
826 if (index == 0)
827 {
828 *string = node->array;
829 ASSERT (strlen(*string) + 1 == node->sizeof_array);
830 return 1;
831 }
832 break;
833 case array_property:
834 if (node->sizeof_array == 0
835 || ((char*)node->array)[node->sizeof_array - 1] != '\0')
836 hw_abort (me, "property \"%s\" invalid for string array", property);
837 /* FALL THROUGH */
838 case string_array_property:
839 ASSERT (node->sizeof_array > 0);
840 ASSERT (((char*)node->array)[node->sizeof_array - 1] == '\0');
841 {
842 const char *chp = node->array;
843 int nr_entries = 0;
844 /* count the number of strings, keeping an eye out for the one
845 we're looking for */
846 *string = chp;
847 do
848 {
849 if (*chp == '\0')
850 {
851 /* next string */
852 nr_entries++;
853 chp++;
854 if (nr_entries == index)
855 *string = chp;
856 }
857 else
858 {
859 chp++;
860 }
861 } while (chp < (char*)node->array + node->sizeof_array);
862 if (index < nr_entries)
863 return nr_entries;
864 else
865 {
866 *string = NULL;
867 return 0;
868 }
869 }
870 break;
871 }
872 return 0;
873 }
874
875 void
876 hw_add_duplicate_property (struct hw *me,
877 const char *property,
878 const struct hw_property *original)
879 {
880 struct hw_property_data *master;
881 HW_TRACE ((me, "hw_add_duplicate_property(property=%s, ...)\n", property));
882 if (original->disposition != permenant_object)
883 hw_abort (me, "Can only duplicate permenant objects");
884 /* find the original's master */
885 master = original->owner->properties_of_hw;
886 while (master->property != original)
887 {
888 master = master->next;
889 ASSERT(master != NULL);
890 }
891 /* now duplicate it */
892 hw_add_property (me, property,
893 original->type,
894 master->init_array, master->sizeof_init_array,
895 original->array, original->sizeof_array,
896 original, permenant_object);
897 }