sim: clean up C11 header includes
[deliverable/binutils-gdb.git] / sim / common / hw-properties.c
1 /* The common simulator framework for GDB, the GNU Debugger.
2
3 Copyright 2002-2021 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 #include <string.h>
29
30 /* property entries */
31
32 struct hw_property_data
33 {
34 struct hw_property_data *next;
35 struct hw_property *property;
36 const void *init_array;
37 unsigned sizeof_init_array;
38 };
39
40 void
41 create_hw_property_data (struct hw *me)
42 {
43 }
44
45 void
46 delete_hw_property_data (struct hw *me)
47 {
48 }
49
50
51 /* Device Properties: */
52
53 static struct hw_property_data *
54 find_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
70 static void
71 hw_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;
83
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 }
92
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;
107
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
122 static void
123 hw_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
162 static void
163 clean_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
196 void
197 hw_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);
208 ASSERT (property->property->disposition == permenant_object);
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
235 void
236 hw_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
286 const struct hw_property *
287 hw_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
303 const struct hw_property *
304 hw_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
328 void
329 hw_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
339 void
340 hw_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
348 const struct hw_property *
349 hw_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
363 void
364 hw_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,
370 &new_boolean, sizeof (new_boolean),
371 &new_boolean, sizeof (new_boolean),
372 NULL, permenant_object);
373 }
374
375 int
376 hw_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
394 void
395 hw_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,
401 ihandle->full_path, strlen (ihandle->full_path) + 1,
402 NULL, 0,
403 NULL, permenant_object);
404 }
405 #endif
406
407 #if 0
408 void
409 hw_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);
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
428 void
429 hw_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));
437
438 }
439 #endif
440
441 #if 0
442 hw_instance *
443 hw_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)
454 hw_abort (me, "property \"%s\" of wrong type (ihandle)", property);
455 if (node->array == NULL)
456 hw_abort (me, "runtime property \"%s\" not yet initialized", property);
457
458 ASSERT (sizeof (ihandle) == node->sizeof_array);
459 memcpy (&ihandle, node->array, sizeof (ihandle));
460 instance = external_to_hw_instance (me, BE2H_cell (ihandle));
461 ASSERT (instance != NULL);
462 return instance;
463 }
464 #endif
465
466
467 void
468 hw_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,
474 &integer, sizeof (integer),
475 &integer, sizeof (integer),
476 NULL, permenant_object);
477 }
478
479 signed_cell
480 hw_find_integer_property (struct hw *me,
481 const char *property)
482 {
483 const struct hw_property *node;
484 signed_cell integer;
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);
490 ASSERT (sizeof (integer) == node->sizeof_array);
491 memcpy (&integer, node->array, sizeof (integer));
492 return BE2H_cell (integer);
493 }
494
495 int
496 hw_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;
504
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;
516
517 /* Find and convert the value */
518 cell = ((signed_cell*)node->array) + index;
519 *integer = BE2H_cell (*cell);
520
521 return node->sizeof_array / sizeof_integer;
522 }
523
524
525 static unsigned_cell *
526 unit_address_to_cells (const hw_unit *unit,
527 unsigned_cell *cell,
528 int nr_cells)
529 {
530 int i;
531 ASSERT (nr_cells == unit->nr_cells);
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
541 static const unsigned_cell *
542 cells_to_unit_address (const unsigned_cell *cell,
543 hw_unit *unit,
544 int nr_cells)
545 {
546 int i;
547 memset (unit, 0, sizeof (*unit));
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
558 static unsigned
559 nr_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
568 void
569 hw_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;
579
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 */
589 cell = unit_address_to_cells (&range->parent_address, cell,
590 hw_unit_nr_address_cells (hw_parent (me)));
591 /* copy the size */
592 cell = unit_address_to_cells (&range->size, cell,
593 hw_unit_nr_size_cells (me));
594 }
595 ASSERT (cell == &cells[nr_range_property_cells (me, nr_ranges)]);
596
597 /* add it */
598 hw_add_property (me, property, range_array_property,
599 cells, sizeof_cells,
600 cells, sizeof_cells,
601 NULL, permenant_object);
602
603 hw_free (me, cells);
604 }
605
606 int
607 hw_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;
616
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);
623
624 /* aligned ? */
625 if ((node->sizeof_array % sizeof_entry) != 0)
626 hw_abort (me, "property \"%s\" contains an incomplete number of entries",
627 property);
628
629 /* within bounds? */
630 if (node->sizeof_array < sizeof_entry * (index + 1))
631 return 0;
632
633 /* find the range of interest */
634 cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index);
635
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));
639
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)));
643
644 /* copy the size - converting as we go */
645 cells = cells_to_unit_address (cells, &range->size,
646 hw_unit_nr_size_cells (me));
647
648 return node->sizeof_array / sizeof_entry;
649 }
650
651
652 static unsigned
653 nr_reg_property_cells (struct hw *me,
654 int nr_regs)
655 {
656 return (hw_unit_nr_address_cells (hw_parent (me))
657 + hw_unit_nr_size_cells (hw_parent (me))
658 ) * nr_regs;
659 }
660
661 void
662 hw_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;
672
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)]);
686
687 /* add it */
688 hw_add_property (me, property, reg_array_property,
689 cells, sizeof_cells,
690 cells, sizeof_cells,
691 NULL, permenant_object);
692
693 hw_free (me, cells);
694 }
695
696 int
697 hw_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;
706
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);
713
714 /* aligned ? */
715 if ((node->sizeof_array % sizeof_entry) != 0)
716 hw_abort (me, "property \"%s\" contains an incomplete number of entries",
717 property);
718
719 /* within bounds? */
720 if (node->sizeof_array < sizeof_entry * (index + 1))
721 return 0;
722
723 /* find the range of interest */
724 cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index);
725
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)));
729
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)));
733
734 return node->sizeof_array / sizeof_entry;
735 }
736
737
738 void
739 hw_add_string_property (struct hw *me,
740 const char *property,
741 const char *string)
742 {
743 hw_add_property (me, property, string_property,
744 string, strlen (string) + 1,
745 string, strlen (string) + 1,
746 NULL, permenant_object);
747 }
748
749 const char *
750 hw_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;
761 ASSERT (strlen (string) + 1 == node->sizeof_array);
762 return string;
763 }
764
765 void
766 hw_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
802 int
803 hw_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;
821 ASSERT (strlen (*string) + 1 == node->sizeof_array);
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
867 void
868 hw_add_duplicate_property (struct hw *me,
869 const char *property,
870 const struct hw_property *original)
871 {
872 struct hw_property_data *master;
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;
880 ASSERT (master != NULL);
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 }
This page took 0.047775 seconds and 4 git commands to generate.