]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/common/hw-properties.c
sim: common: trim trailing whitespace
[thirdparty/binutils-gdb.git] / sim / common / hw-properties.c
CommitLineData
b85e4829
AC
1/* The common simulator framework for GDB, the GNU Debugger.
2
7b6bb8da 3 Copyright 2002, 2007, 2008, 2009, 2010, 2011 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
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
c906108c
SS
36/* property entries */
37
38struct 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
45void
46create_hw_property_data (struct hw *me)
47{
48}
49
50void
51delete_hw_property_data (struct hw *me)
52{
53}
54
55
56/* Device Properties: */
57
58static struct hw_property_data *
59find_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
75static void
76hw_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;
028f6515 88
c906108c
SS
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 }
028f6515 97
c906108c
SS
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;
028f6515 112
c906108c
SS
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
127static void
128hw_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
167static void
168clean_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
201void
202hw_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
240void
241hw_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
291const struct hw_property *
292hw_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
308const struct hw_property *
309hw_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
333void
334hw_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
344void
345hw_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
353const struct hw_property *
354hw_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
368void
369hw_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
380int
381hw_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
399void
400hw_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
413void
414hw_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);
6d519a46 419 HW_TRACE ((me, "hw_find_ihandle_runtime_property(property=%s)\n", property));
c906108c
SS
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
434void
435hw_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));
028f6515 443
c906108c
SS
444}
445#endif
446
447#if 0
448hw_instance *
449hw_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
473void
474hw_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
485signed_cell
486hw_find_integer_property (struct hw *me,
487 const char *property)
488{
489 const struct hw_property *node;
490 signed_cell integer;
6d519a46 491 HW_TRACE ((me, "hw_find_integer(property=%s)\n", property));
c906108c
SS
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
502int
503hw_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;
6d519a46 511 HW_TRACE ((me, "hw_find_integer(property=%s)\n", property));
028f6515 512
c906108c
SS
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;
028f6515 524
c906108c
SS
525 /* Find and convert the value */
526 cell = ((signed_cell*)node->array) + index;
527 *integer = BE2H_cell (*cell);
028f6515 528
c906108c
SS
529 return node->sizeof_array / sizeof_integer;
530}
531
532
533static unsigned_cell *
534unit_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
549static const unsigned_cell *
550cells_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
566static unsigned
567nr_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
576void
577hw_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;
028f6515 587
c906108c
SS
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 */
028f6515 597 cell = unit_address_to_cells (&range->parent_address, cell,
c906108c
SS
598 hw_unit_nr_address_cells (hw_parent (me)));
599 /* copy the size */
028f6515 600 cell = unit_address_to_cells (&range->size, cell,
c906108c
SS
601 hw_unit_nr_size_cells (me));
602 }
603 ASSERT (cell == &cells[nr_range_property_cells (me, nr_ranges)]);
028f6515 604
c906108c
SS
605 /* add it */
606 hw_add_property (me, property, range_array_property,
607 cells, sizeof_cells,
608 cells, sizeof_cells,
609 NULL, permenant_object);
028f6515 610
c906108c
SS
611 hw_free (me, cells);
612}
613
614int
615hw_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;
028f6515 624
c906108c
SS
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);
028f6515 631
c906108c
SS
632 /* aligned ? */
633 if ((node->sizeof_array % sizeof_entry) != 0)
634 hw_abort (me, "property \"%s\" contains an incomplete number of entries",
635 property);
028f6515 636
c906108c
SS
637 /* within bounds? */
638 if (node->sizeof_array < sizeof_entry * (index + 1))
639 return 0;
028f6515 640
c906108c
SS
641 /* find the range of interest */
642 cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index);
028f6515 643
c906108c
SS
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));
028f6515 647
c906108c
SS
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)));
028f6515 651
c906108c
SS
652 /* copy the size - converting as we go */
653 cells = cells_to_unit_address (cells, &range->size,
654 hw_unit_nr_size_cells (me));
028f6515 655
c906108c
SS
656 return node->sizeof_array / sizeof_entry;
657}
658
659
660static unsigned
661nr_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
669void
670hw_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;
028f6515 680
c906108c
SS
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)]);
028f6515 694
c906108c
SS
695 /* add it */
696 hw_add_property (me, property, reg_array_property,
697 cells, sizeof_cells,
698 cells, sizeof_cells,
699 NULL, permenant_object);
028f6515 700
c906108c
SS
701 hw_free (me, cells);
702}
703
704int
705hw_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;
028f6515 714
c906108c
SS
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);
028f6515 721
c906108c
SS
722 /* aligned ? */
723 if ((node->sizeof_array % sizeof_entry) != 0)
724 hw_abort (me, "property \"%s\" contains an incomplete number of entries",
725 property);
028f6515 726
c906108c
SS
727 /* within bounds? */
728 if (node->sizeof_array < sizeof_entry * (index + 1))
729 return 0;
028f6515 730
c906108c
SS
731 /* find the range of interest */
732 cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index);
028f6515 733
c906108c
SS
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)));
028f6515 737
c906108c
SS
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)));
028f6515 741
c906108c
SS
742 return node->sizeof_array / sizeof_entry;
743}
744
745
746void
747hw_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
757const char *
758hw_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
773void
774hw_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
810int
811hw_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
875void
876hw_add_duplicate_property (struct hw *me,
877 const char *property,
878 const struct hw_property *original)
879{
880 struct hw_property_data *master;
6d519a46 881 HW_TRACE ((me, "hw_add_duplicate_property(property=%s, ...)\n", property));
c906108c
SS
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}