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