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