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