Annotation of embedaddon/libpdel/structs/structs.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * Copyright (c) 2001-2002 Packet Design, LLC.
! 4: * All rights reserved.
! 5: *
! 6: * Subject to the following obligations and disclaimer of warranty,
! 7: * use and redistribution of this software, in source or object code
! 8: * forms, with or without modifications are expressly permitted by
! 9: * Packet Design; provided, however, that:
! 10: *
! 11: * (i) Any and all reproductions of the source or object code
! 12: * must include the copyright notice above and the following
! 13: * disclaimer of warranties; and
! 14: * (ii) No rights are granted, in any manner or form, to use
! 15: * Packet Design trademarks, including the mark "PACKET DESIGN"
! 16: * on advertising, endorsements, or otherwise except as such
! 17: * appears in the above copyright notice or in the software.
! 18: *
! 19: * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
! 20: * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
! 21: * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
! 22: * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
! 23: * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
! 24: * OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
! 25: * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
! 26: * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
! 27: * RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
! 28: * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
! 29: * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
! 30: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
! 31: * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
! 32: * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
! 33: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 34: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
! 35: * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
! 36: * THE POSSIBILITY OF SUCH DAMAGE.
! 37: *
! 38: * Author: Archie Cobbs <archie@freebsd.org>
! 39: */
! 40:
! 41: #include <sys/types.h>
! 42:
! 43: #include <stdlib.h>
! 44: #include <stdio.h>
! 45: #include <stdarg.h>
! 46: #include <assert.h>
! 47: #include <string.h>
! 48: #include <ctype.h>
! 49: #include <errno.h>
! 50:
! 51: #include "structs/structs.h"
! 52: #include "structs/type/int.h"
! 53: #include "structs/type/array.h"
! 54: #include "structs/type/string.h"
! 55: #include "structs/type/struct.h"
! 56: #include "structs/type/union.h"
! 57: #include "util/typed_mem.h"
! 58:
! 59: /* Special handling for array length as a read-only field */
! 60: static const struct structs_type structs_type_array_length = {
! 61: sizeof(u_int),
! 62: "uint",
! 63: STRUCTS_TYPE_PRIMITIVE,
! 64: structs_region_init,
! 65: structs_region_copy,
! 66: structs_region_equal,
! 67: structs_int_ascify,
! 68: structs_notsupp_binify,
! 69: structs_region_encode_netorder,
! 70: structs_notsupp_decode,
! 71: structs_nothing_free,
! 72: { { (void *)2 }, { (void *)0 } } /* args for structs_int_ascify */
! 73: };
! 74:
! 75: /* Special handling for union field name as a read-only field */
! 76: static const struct structs_type structs_type_union_field_name = {
! 77: sizeof(char *),
! 78: "string",
! 79: STRUCTS_TYPE_PRIMITIVE,
! 80: structs_notsupp_init,
! 81: structs_notsupp_copy,
! 82: structs_string_equal,
! 83: structs_string_ascify,
! 84: structs_notsupp_binify,
! 85: structs_notsupp_encode,
! 86: structs_notsupp_decode,
! 87: structs_nothing_free,
! 88: { { (void *)"union field_name" }, /* args for structs_type_string */
! 89: { (void *)0 } }
! 90: };
! 91:
! 92: /*
! 93: * Initialize an item.
! 94: */
! 95: int
! 96: structs_init(const struct structs_type *type, const char *name, void *data)
! 97: {
! 98: /* Find item */
! 99: if ((type = structs_find(type, name, &data, 0)) == NULL)
! 100: return (-1);
! 101:
! 102: /* Initialize it */
! 103: return ((*type->init)(type, data));
! 104: }
! 105:
! 106: /*
! 107: * Reset an item.
! 108: */
! 109: int
! 110: structs_reset(const struct structs_type *type, const char *name, void *data)
! 111: {
! 112: void *temp;
! 113:
! 114: /* Find item */
! 115: if ((type = structs_find(type, name, &data, 0)) == NULL)
! 116: return (-1);
! 117:
! 118: /* Make a temporary new copy */
! 119: if ((temp = MALLOC(TYPED_MEM_TEMP, type->size)) == NULL)
! 120: return (-1);
! 121: memset(temp, 0, type->size);
! 122: if ((*type->init)(type, temp) == -1) {
! 123: FREE(TYPED_MEM_TEMP, temp);
! 124: return (-1);
! 125: }
! 126:
! 127: /* Replace existing item, freeing it first */
! 128: (*type->uninit)(type, data);
! 129: memcpy(data, temp, type->size);
! 130: FREE(TYPED_MEM_TEMP, temp);
! 131: return (0);
! 132: }
! 133:
! 134: /*
! 135: * Free an item, returning it to its initialized state.
! 136: *
! 137: * If "name" is NULL or empty string, the entire structure is free'd.
! 138: */
! 139: int
! 140: structs_free(const struct structs_type *type, const char *name, void *data)
! 141: {
! 142: const int errno_save = errno;
! 143:
! 144: /* Find item */
! 145: if ((type = structs_find(type, name, &data, 0)) == NULL)
! 146: return (-1);
! 147:
! 148: /* Free it */
! 149: (*type->uninit)(type, data);
! 150: errno = errno_save;
! 151: return (0);
! 152: }
! 153:
! 154: /*
! 155: * Get a copy of an item.
! 156: *
! 157: * If "name" is NULL or empty string, the entire structure is copied.
! 158: *
! 159: * It is assumed that "to" points to a region big enough to hold
! 160: * the copy of the item. "to" will not be free'd first, so it should
! 161: * not already be initialized.
! 162: *
! 163: * Note: "name" is only applied to "from". The structs types of
! 164: * "from.<name>" and "to" must be the same.
! 165: */
! 166: int
! 167: structs_get(const struct structs_type *type,
! 168: const char *name, const void *from, void *to)
! 169: {
! 170: /* Find item */
! 171: if ((type = structs_find(type, name, (void **)&from, 0)) == NULL)
! 172: return (-1);
! 173:
! 174: /* Copy item */
! 175: return ((*type->copy)(type, from, to));
! 176: }
! 177:
! 178: /*
! 179: * Set an item in a structure.
! 180: *
! 181: * If "name" is NULL or empty string, the entire structure is copied.
! 182: *
! 183: * It is assumed that "to" is already initialized.
! 184: *
! 185: * Note: "name" is only applied to "to". The structs types of
! 186: * "from" and "to.<name>" must be the same.
! 187: */
! 188: int
! 189: structs_set(const struct structs_type *type,
! 190: const void *from, const char *name, void *to)
! 191: {
! 192: void *copy;
! 193:
! 194: /* Find item */
! 195: if ((type = structs_find(type, name, &to, 0)) == NULL)
! 196: return (-1);
! 197:
! 198: /* Make a new copy of 'from' */
! 199: if ((copy = MALLOC(TYPED_MEM_TEMP, type->size)) == NULL)
! 200: return (-1);
! 201: if ((*type->copy)(type, from, copy) == -1) {
! 202: FREE(TYPED_MEM_TEMP, copy);
! 203: return (-1);
! 204: }
! 205:
! 206: /* Free overwritten item in 'to' */
! 207: (*type->uninit)(type, to);
! 208:
! 209: /* Move new item in its place */
! 210: memcpy(to, copy, type->size);
! 211:
! 212: /* Done */
! 213: FREE(TYPED_MEM_TEMP, copy);
! 214: return (0);
! 215: }
! 216:
! 217: /*
! 218: * Get the ASCII form of an item.
! 219: */
! 220: char *
! 221: structs_get_string(const struct structs_type *type,
! 222: const char *name, const void *data, const char *mtype)
! 223: {
! 224: /* Find item */
! 225: if ((type = structs_find(type, name, (void **)&data, 0)) == NULL)
! 226: return (NULL);
! 227:
! 228: /* Ascify it */
! 229: return ((*type->ascify)(type, mtype, data));
! 230: }
! 231:
! 232: /*
! 233: * Set an item's value from a string.
! 234: *
! 235: * The referred to item must be of a type that supports ASCII encoding,
! 236: * and is assumed to be already initialized.
! 237: */
! 238: int
! 239: structs_set_string(const struct structs_type *type, const char *name,
! 240: const char *ascii, void *data, char *ebuf, size_t emax)
! 241: {
! 242: void *temp;
! 243: char dummy[1];
! 244:
! 245: /* Sanity check */
! 246: if (ascii == NULL)
! 247: ascii = "";
! 248: if (ebuf == NULL) {
! 249: ebuf = dummy;
! 250: emax = sizeof(dummy);
! 251: }
! 252:
! 253: /* Initialize error buffer */
! 254: if (emax > 0)
! 255: *ebuf = '\0';
! 256:
! 257: /* Find item */
! 258: if ((type = structs_find(type, name, &data, 1)) == NULL) {
! 259: strlcpy(ebuf, strerror(errno), emax);
! 260: return (-1);
! 261: }
! 262:
! 263: /* Binify item into temporary storage */
! 264: if ((temp = MALLOC(TYPED_MEM_TEMP, type->size)) == NULL)
! 265: return (-1);
! 266: memset(temp, 0, type->size);
! 267: if ((*type->binify)(type, ascii, temp, ebuf, emax) == -1) {
! 268: FREE(TYPED_MEM_TEMP, temp);
! 269: if (emax > 0 && *ebuf == '\0')
! 270: strlcpy(ebuf, strerror(errno), emax);
! 271: return (-1);
! 272: }
! 273:
! 274: /* Replace existing item, freeing it first */
! 275: (*type->uninit)(type, data);
! 276: memcpy(data, temp, type->size);
! 277: FREE(TYPED_MEM_TEMP, temp);
! 278: return (0);
! 279: }
! 280:
! 281: /*
! 282: * Get the binary encoded form of an item, allocated with type 'mtype'.
! 283: */
! 284: int
! 285: structs_get_binary(const struct structs_type *type, const char *name,
! 286: const void *data, const char *mtype, struct structs_data *code)
! 287: {
! 288: /* Find item */
! 289: if ((type = structs_find(type, name, (void **)&data, 0)) == NULL) {
! 290: memset(code, 0, sizeof(*code));
! 291: return (-1);
! 292: }
! 293:
! 294: /* Encode it */
! 295: if ((*type->encode)(type, mtype, code, data) == -1) {
! 296: memset(code, 0, sizeof(*code));
! 297: return (-1);
! 298: }
! 299:
! 300: /* Done */
! 301: return (0);
! 302: }
! 303:
! 304: /*
! 305: * Set an item's value from its binary encoded value.
! 306: */
! 307: int
! 308: structs_set_binary(const struct structs_type *type, const char *name,
! 309: const struct structs_data *code, void *data, char *ebuf, size_t emax)
! 310: {
! 311: void *temp;
! 312: int clen;
! 313:
! 314: /* Initialize error buffer */
! 315: if (emax > 0)
! 316: *ebuf = '\0';
! 317:
! 318: /* Find item */
! 319: if ((type = structs_find(type, name, (void **)&data, 0)) == NULL) {
! 320: strlcpy(ebuf, strerror(errno), emax);
! 321: return (-1);
! 322: }
! 323:
! 324: /* Decode item into temporary storage */
! 325: if ((temp = MALLOC(TYPED_MEM_TEMP, type->size)) == NULL)
! 326: return (-1);
! 327: memset(temp, 0, type->size);
! 328: if ((clen = (*type->decode)(type, code->data,
! 329: code->length, temp, ebuf, emax)) == -1) {
! 330: FREE(TYPED_MEM_TEMP, temp);
! 331: if (emax > 0 && *ebuf == '\0')
! 332: strlcpy(ebuf, strerror(errno), emax);
! 333: return (-1);
! 334: }
! 335: assert(clen <= code->length);
! 336:
! 337: /* Replace existing item, freeing it first */
! 338: (*type->uninit)(type, data);
! 339: memcpy(data, temp, type->size);
! 340: FREE(TYPED_MEM_TEMP, temp);
! 341:
! 342: /* Done */
! 343: return (clen);
! 344: }
! 345:
! 346: /*
! 347: * Test for equality.
! 348: */
! 349: int
! 350: structs_equal(const struct structs_type *type,
! 351: const char *name, const void *data1, const void *data2)
! 352: {
! 353: /* Find items */
! 354: if (structs_find(type, name, (void **)&data1, 0) == NULL)
! 355: return (-1);
! 356: if ((type = structs_find(type, name, (void **)&data2, 0)) == NULL)
! 357: return (-1);
! 358:
! 359: /* Compare them */
! 360: return ((*type->equal)(type, data1, data2));
! 361: }
! 362:
! 363: /*
! 364: * Find an item in a structure.
! 365: */
! 366: const struct structs_type *
! 367: structs_find(const struct structs_type *type, const char *name,
! 368: void **datap, int set_union)
! 369: {
! 370: void *data = *datap;
! 371: const char *next;
! 372:
! 373: /* Empty string means stop recursing */
! 374: if (name == NULL || *name == '\0')
! 375: return (type);
! 376:
! 377: /* Primitive types don't have sub-elements */
! 378: if (type->tclass == STRUCTS_TYPE_PRIMITIVE) {
! 379: errno = ENOENT;
! 380: return (NULL);
! 381: }
! 382:
! 383: /* Dereference through pointer(s) */
! 384: while (type->tclass == STRUCTS_TYPE_POINTER) {
! 385: type = type->args[0].v;
! 386: data = *((void **)data);
! 387: }
! 388:
! 389: /* Get next name component */
! 390: if ((next = strchr(name, STRUCTS_SEPARATOR)) != NULL)
! 391: next++;
! 392:
! 393: /* Find element of aggregate structure update type and data */
! 394: switch (type->tclass) {
! 395: case STRUCTS_TYPE_ARRAY:
! 396: {
! 397: const struct structs_type *const etype = type->args[0].v;
! 398: const struct structs_array *const ary = data;
! 399: u_long index;
! 400: char *eptr;
! 401:
! 402: /* Special handling for "length" */
! 403: if (strcmp(name, "length") == 0) {
! 404: type = &structs_type_array_length;
! 405: data = (void *)&ary->length;
! 406: break;
! 407: }
! 408:
! 409: /* Decode an index */
! 410: index = strtoul(name, &eptr, 10);
! 411: if (!isdigit(*name)
! 412: || eptr == name
! 413: || (*eptr != '\0' && *eptr != STRUCTS_SEPARATOR)) {
! 414: errno = ENOENT;
! 415: return (NULL);
! 416: }
! 417: if (index >= ary->length) {
! 418: errno = EDOM;
! 419: return (NULL);
! 420: }
! 421: type = etype;
! 422: data = (char *)ary->elems + (index * etype->size);
! 423: break;
! 424: }
! 425: case STRUCTS_TYPE_FIXEDARRAY:
! 426: {
! 427: const struct structs_type *const etype = type->args[0].v;
! 428: const u_int length = type->args[2].i;
! 429: u_long index;
! 430: char *eptr;
! 431:
! 432: /* Special handling for "length" */
! 433: if (strcmp(name, "length") == 0) {
! 434: type = &structs_type_array_length;
! 435: data = (void *)&type->args[2].i;
! 436: break;
! 437: }
! 438:
! 439: /* Decode an index */
! 440: index = strtoul(name, &eptr, 10);
! 441: if (!isdigit(*name)
! 442: || eptr == name
! 443: || (*eptr != '\0' && *eptr != STRUCTS_SEPARATOR)) {
! 444: errno = ENOENT;
! 445: return (NULL);
! 446: }
! 447: if (index >= length) {
! 448: errno = EDOM;
! 449: return (NULL);
! 450: }
! 451: type = etype;
! 452: data = (char *)data + (index * etype->size);
! 453: break;
! 454: }
! 455: case STRUCTS_TYPE_STRUCTURE:
! 456: {
! 457: const struct structs_field *field;
! 458:
! 459: /* Find the field */
! 460: for (field = type->args[0].v; field->name != NULL; field++) {
! 461: const size_t fnlen = strlen(field->name);
! 462:
! 463: /* Handle field names with separator in them */
! 464: if (strncmp(name, field->name, fnlen) == 0
! 465: && (name[fnlen] == '\0'
! 466: || name[fnlen] == STRUCTS_SEPARATOR)) {
! 467: next = (name[fnlen] != '\0') ?
! 468: name + fnlen + 1 : NULL;
! 469: break;
! 470: }
! 471: }
! 472: if (field->name == NULL) {
! 473: errno = ENOENT;
! 474: return (NULL);
! 475: }
! 476: type = field->type;
! 477: data = (char *)data + field->offset;
! 478: break;
! 479: }
! 480: case STRUCTS_TYPE_UNION:
! 481: {
! 482: const struct structs_ufield *const fields = type->args[0].v;
! 483: const char *const mtype = type->args[1].s;
! 484: struct structs_union *const un = data;
! 485: const size_t oflen = strlen(un->field_name);
! 486: const struct structs_ufield *ofield;
! 487: const struct structs_ufield *field;
! 488: void *new_un;
! 489: void *data2;
! 490:
! 491: /* Special handling for "field_name" */
! 492: if (strcmp(name, "field_name") == 0) {
! 493: type = &structs_type_union_field_name;
! 494: data = (void *)&un->field_name;
! 495: break;
! 496: }
! 497:
! 498: /* Find the old field */
! 499: for (ofield = fields; ofield->name != NULL; ofield++) {
! 500: if (strcmp(ofield->name, un->field_name) == 0)
! 501: break;
! 502: }
! 503: if (ofield->name == NULL) {
! 504: assert(0);
! 505: errno = EINVAL;
! 506: return (NULL);
! 507: }
! 508:
! 509: /*
! 510: * Check if the union is already set to the desired field,
! 511: * handling field names with the separator char in them.
! 512: */
! 513: if (strncmp(name, un->field_name, oflen) == 0
! 514: && (name[oflen] == '\0'
! 515: || name[oflen] == STRUCTS_SEPARATOR)) {
! 516: next = (name[oflen] != '\0') ? name + oflen + 1 : NULL;
! 517: field = ofield;
! 518: goto union_done;
! 519: }
! 520:
! 521: /* Is modifying the union to get the right name acceptable? */
! 522: if (!set_union) {
! 523: errno = ENOENT;
! 524: return (NULL);
! 525: }
! 526:
! 527: /* Find the new field */
! 528: for (field = fields; field->name != NULL; field++) {
! 529: const size_t fnlen = strlen(field->name);
! 530:
! 531: /* Handle field names with separator in them */
! 532: if (strncmp(name, field->name, fnlen) == 0
! 533: && (name[fnlen] == '\0'
! 534: || name[fnlen] == STRUCTS_SEPARATOR)) {
! 535: next = (name[fnlen] != '\0') ?
! 536: name + fnlen + 1 : NULL;
! 537: break;
! 538: }
! 539: }
! 540: if (field->name == NULL) {
! 541: errno = ENOENT;
! 542: return (NULL);
! 543: }
! 544:
! 545: /* Create a new union with the new field type */
! 546: if ((new_un = MALLOC(mtype, field->type->size)) == NULL)
! 547: return (NULL);
! 548: if ((*field->type->init)(field->type, new_un) == -1) {
! 549: FREE(mtype, new_un);
! 550: return (NULL);
! 551: }
! 552:
! 553: /* See if name would be found with new union instead of old */
! 554: data2 = new_un;
! 555: if (next != NULL
! 556: && structs_find(field->type, next, &data2, 1) == NULL) {
! 557: (*field->type->uninit)(field->type, new_un);
! 558: FREE(mtype, new_un);
! 559: return (NULL);
! 560: }
! 561:
! 562: /* Replace existing union with new one having desired type */
! 563: (*ofield->type->uninit)(ofield->type, un->un);
! 564: FREE(mtype, un->un);
! 565: un->un = new_un;
! 566: *((const char **)&un->field_name) = field->name;
! 567:
! 568: union_done:
! 569: /* Continue recursing */
! 570: type = field->type;
! 571: data = un->un;
! 572: break;
! 573: }
! 574: default:
! 575: assert(0);
! 576: return (NULL);
! 577: }
! 578:
! 579: /* Recurse on sub-element */
! 580: if ((type = structs_find(type, next, &data, set_union)) == NULL)
! 581: return (NULL);
! 582:
! 583: /* Done */
! 584: *datap = data;
! 585: return (type);
! 586: }
! 587:
! 588: /*
! 589: * Traverse a structure.
! 590: */
! 591:
! 592: struct structs_trav {
! 593: char **list;
! 594: u_int len;
! 595: u_int alloc;
! 596: const char *mtype;
! 597: };
! 598:
! 599: static int structs_trav(struct structs_trav *t, const char *name,
! 600: const struct structs_type *type, const void *data);
! 601:
! 602: int
! 603: structs_traverse(const struct structs_type *type,
! 604: const void *data, char ***listp, const char *mtype)
! 605: {
! 606: struct structs_trav t;
! 607:
! 608: /* Initialize traversal structure */
! 609: memset(&t, 0, sizeof(t));
! 610: t.mtype = mtype;
! 611:
! 612: /* Recurse */
! 613: if (structs_trav(&t, "", type, data) == -1) {
! 614: while (t.len > 0)
! 615: FREE(t.mtype, t.list[--t.len]);
! 616: FREE(t.mtype, t.list);
! 617: return (-1);
! 618: }
! 619:
! 620: /* Return the result */
! 621: *listp = t.list;
! 622: return (t.len);
! 623: }
! 624:
! 625: static int
! 626: structs_trav(struct structs_trav *t, const char *name,
! 627: const struct structs_type *type, const void *data)
! 628: {
! 629: const char *const dot = (*name == '\0' ? "" : ".");
! 630: char *ename;
! 631: int i;
! 632:
! 633: /* Dereference through pointer(s) */
! 634: while (type->tclass == STRUCTS_TYPE_POINTER) {
! 635: type = type->args[0].v;
! 636: data = *((void **)data);
! 637: }
! 638:
! 639: switch (type->tclass) {
! 640: case STRUCTS_TYPE_PRIMITIVE:
! 641: {
! 642: /* Grow list as necessary */
! 643: if (t->len == t->alloc) {
! 644: u_int new_alloc;
! 645: char **new_list;
! 646:
! 647: new_alloc = (t->alloc + 32) * 2;
! 648: if ((new_list = REALLOC(t->mtype,
! 649: t->list, new_alloc * sizeof(*t->list))) == NULL)
! 650: return (-1);
! 651: t->list = new_list;
! 652: t->alloc = new_alloc;
! 653: }
! 654:
! 655: /* Add new name to list */
! 656: if ((t->list[t->len] = STRDUP(t->mtype, name)) == NULL)
! 657: return (-1);
! 658: t->len++;
! 659:
! 660: /* Done */
! 661: return (0);
! 662: }
! 663:
! 664: case STRUCTS_TYPE_ARRAY:
! 665: {
! 666: const struct structs_type *const etype = type->args[0].v;
! 667: const struct structs_array *const ary = data;
! 668:
! 669: /* Iterate over array elements */
! 670: for (i = 0; i < ary->length; i++) {
! 671: const void *const edata
! 672: = (char *)ary->elems + (i * etype->size);
! 673:
! 674: if (ASPRINTF(t->mtype,
! 675: &ename, "%s%s%d", name, dot, i) == -1)
! 676: return (-1);
! 677: if (structs_trav(t, ename, etype, edata) == -1) {
! 678: FREE(t->mtype, ename);
! 679: return (-1);
! 680: }
! 681: FREE(t->mtype, ename);
! 682: }
! 683:
! 684: /* Done */
! 685: return (0);
! 686: }
! 687:
! 688: case STRUCTS_TYPE_FIXEDARRAY:
! 689: {
! 690: const struct structs_type *const etype = type->args[0].v;
! 691: const u_int length = type->args[2].i;
! 692:
! 693: /* Iterate over array elements */
! 694: for (i = 0; i < length; i++) {
! 695: const void *const edata
! 696: = (char *)data + (i * etype->size);
! 697:
! 698: if (ASPRINTF(t->mtype,
! 699: &ename, "%s%s%d", name, dot, i) == -1)
! 700: return (-1);
! 701: if (structs_trav(t, ename, etype, edata) == -1) {
! 702: FREE(t->mtype, ename);
! 703: return (-1);
! 704: }
! 705: FREE(t->mtype, ename);
! 706: }
! 707:
! 708: /* Done */
! 709: return (0);
! 710: }
! 711:
! 712: case STRUCTS_TYPE_STRUCTURE:
! 713: {
! 714: const struct structs_field *field;
! 715:
! 716: /* Iterate over structure fields */
! 717: for (field = type->args[0].v; field->name != NULL; field++) {
! 718: const void *const edata
! 719: = (char *)data + field->offset;
! 720:
! 721: if (ASPRINTF(t->mtype,
! 722: &ename, "%s%s%s", name, dot, field->name) == -1)
! 723: return (-1);
! 724: if (structs_trav(t, ename, field->type, edata) == -1) {
! 725: FREE(t->mtype, ename);
! 726: return (-1);
! 727: }
! 728: FREE(t->mtype, ename);
! 729: }
! 730:
! 731: /* Done */
! 732: return (0);
! 733: }
! 734:
! 735: case STRUCTS_TYPE_UNION:
! 736: {
! 737: const struct structs_ufield *const fields = type->args[0].v;
! 738: const struct structs_union *const un = data;
! 739: const struct structs_ufield *field;
! 740:
! 741: /* Find field */
! 742: for (field = fields; field->name != NULL
! 743: && strcmp(un->field_name, field->name) != 0; field++);
! 744: if (field->name == NULL) {
! 745: assert(0);
! 746: errno = EINVAL;
! 747: return (-1);
! 748: }
! 749:
! 750: /* Do selected union field */
! 751: if (ASPRINTF(t->mtype,
! 752: &ename, "%s%s%s", name, dot, field->name) == -1)
! 753: return (-1);
! 754: if (structs_trav(t, ename, field->type, un->un) == -1) {
! 755: FREE(t->mtype, ename);
! 756: return (-1);
! 757: }
! 758: FREE(t->mtype, ename);
! 759:
! 760: /* Done */
! 761: return (0);
! 762: }
! 763:
! 764: default:
! 765: assert(0);
! 766: errno = ECONNABORTED;
! 767: return (-1);
! 768: }
! 769: }
! 770:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>