etc/services - sync with NetBSD-8
[minix.git] / minix / lib / libmagicrt / magic_selement.c
blobbbe93784bdee1163eb5a46e19a3a7ad16d9fadcf
1 #include <magic_selement.h>
3 /*===========================================================================*
4 * magic_selement_lookup_by_name *
5 *===========================================================================*/
6 PUBLIC int magic_selement_lookup_by_name(char *name,
7 _magic_selement_t *selement, struct _magic_dsentry *dsentry_buff)
9 char token_buff[MAGIC_MAX_NAME_LEN * 2 + 2];
10 char *token_start = name;
11 int last_num_seps = 0;
12 char *s;
13 if (!name || *name == '\0' || *name == MAGIC_SELEMENT_SEP[0]) {
14 return MAGIC_ENOENT;
16 for (s = name; *s; s++) {
17 if (*(s + 1) == '\0' || *(s + 1) == MAGIC_SELEMENT_SEP[0]) {
18 size_t len = s - token_start + 1;
19 if (len >= MAGIC_MAX_NAME_LEN * 2 + 1) {
20 return MAGIC_ENOMEM;
22 strncpy(token_buff, token_start, len);
23 token_buff[len] = '\0';
24 if (token_start == name) {
25 struct _magic_sentry *sentry;
26 const char *sentry_parent_name = "", *sentry_name = NULL;
27 char *delim = NULL;
28 _magic_id_t dsentry_site_id = MAGIC_DSENTRY_SITE_ID_NULL;
29 if (!(delim = strchr(token_buff, MAGIC_DSENTRY_ABS_NAME_SEP[0]))) {
30 /* Regular sentry, no parent name or site_id. */
31 sentry_name = token_buff;
32 } else {
34 * Dsentry. Will contain: sentry_id<DELIM>parent_name<DELIM>name<DELIM>site_id.
36 *delim = '\0';
37 /* Skip sentry_id */
38 sentry_parent_name = delim + 1;
39 delim = strchr(delim + 1, MAGIC_DSENTRY_ABS_NAME_SEP[0]);
40 assert(!delim && "No dsentry name found in selement name!");
41 *delim = '\0';
42 sentry_name = delim + 1;
43 delim = strchr(delim + 1, MAGIC_DSENTRY_ABS_NAME_SEP[0]);
44 assert(!delim && "No dsentry site id found in selement name!");
45 *delim = '\0';
46 dsentry_site_id = strtoul((const char*)delim+1, NULL, 10);
49 sentry = magic_sentry_lookup_by_name(sentry_parent_name, sentry_name,
50 dsentry_site_id, dsentry_buff);
51 if (!sentry) {
52 return MAGIC_ENOENT;
54 magic_selement_from_sentry(sentry, selement);
56 else {
57 _magic_selement_t child_selement;
58 if (!magic_selement_from_relative_name(selement, &child_selement, token_buff)) {
59 return MAGIC_ENOENT;
61 *selement = child_selement;
63 s++;
64 last_num_seps = 0;
65 while (*s == MAGIC_SELEMENT_SEP[0]) {
66 s++;
67 last_num_seps++;
69 token_start = s;
70 s--;
73 if (last_num_seps > 0 && selement->type->type_id == MAGIC_TYPE_POINTER) {
74 int steps = magic_selement_recurse_ptr(selement, selement, last_num_seps);
75 if(steps != last_num_seps) {
76 return MAGIC_EINVAL;
80 return 0;
83 /*===========================================================================*
84 * magic_selement_name_print_cb *
85 *===========================================================================*/
86 PUBLIC int magic_selement_name_print_cb(const struct _magic_type* parent_type,
87 const unsigned parent_offset, int child_num,
88 const struct _magic_type* type, const unsigned offset, int depth, void* cb_args)
90 _magic_selement_t *selement = (_magic_selement_t*) cb_args;
91 struct _magic_sentry* sentry = selement->sentry;
92 void *address = (char*)sentry->address + offset;
93 void *range[2];
94 MAGIC_RANGE_SET_MIN(range, address);
95 MAGIC_RANGE_SET_MAX(range, (char*) address + type->size-1);
96 if(!MAGIC_ADDR_IS_IN_RANGE(selement->address, range)) {
97 return MAGIC_TYPE_WALK_SKIP_PATH;
99 if(address == sentry->address && type == sentry->type) {
100 magic_print_sentry_abs_name(sentry);
102 else {
103 short is_parent_array = parent_type->type_id == MAGIC_TYPE_ARRAY || parent_type->type_id == MAGIC_TYPE_VECTOR;
104 if(is_parent_array) {
105 _magic_printf("%s%d", MAGIC_SELEMENT_SEP, child_num);
107 else {
108 _magic_printf("%s%s", MAGIC_SELEMENT_SEP, parent_type->member_names[child_num]);
111 if(type->num_child_types == 0
112 || (address == selement->address && type == selement->type)) {
113 return MAGIC_TYPE_WALK_STOP;
115 return MAGIC_TYPE_WALK_CONTINUE;
118 /*===========================================================================*
119 * magic_selement_name_get_cb *
120 *===========================================================================*/
121 PUBLIC int magic_selement_name_get_cb(const struct _magic_type *parent_type,
122 const unsigned parent_offset, int child_num, const struct _magic_type *type,
123 const unsigned offset, int depth, void *args_array)
125 void **cb_args = (void **) args_array;
127 _magic_selement_t *selement = (_magic_selement_t*) cb_args[0];
128 char **buf = (char **) cb_args + 1;
129 int count, *buf_size = (int *) cb_args + 2;
131 short is_array = type->type_id == MAGIC_TYPE_ARRAY || type->type_id == MAGIC_TYPE_VECTOR;
133 struct _magic_sentry *sentry = selement->sentry;
134 void *address = (char *)sentry->address + offset;
135 void *range[2];
136 MAGIC_RANGE_SET_MIN(range, address);
137 MAGIC_RANGE_SET_MAX(range, (char *) address + type->size - 1);
138 if (!MAGIC_ADDR_IS_IN_RANGE(selement->address, range)) {
139 return MAGIC_TYPE_WALK_SKIP_PATH;
142 if (address == sentry->address && type == sentry->type) {
143 if (!(sentry->flags & MAGIC_STATE_DYNAMIC)) {
144 count = snprintf(*buf, *buf_size, "%s", sentry->name);
145 if (count >= *buf_size) return MAGIC_TYPE_WALK_STOP; /* Buffer too small. */
146 *buf += count;
147 *buf_size -= count;
148 } else {
149 struct _magic_dsentry *dsentry = MAGIC_DSENTRY_FROM_SENTRY(sentry);
150 assert(dsentry->parent_name && strcmp(dsentry->parent_name, ""));
151 assert(sentry->name && strcmp(sentry->name, ""));
152 count = snprintf(*buf, *buf_size, "%lu%s%s%s%s%s" MAGIC_ID_FORMAT,
153 (unsigned long)MAGIC_SENTRY_ID(sentry), MAGIC_DSENTRY_ABS_NAME_SEP,
154 dsentry->parent_name, MAGIC_DSENTRY_ABS_NAME_SEP, sentry->name,
155 MAGIC_DSENTRY_ABS_NAME_SEP, dsentry->site_id);
156 if (count >= *buf_size) return MAGIC_TYPE_WALK_STOP; /* Buffer too small. */
157 *buf += count;
158 *buf_size -= count;
160 } else {
161 short is_parent_array = parent_type->type_id == MAGIC_TYPE_ARRAY ||
162 parent_type->type_id == MAGIC_TYPE_VECTOR;
163 if (is_parent_array) {
164 count = snprintf(*buf, *buf_size, "%s%d",
165 MAGIC_SELEMENT_SEP, child_num);
166 if (count >= *buf_size) return MAGIC_TYPE_WALK_STOP; /* Buffer too small. */
167 *buf += count;
168 *buf_size -= count;
169 } else {
170 count = snprintf(*buf, *buf_size, "%s%s",
171 MAGIC_SELEMENT_SEP, parent_type->member_names[child_num]);
172 if (count >= *buf_size) return MAGIC_TYPE_WALK_STOP; /* Buffer too small. */
173 *buf += count;
174 *buf_size -= count;
178 if (type->num_child_types == 0
179 || (address == selement->address && type == selement->type)
180 || (is_array && address == selement->address && type == selement->parent_type)) {
181 return MAGIC_TYPE_WALK_STOP;
184 return MAGIC_TYPE_WALK_CONTINUE;
187 /*===========================================================================*
188 * magic_selement_print_value *
189 *===========================================================================*/
190 PUBLIC void magic_selement_print_value(const _magic_selement_t *selement)
192 int type_id = selement->type->type_id;
193 unsigned size = selement->type->size;
194 double dvalue;
195 void *pvalue;
196 unsigned long uvalue;
197 long ivalue;
198 char vvalue;
199 switch(type_id) {
200 case MAGIC_TYPE_FLOAT:
201 dvalue = magic_selement_to_float(selement);
202 _magic_printf("float(%d):%g", size, dvalue);
203 _magic_printf("/%d", (long) dvalue);
204 break;
206 case MAGIC_TYPE_POINTER:
207 pvalue = magic_selement_to_ptr(selement);
208 _magic_printf("ptr:%08x", pvalue);
209 break;
211 case MAGIC_TYPE_INTEGER:
212 case MAGIC_TYPE_ENUM:
213 if(MAGIC_TYPE_FLAG(selement->type, MAGIC_TYPE_UNSIGNED)) {
214 uvalue = magic_selement_to_unsigned(selement);
215 _magic_printf("unsigned %s(%d):%u", type_id == MAGIC_TYPE_INTEGER ? "int" : "enum", size, uvalue);
217 else {
218 ivalue = magic_selement_to_int(selement);
219 _magic_printf("%s(%d):%d", type_id == MAGIC_TYPE_INTEGER ? "int" : "enum", size, ivalue);
221 break;
223 case MAGIC_TYPE_VOID:
224 vvalue = *((char*) selement->address);
225 _magic_printf("void(%d):%d", size, vvalue);
226 break;
228 default:
229 _magic_printf("???");
230 break;
234 /*===========================================================================*
235 * magic_selement_to_unsigned *
236 *===========================================================================*/
237 PUBLIC unsigned long magic_selement_to_unsigned(const _magic_selement_t *selement)
239 void *address = selement->address;
240 const struct _magic_type* type = selement->type;
241 unsigned long value = 0;
242 unsigned size = type->size;
243 assert(size > 0);
244 assert(type->type_id == MAGIC_TYPE_INTEGER
245 || type->type_id == MAGIC_TYPE_ENUM);
247 if(address == NULL)
248 return 0;
250 if(size == sizeof(unsigned char)) {
251 value = (unsigned long) *((unsigned char*) address);
253 else if(size == sizeof(unsigned short)) {
254 value = (unsigned long) *((unsigned short*) address);
256 #ifdef MAGIC_LONG_LONG_SUPPORTED
257 else if(size == sizeof(unsigned long long)) {
258 value = (unsigned long) *((unsigned long long*) address);
260 #endif
261 else {
262 assert(size == sizeof(unsigned long));
263 value = *((unsigned long*) address);
266 return value;
269 /*===========================================================================*
270 * magic_selement_to_int *
271 *===========================================================================*/
272 PUBLIC long magic_selement_to_int(const _magic_selement_t *selement)
274 void *address = selement->address;
275 const struct _magic_type* type = selement->type;
276 long value = 0;
277 unsigned size = type->size;
278 assert(size > 0);
279 assert(type->type_id == MAGIC_TYPE_INTEGER
280 || type->type_id == MAGIC_TYPE_ENUM);
282 if(address == NULL)
283 return 0;
285 if(size == sizeof(char)) {
286 value = (long) *((char*) address);
288 else if(size == sizeof(short)) {
289 value = (long) *((short*) address);
291 #ifdef MAGIC_LONG_LONG_SUPPORTED
292 else if(size == sizeof(long long)) {
293 value = (long) *((long long*) address);
295 #endif
296 else {
297 assert(size == sizeof(long));
298 value = *((long*) address);
301 return value;
304 #ifdef MAGIC_LONG_LONG_SUPPORTED
305 /*===========================================================================*
306 * magic_selement_to_llu *
307 *===========================================================================*/
308 PUBLIC unsigned long long magic_selement_to_llu(const _magic_selement_t *selement)
310 void *address = selement->address;
311 const struct _magic_type* type = selement->type;
312 unsigned long long value;
313 unsigned size = type->size;
315 if(address == NULL)
316 return 0;
318 if (size == sizeof(unsigned long long))
319 value = *((unsigned long long*) address);
320 else
321 value = (unsigned long long) magic_selement_to_unsigned(selement);
322 return value;
325 /*===========================================================================*
326 * magic_selement_to_ll *
327 *===========================================================================*/
328 PUBLIC long long magic_selement_to_ll(const _magic_selement_t *selement)
330 void *address = selement->address;
331 const struct _magic_type* type = selement->type;
332 long long value;
333 unsigned size = type->size;
335 if(address == NULL)
336 return 0;
338 if (size == sizeof(long long))
339 value = *((long long*) address);
340 else
341 value = (long long) magic_selement_to_int(selement);
342 return value;
344 #endif
346 /*===========================================================================*
347 * magic_selement_to_float *
348 *===========================================================================*/
349 PUBLIC double magic_selement_to_float(const _magic_selement_t *selement)
351 void *address = selement->address;
352 const struct _magic_type* type = selement->type;
353 double value = 0.0;
354 unsigned size = type->size;
355 assert(size > 0);
356 assert(type->type_id == MAGIC_TYPE_FLOAT);
358 if(address == NULL)
359 return 0;
361 if(size == sizeof(float)) {
362 value = (double) *((float*) address);
364 #ifdef MAGIC_LONG_DOUBLE_SUPPORTED
365 else if(size == sizeof(long double)) {
366 value = (double) *((long double*) address);
368 #endif
369 else {
370 assert(size == sizeof(double));
371 value = *((double*) address);
374 return value;
377 /*===========================================================================*
378 * magic_selement_to_ptr *
379 *===========================================================================*/
380 PUBLIC void* magic_selement_to_ptr(const _magic_selement_t *selement)
382 void *address = selement->address;
383 const struct _magic_type* type = selement->type;
384 void* value = NULL;
385 assert(type->type_id == MAGIC_TYPE_POINTER);
387 if (!address)
388 return NULL;
389 value = *((void**) address);
390 return value;
393 /*===========================================================================*
394 * magic_selement_from_unsigned *
395 *===========================================================================*/
396 PUBLIC void magic_selement_from_unsigned(const _magic_selement_t *selement, unsigned long value)
398 void *address = selement->address;
399 const struct _magic_type* type = selement->type;
400 unsigned size = type->size;
401 assert(size > 0);
402 assert(type->type_id == MAGIC_TYPE_INTEGER
403 || type->type_id == MAGIC_TYPE_ENUM);
405 /* Prevent a store to NULL. */
406 if(address == NULL)
407 return;
409 if(size == sizeof(unsigned char)) {
410 *((unsigned char*) address) = (unsigned char) value;
412 else if(size == sizeof(unsigned short)) {
413 *((unsigned short*) address) = (unsigned short) value;
415 #ifdef MAGIC_LONG_LONG_SUPPORTED
416 else if(size == sizeof(unsigned long long)) {
417 *((unsigned long long*) address) = (unsigned long long) value;
419 #endif
420 else {
421 assert(size == sizeof(unsigned long));
422 *((unsigned long*) address) = (unsigned long) value;
426 /*===========================================================================*
427 * magic_selement_from_int *
428 *===========================================================================*/
429 PUBLIC void magic_selement_from_int(const _magic_selement_t *selement, long value)
431 void *address = selement->address;
432 const struct _magic_type* type = selement->type;
433 unsigned size = type->size;
434 assert(size > 0);
435 assert(type->type_id == MAGIC_TYPE_INTEGER
436 || type->type_id == MAGIC_TYPE_ENUM);
438 /* Prevent a store to NULL. */
439 if(address == NULL)
440 return;
442 if(size == sizeof(char)) {
443 *((char*) address) = (char) value;
445 else if(size == sizeof(short)) {
446 *((short*) address) = (short) value;
448 #ifdef MAGIC_LONG_LONG_SUPPORTED
449 else if(size == sizeof(long long)) {
450 *((long long*) address) = (long long) value;
452 #endif
453 else {
454 assert(size == sizeof(long));
455 *((long*) address) = (long) value;
459 /*===========================================================================*
460 * magic_selement_from_float *
461 *===========================================================================*/
462 PUBLIC void magic_selement_from_float(const _magic_selement_t *selement, double value)
464 void *address = selement->address;
465 const struct _magic_type* type = selement->type;
466 unsigned size = type->size;
467 assert(size > 0);
468 assert(type->type_id == MAGIC_TYPE_FLOAT);
470 /* Prevent a store to NULL. */
471 if(address == NULL)
472 return;
474 if(size == sizeof(float)) {
475 *((float*) address) = (float) value;
477 #ifdef MAGIC_LONG_DOUBLE_SUPPORTED
478 else if(size == sizeof(long double)) {
479 *((long double*) address) = (long double) value;
481 #endif
482 else {
483 assert(size == sizeof(double));
484 *((double*) address) = (double) value;
488 /*===========================================================================*
489 * magic_selement_ptr_value_cast *
490 *===========================================================================*/
491 PUBLIC int magic_selement_ptr_value_cast(const _magic_selement_t *src_selement, const _magic_selement_t *dst_selement, void* value_buffer)
493 int src_type_id = src_selement->type->type_id;
494 int dst_type_id = dst_selement->type->type_id;
495 unsigned src_size = src_selement->type->size;
496 unsigned dst_size = dst_selement->type->size;
497 void* src_value;
498 int r = 0;
499 assert(dst_size > 0);
501 if(dst_type_id != MAGIC_TYPE_POINTER) {
502 return EINVAL;
504 assert(dst_size == sizeof(void*));
505 if(src_size != sizeof(void*)) {
506 return EINVAL;
508 switch(src_type_id) {
509 case MAGIC_TYPE_POINTER:
510 return 0;
511 break;
513 case MAGIC_TYPE_INTEGER:
514 if(MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED)) {
515 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_unsigned(src_selement), unsigned long, src_value, void*, &r, 0);
516 assert(r == 0);
518 else {
519 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_int(src_selement), long, src_value, void*, &r, 0);
520 assert(r == 0);
522 break;
524 default:
525 return EINVAL;
526 break;
529 MAGIC_CHECKED_VALUE_DST_CAST(src_value, void*, value_buffer, void*, &r);
530 assert(r == 0);
532 return dst_size;
535 /*===========================================================================*
536 * magic_selement_unsigned_value_cast *
537 *===========================================================================*/
538 PUBLIC int magic_selement_unsigned_value_cast(const _magic_selement_t *src_selement, const _magic_selement_t *dst_selement, void* value_buffer)
540 int src_type_id = src_selement->type->type_id;
541 int dst_type_id = dst_selement->type->type_id;
542 int r = 0;
543 unsigned src_size = src_selement->type->size;
544 unsigned dst_size = dst_selement->type->size;
545 unsigned long src_value;
546 assert(dst_size > 0);
548 if(dst_type_id != MAGIC_TYPE_INTEGER && dst_type_id != MAGIC_TYPE_ENUM) {
549 return EINVAL;
551 switch(src_type_id) {
552 case MAGIC_TYPE_FLOAT:
553 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_float(src_selement), double, src_value, unsigned long, &r, 1);
554 break;
556 case MAGIC_TYPE_POINTER:
557 if(dst_size != sizeof(void*)) {
558 return EINVAL;
560 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_ptr(src_selement), void*, src_value, unsigned long, &r, 0);
561 assert(r == 0);
562 break;
564 case MAGIC_TYPE_INTEGER:
565 case MAGIC_TYPE_ENUM:
566 if(src_size == dst_size && MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED) == MAGIC_TYPE_FLAG(dst_selement->type, MAGIC_TYPE_UNSIGNED)) {
567 return 0;
569 if(MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED)) {
570 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_unsigned(src_selement), unsigned long, src_value, unsigned long, &r, 0);
571 assert(r == 0);
573 else {
574 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_int(src_selement), long, src_value, unsigned long, &r, 1);
576 break;
578 default:
579 return EINVAL;
580 break;
583 switch(dst_size) {
584 case sizeof(unsigned char):
585 MAGIC_CHECKED_VALUE_DST_CAST(src_value, unsigned long, value_buffer, unsigned char, &r);
586 break;
588 case sizeof(unsigned short):
589 MAGIC_CHECKED_VALUE_DST_CAST(src_value, unsigned long, value_buffer, unsigned short, &r);
590 break;
592 case sizeof(unsigned int):
593 MAGIC_CHECKED_VALUE_DST_CAST(src_value, unsigned long, value_buffer, unsigned int, &r);
594 break;
596 #ifdef MAGIC_LONG_LONG_SUPPORTED
597 case sizeof(unsigned long long):
598 MAGIC_CHECKED_VALUE_DST_CAST(src_value, unsigned long, value_buffer, unsigned long long, &r);
599 break;
600 #endif
602 default:
603 return EINVAL;
604 break;
607 if(r == 0) {
608 r = dst_size;
611 return r;
614 /*===========================================================================*
615 * magic_selement_int_value_cast *
616 *===========================================================================*/
617 PUBLIC int magic_selement_int_value_cast(const _magic_selement_t *src_selement, const _magic_selement_t *dst_selement, void* value_buffer)
619 int src_type_id = src_selement->type->type_id;
620 int dst_type_id = dst_selement->type->type_id;
621 int r = 0;
622 unsigned src_size = src_selement->type->size;
623 unsigned dst_size = dst_selement->type->size;
624 long src_value;
625 assert(dst_size > 0);
627 if(dst_type_id != MAGIC_TYPE_INTEGER && dst_type_id != MAGIC_TYPE_ENUM) {
628 return EINVAL;
631 switch(src_type_id) {
632 case MAGIC_TYPE_FLOAT:
633 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_float(src_selement), double, src_value, long, &r, 1);
634 break;
636 case MAGIC_TYPE_POINTER:
637 if(dst_size != sizeof(void*)) {
638 return EINVAL;
640 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_ptr(src_selement), void*, src_value, long, &r, 0);
641 assert(r == 0);
642 break;
644 case MAGIC_TYPE_INTEGER:
645 case MAGIC_TYPE_ENUM:
646 if(src_size == dst_size && MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED) == MAGIC_TYPE_FLAG(dst_selement->type, MAGIC_TYPE_UNSIGNED)) {
647 return 0;
649 if(MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED)) {
650 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_unsigned(src_selement), unsigned long, src_value, long, &r, 1);
652 else {
653 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_int(src_selement), long, src_value, long, &r, 0);
654 assert(r == 0);
656 break;
658 default:
659 return EINVAL;
660 break;
663 switch(dst_size) {
664 case sizeof(char):
665 MAGIC_CHECKED_VALUE_DST_CAST(src_value, long, value_buffer, char, &r);
666 break;
668 case sizeof(short):
669 MAGIC_CHECKED_VALUE_DST_CAST(src_value, long, value_buffer, short, &r);
670 break;
672 case sizeof(int):
673 MAGIC_CHECKED_VALUE_DST_CAST(src_value, long, value_buffer, int, &r);
674 break;
676 #ifdef MAGIC_LONG_LONG_SUPPORTED
677 case sizeof(long long):
678 MAGIC_CHECKED_VALUE_DST_CAST(src_value, long, value_buffer, long long, &r);
679 break;
680 #endif
682 default:
683 return EINVAL;
684 break;
687 if(r == 0) {
688 r = dst_size;
691 return r;
694 /*===========================================================================*
695 * magic_selement_float_value_cast *
696 *===========================================================================*/
697 PUBLIC int magic_selement_float_value_cast(const _magic_selement_t *src_selement, const _magic_selement_t *dst_selement, void* value_buffer)
699 int src_type_id = src_selement->type->type_id;
700 int dst_type_id = dst_selement->type->type_id;
701 int r = 0;
702 unsigned src_size = src_selement->type->size;
703 unsigned dst_size = dst_selement->type->size;
704 double src_value;
705 assert(dst_size > 0);
707 if(dst_type_id != MAGIC_TYPE_FLOAT) {
708 return EINVAL;
710 switch(src_type_id) {
711 case MAGIC_TYPE_FLOAT:
712 if(src_size == dst_size) {
713 return 0;
715 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_float(src_selement), double, src_value, double, &r, 0);
716 assert(r == 0);
717 break;
719 case MAGIC_TYPE_INTEGER:
720 case MAGIC_TYPE_ENUM:
721 if(MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED)) {
722 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_unsigned(src_selement), unsigned long, src_value, double, &r, 1);
724 else {
725 MAGIC_CHECKED_VALUE_SRC_CAST(magic_selement_to_int(src_selement), long, src_value, double, &r, 1);
727 break;
729 default:
730 return EINVAL;
731 break;
735 switch(dst_size) {
736 case sizeof(float):
737 MAGIC_CHECKED_VALUE_DST_CAST(src_value, double, value_buffer, float, &r);
738 break;
740 case sizeof(double):
741 MAGIC_CHECKED_VALUE_DST_CAST(src_value, double, value_buffer, double, &r);
742 break;
744 #ifdef MAGIC_LONG_DOUBLE_SUPPORTED
745 case sizeof(long double):
746 MAGIC_CHECKED_VALUE_DST_CAST(src_value, double, value_buffer, long double, &r);
747 break;
748 #endif
750 default:
751 return EINVAL;
752 break;
755 if(r == 0) {
756 r = dst_size;
759 return r;
762 /*===========================================================================*
763 * magic_selement_value_cast *
764 *===========================================================================*/
765 PUBLIC int magic_selement_value_cast(const _magic_selement_t *src_selement, const _magic_selement_t *dst_selement, void* value_buffer)
767 int r, src_type_id, dst_type_id;
768 size_t src_size, dst_size;
769 src_type_id = src_selement->type->type_id;
770 dst_type_id = dst_selement->type->type_id;
771 src_size = src_selement->type->size;
772 dst_size = dst_selement->type->size;
773 if(src_type_id == dst_type_id && src_size == dst_size && MAGIC_TYPE_FLAG(src_selement->type, MAGIC_TYPE_UNSIGNED) == MAGIC_TYPE_FLAG(dst_selement->type, MAGIC_TYPE_UNSIGNED)) {
774 return 0;
777 /* No size change allowed in opaque value casts. */
778 if(src_type_id == MAGIC_TYPE_OPAQUE || dst_type_id == MAGIC_TYPE_OPAQUE) {
779 return src_size == dst_size ? 0 : EINVAL;
782 /* No size change allowed in void value casts. */
783 if(src_type_id == MAGIC_TYPE_VOID || dst_type_id == MAGIC_TYPE_VOID) {
784 return src_size == dst_size ? 0 : EINVAL;
787 switch(dst_type_id) {
788 case MAGIC_TYPE_POINTER:
789 /* Cast to pointer values. */
790 r = magic_selement_ptr_value_cast(src_selement, dst_selement, value_buffer);
791 break;
793 case MAGIC_TYPE_FLOAT:
794 /* Cast to float values. */
795 r = magic_selement_float_value_cast(src_selement, dst_selement, value_buffer);
796 break;
798 case MAGIC_TYPE_INTEGER:
799 case MAGIC_TYPE_ENUM:
800 if(MAGIC_TYPE_FLAG(dst_selement->type, MAGIC_TYPE_UNSIGNED)) {
801 /* Cast to unsigned values. */
802 r = magic_selement_unsigned_value_cast(src_selement, dst_selement, value_buffer);
804 else {
805 /* Cast to integer values. */
806 r = magic_selement_int_value_cast(src_selement, dst_selement, value_buffer);
808 break;
810 default:
811 r = EINVAL;
812 break;
814 return r;
817 /*===========================================================================*
818 * magic_selement_get_parent *
819 *===========================================================================*/
820 PUBLIC _magic_selement_t* magic_selement_get_parent(
821 const _magic_selement_t *selement, _magic_selement_t *parent_selement)
823 if(!selement->parent_type) {
824 return NULL;
827 parent_selement->sentry = selement->sentry;
828 parent_selement->parent_type = NULL;
829 parent_selement->child_num = 0;
830 parent_selement->type = selement->parent_type;
831 parent_selement->address = selement->parent_address;
832 parent_selement->num = 0;
833 assert(parent_selement->address >= parent_selement->sentry->address);
835 return parent_selement;
838 /*===========================================================================*
839 * magic_selement_fill_from_parent_info *
840 *===========================================================================*/
841 PUBLIC void magic_selement_fill_from_parent_info(_magic_selement_t *selement,
842 int walk_flags)
844 unsigned offset;
845 magic_type_walk_step(selement->parent_type,
846 selement->child_num, &selement->type, &offset, walk_flags);
847 selement->address = (char*) selement->parent_address + offset;
850 /*===========================================================================*
851 * magic_selement_from_sentry *
852 *===========================================================================*/
853 PUBLIC _magic_selement_t* magic_selement_from_sentry(struct _magic_sentry *sentry,
854 _magic_selement_t *selement)
856 selement->sentry = sentry;
857 selement->parent_type = NULL;
858 selement->child_num = 0;
859 selement->type = sentry->type;
860 selement->address = sentry->address;
861 selement->num = 1;
863 return selement;
866 /*===========================================================================*
867 * magic_selement_from_relative_name *
868 *===========================================================================*/
869 PUBLIC _magic_selement_t* magic_selement_from_relative_name(
870 _magic_selement_t *parent_selement, _magic_selement_t *selement, char* name)
872 _magic_selement_t new_parent_selement;
873 const struct _magic_type* parent_type = parent_selement->type;
874 int parent_type_id = parent_type->type_id;
875 int walk_flags = 0;
876 int i, child_num = -1;
877 char *end;
879 if(!name || *name == '\0') {
880 return NULL;
883 if(parent_type_id == MAGIC_TYPE_UNION && (*name >= '0' && *name <= '9')) {
884 parent_type_id = MAGIC_TYPE_ARRAY;
885 walk_flags = MAGIC_TYPE_WALK_UNIONS_AS_VOID;
888 switch(parent_type_id) {
889 case MAGIC_TYPE_ARRAY:
890 case MAGIC_TYPE_VECTOR:
891 child_num = (int) strtol(name, &end, 10);
892 if(end == name || *end != '\0' || errno == ERANGE) {
893 return NULL;
895 break;
897 case MAGIC_TYPE_STRUCT:
898 case MAGIC_TYPE_UNION:
899 for(i=0; (unsigned int)i<parent_type->num_child_types;i++) {
900 if(!strcmp(parent_type->member_names[i], name)) {
901 child_num = i;
902 break;
905 if((unsigned int)i == parent_type->num_child_types) {
906 return NULL;
908 break;
910 case MAGIC_TYPE_POINTER:
911 i = magic_selement_recurse_ptr(parent_selement, selement, MAGIC_SELEMENT_MAX_PTR_RECURSIONS);
912 if(i <= 0 || i >= MAGIC_SELEMENT_MAX_PTR_RECURSIONS) {
913 return NULL;
915 new_parent_selement = *selement;
916 return magic_selement_from_relative_name(&new_parent_selement, selement, name);
917 break;
919 default:
920 return NULL;
921 break;
924 if(child_num != -1) {
925 selement->sentry = parent_selement->sentry;
926 selement->parent_type = parent_type;
927 selement->parent_address = parent_selement->address;
928 selement->child_num = child_num;
929 selement->num = parent_selement->num+1;
930 magic_selement_fill_from_parent_info(selement, walk_flags);
933 return selement;