1/* 2 * Copyright 2001-2004 Brandon Long 3 * All Rights Reserved. 4 * 5 * ClearSilver Templating System 6 * 7 * This code is made available under the terms of the ClearSilver License. 8 * http://www.clearsilver.net/license.hdf 9 * 10 */ 11 12#include "cs_config.h" 13 14#include <stdlib.h> 15#include <unistd.h> 16#include <string.h> 17#include <stdio.h> 18#include <ctype.h> 19#include <errno.h> 20#include <limits.h> 21#include <stdarg.h> 22#include <sys/stat.h> 23#include "neo_misc.h" 24#include "neo_err.h" 25#include "neo_rand.h" 26#include "neo_hdf.h" 27#include "neo_str.h" 28#include "neo_files.h" 29#include "ulist.h" 30 31/* Ok, in order to use the hash, we have to support n-len strings 32 * instead of null terminated strings (since in set_value and walk_hdf 33 * we are merely using part of the HDF name for lookup, and that might 34 * be a const, and we don't want the overhead of allocating/copying 35 * that data out...) 36 * 37 * Since HASH doesn't maintain any data placed in it, merely pointers to 38 * it, we use the HDF node itself as the key, and have specific 39 * comp/hash functions which just use the name/name_len as the key. 40 */ 41 42static int hash_hdf_comp(const void *a, const void *b) 43{ 44 HDF *ha = (HDF *)a; 45 HDF *hb = (HDF *)b; 46 47 return (ha->name_len == hb->name_len) && !strncmp(ha->name, hb->name, ha->name_len); 48} 49 50static UINT32 hash_hdf_hash(const void *a) 51{ 52 HDF *ha = (HDF *)a; 53 return ne_crc((UINT8 *)(ha->name), ha->name_len); 54} 55 56static NEOERR *_alloc_hdf (HDF **hdf, const char *name, size_t nlen, 57 const char *value, int dup, int wf, HDF *top) 58{ 59 *hdf = calloc (1, sizeof (HDF)); 60 if (*hdf == NULL) 61 { 62 return nerr_raise (NERR_NOMEM, "Unable to allocate memory for hdf element"); 63 } 64 65 (*hdf)->top = top; 66 67 if (name != NULL) 68 { 69 (*hdf)->name_len = nlen; 70 (*hdf)->name = (char *) malloc (nlen + 1); 71 if ((*hdf)->name == NULL) 72 { 73 free((*hdf)); 74 (*hdf) = NULL; 75 return nerr_raise (NERR_NOMEM, 76 "Unable to allocate memory for hdf element: %s", name); 77 } 78 strncpy((*hdf)->name, name, nlen); 79 (*hdf)->name[nlen] = '\0'; 80 } 81 if (value != NULL) 82 { 83 if (dup) 84 { 85 (*hdf)->alloc_value = 1; 86 (*hdf)->value = strdup(value); 87 if ((*hdf)->value == NULL) 88 { 89 free((*hdf)->name); 90 free((*hdf)); 91 (*hdf) = NULL; 92 return nerr_raise (NERR_NOMEM, 93 "Unable to allocate memory for hdf element %s", name); 94 } 95 } 96 else 97 { 98 (*hdf)->alloc_value = wf; 99 /* We're overriding the const of value here for the set_buf case 100 * where we overrode the char * to const char * earlier, since 101 * alloc_value actually keeps track of the const-ness for us */ 102 (*hdf)->value = (char *)value; 103 } 104 } 105 return STATUS_OK; 106} 107 108static void _dealloc_hdf_attr(HDF_ATTR **attr) 109{ 110 HDF_ATTR *next; 111 112 while ((*attr) != NULL) 113 { 114 next = (*attr)->next; 115 if ((*attr)->key) free((*attr)->key); 116 if ((*attr)->value) free((*attr)->value); 117 free(*attr); 118 *attr = next; 119 } 120 *attr = NULL; 121} 122 123static void _dealloc_hdf (HDF **hdf) 124{ 125 HDF *myhdf = *hdf; 126 HDF *next = NULL; 127 128 if (myhdf == NULL) return; 129 if (myhdf->child != NULL) 130 _dealloc_hdf(&(myhdf->child)); 131 132 /* This was easier recursively, but dangerous on long lists, so we 133 * walk it ourselves */ 134 next = myhdf->next; 135 while (next != NULL) 136 { 137 myhdf->next = next->next; 138 next->next = NULL; 139 _dealloc_hdf(&next); 140 next = myhdf->next; 141 } 142 if (myhdf->name != NULL) 143 { 144 free (myhdf->name); 145 myhdf->name = NULL; 146 } 147 if (myhdf->value != NULL) 148 { 149 if (myhdf->alloc_value) 150 free (myhdf->value); 151 myhdf->value = NULL; 152 } 153 if (myhdf->attr != NULL) 154 { 155 _dealloc_hdf_attr(&(myhdf->attr)); 156 } 157 if (myhdf->hash != NULL) 158 { 159 ne_hash_destroy(&myhdf->hash); 160 } 161 free(myhdf); 162 *hdf = NULL; 163} 164 165NEOERR* hdf_init (HDF **hdf) 166{ 167 NEOERR *err; 168 HDF *my_hdf; 169 170 *hdf = NULL; 171 172 err = nerr_init(); 173 if (err != STATUS_OK) 174 return nerr_pass (err); 175 176 err = _alloc_hdf (&my_hdf, NULL, 0, NULL, 0, 0, NULL); 177 if (err != STATUS_OK) 178 return nerr_pass (err); 179 180 my_hdf->top = my_hdf; 181 182 *hdf = my_hdf; 183 184 return STATUS_OK; 185} 186 187void hdf_destroy (HDF **hdf) 188{ 189 if (*hdf == NULL) return; 190 if ((*hdf)->top == (*hdf)) 191 { 192 _dealloc_hdf(hdf); 193 } 194} 195 196static int _walk_hdf (HDF *hdf, const char *name, HDF **node) 197{ 198 HDF *parent = NULL; 199 HDF *hp = hdf; 200 HDF hash_key; 201 int x = 0; 202 const char *s, *n; 203 int r; 204 205 *node = NULL; 206 207 if (hdf == NULL) return -1; 208 if (name == NULL || name[0] == '\0') 209 { 210 *node = hdf; 211 return 0; 212 } 213 214 if (hdf->link) 215 { 216 r = _walk_hdf (hdf->top, hdf->value, &hp); 217 if (r) return r; 218 if (hp) 219 { 220 parent = hp; 221 hp = hp->child; 222 } 223 } 224 else 225 { 226 parent = hdf; 227 hp = hdf->child; 228 } 229 if (hp == NULL) 230 { 231 return -1; 232 } 233 234 n = name; 235 s = strchr (n, '.'); 236 x = (s == NULL) ? strlen(n) : s - n; 237 238 while (1) 239 { 240 if (parent && parent->hash) 241 { 242 hash_key.name = (char *)n; 243 hash_key.name_len = x; 244 hp = ne_hash_lookup(parent->hash, &hash_key); 245 } 246 else 247 { 248 while (hp != NULL) 249 { 250 if (hp->name && (x == hp->name_len) && !strncmp(hp->name, n, x)) 251 { 252 break; 253 } 254 else 255 { 256 hp = hp->next; 257 } 258 } 259 } 260 if (hp == NULL) 261 { 262 return -1; 263 } 264 if (s == NULL) break; 265 266 if (hp->link) 267 { 268 r = _walk_hdf (hp->top, hp->value, &hp); 269 if (r) { 270 return r; 271 } 272 parent = hp; 273 hp = hp->child; 274 } 275 else 276 { 277 parent = hp; 278 hp = hp->child; 279 } 280 n = s + 1; 281 s = strchr (n, '.'); 282 x = (s == NULL) ? strlen(n) : s - n; 283 } 284 if (hp->link) 285 { 286 return _walk_hdf (hp->top, hp->value, node); 287 } 288 289 *node = hp; 290 return 0; 291} 292 293int hdf_get_int_value (HDF *hdf, const char *name, int defval) 294{ 295 HDF *node; 296 int v; 297 char *n; 298 299 if ((_walk_hdf(hdf, name, &node) == 0) && (node->value != NULL)) 300 { 301 v = strtol (node->value, &n, 10); 302 if (node->value == n) v = defval; 303 return v; 304 } 305 return defval; 306} 307 308/* This should return a const char *, but changing this would have big 309 * repurcussions for any C code using this function, so no change for now */ 310char* hdf_get_value (HDF *hdf, const char *name, const char *defval) 311{ 312 HDF *node; 313 314 if ((_walk_hdf(hdf, name, &node) == 0) && (node->value != NULL)) 315 { 316 return node->value; 317 } 318 return (char *)defval; 319} 320 321char* hdf_get_valuevf (HDF *hdf, const char *namefmt, va_list ap) 322{ 323 HDF *node; 324 char *name; 325 326 name = vsprintf_alloc(namefmt, ap); 327 if (name == NULL) return NULL; 328 if ((_walk_hdf(hdf, name, &node) == 0) && (node->value != NULL)) 329 { 330 free(name); 331 return node->value; 332 } 333 free(name); 334 return NULL; 335} 336 337char* hdf_get_valuef (HDF *hdf, const char *namefmt, ...) 338{ 339 char *val; 340 va_list ap; 341 342 va_start(ap, namefmt); 343 val = hdf_get_valuevf(hdf, namefmt, ap); 344 va_end(ap); 345 return val; 346} 347 348NEOERR* hdf_get_copy (HDF *hdf, const char *name, char **value, 349 const char *defval) 350{ 351 HDF *node; 352 353 if ((_walk_hdf(hdf, name, &node) == 0) && (node->value != NULL)) 354 { 355 *value = strdup(node->value); 356 if (*value == NULL) 357 { 358 return nerr_raise (NERR_NOMEM, "Unable to allocate copy of %s", name); 359 } 360 } 361 else 362 { 363 if (defval == NULL) 364 *value = NULL; 365 else 366 { 367 *value = strdup(defval); 368 if (*value == NULL) 369 { 370 return nerr_raise (NERR_NOMEM, "Unable to allocate copy of %s", name); 371 } 372 } 373 } 374 return STATUS_OK; 375} 376 377HDF* hdf_get_obj (HDF *hdf, const char *name) 378{ 379 HDF *obj; 380 381 _walk_hdf(hdf, name, &obj); 382 return obj; 383} 384 385HDF* hdf_get_child (HDF *hdf, const char *name) 386{ 387 HDF *obj; 388 _walk_hdf(hdf, name, &obj); 389 if (obj != NULL) return obj->child; 390 return obj; 391} 392 393HDF_ATTR* hdf_get_attr (HDF *hdf, const char *name) 394{ 395 HDF *obj; 396 _walk_hdf(hdf, name, &obj); 397 if (obj != NULL) return obj->attr; 398 return NULL; 399} 400 401NEOERR* hdf_set_attr (HDF *hdf, const char *name, const char *key, 402 const char *value) 403{ 404 HDF *obj; 405 HDF_ATTR *attr, *last; 406 407 _walk_hdf(hdf, name, &obj); 408 if (obj == NULL) 409 return nerr_raise(NERR_ASSERT, "Unable to set attribute on none existant node"); 410 411 if (obj->attr != NULL) 412 { 413 attr = obj->attr; 414 last = attr; 415 while (attr != NULL) 416 { 417 if (!strcmp(attr->key, key)) 418 { 419 if (attr->value) free(attr->value); 420 /* a set of NULL deletes the attr */ 421 if (value == NULL) 422 { 423 if (attr == obj->attr) 424 obj->attr = attr->next; 425 else 426 last->next = attr->next; 427 free(attr->key); 428 free(attr); 429 return STATUS_OK; 430 } 431 attr->value = strdup(value); 432 if (attr->value == NULL) 433 return nerr_raise(NERR_NOMEM, "Unable to set attr %s to %s", key, value); 434 return STATUS_OK; 435 } 436 last = attr; 437 attr = attr->next; 438 } 439 last->next = (HDF_ATTR *) calloc(1, sizeof(HDF_ATTR)); 440 if (last->next == NULL) 441 return nerr_raise(NERR_NOMEM, "Unable to set attr %s to %s", key, value); 442 attr = last->next; 443 } 444 else 445 { 446 if (value == NULL) return STATUS_OK; 447 obj->attr = (HDF_ATTR *) calloc(1, sizeof(HDF_ATTR)); 448 if (obj->attr == NULL) 449 return nerr_raise(NERR_NOMEM, "Unable to set attr %s to %s", key, value); 450 attr = obj->attr; 451 } 452 attr->key = strdup(key); 453 attr->value = strdup(value); 454 if (attr->key == NULL || attr->value == NULL) 455 return nerr_raise(NERR_NOMEM, "Unable to set attr %s to %s", key, value); 456 457 return STATUS_OK; 458} 459 460HDF* hdf_obj_child (HDF *hdf) 461{ 462 HDF *obj; 463 if (hdf == NULL) return NULL; 464 if (hdf->link) 465 { 466 if (_walk_hdf(hdf->top, hdf->value, &obj)) 467 return NULL; 468 return obj->child; 469 } 470 return hdf->child; 471} 472 473HDF* hdf_obj_next (HDF *hdf) 474{ 475 if (hdf == NULL) return NULL; 476 return hdf->next; 477} 478 479HDF* hdf_obj_top (HDF *hdf) 480{ 481 if (hdf == NULL) return NULL; 482 return hdf->top; 483} 484 485HDF_ATTR* hdf_obj_attr (HDF *hdf) 486{ 487 if (hdf == NULL) return NULL; 488 return hdf->attr; 489} 490 491char* hdf_obj_name (HDF *hdf) 492{ 493 if (hdf == NULL) return NULL; 494 return hdf->name; 495} 496 497char* hdf_obj_value (HDF *hdf) 498{ 499 int count = 0; 500 501 if (hdf == NULL) return NULL; 502 while (hdf->link && count < 100) 503 { 504 if (_walk_hdf (hdf->top, hdf->value, &hdf)) 505 return NULL; 506 count++; 507 } 508 return hdf->value; 509} 510 511void _merge_attr (HDF_ATTR *dest, HDF_ATTR *src) 512{ 513 HDF_ATTR *da, *ld; 514 HDF_ATTR *sa, *ls; 515 BOOL found; 516 517 sa = src; 518 ls = src; 519 while (sa != NULL) 520 { 521 da = dest; 522 ld = da; 523 found = 0; 524 while (da != NULL) 525 { 526 if (!strcmp(da->key, sa->key)) 527 { 528 if (da->value) free(da->value); 529 da->value = sa->value; 530 sa->value = NULL; 531 found = 1; 532 break; 533 } 534 ld = da; 535 da = da->next; 536 } 537 if (!found) 538 { 539 ld->next = sa; 540 ls->next = sa->next; 541 if (src == sa) src = sa->next; 542 ld->next->next = NULL; 543 sa = ls->next; 544 } 545 else 546 { 547 ls = sa; 548 sa = sa->next; 549 } 550 } 551 _dealloc_hdf_attr(&src); 552} 553 554NEOERR* _hdf_hash_level(HDF *hdf) 555{ 556 NEOERR *err; 557 HDF *child; 558 559 err = ne_hash_init(&(hdf->hash), hash_hdf_hash, hash_hdf_comp); 560 if (err) return nerr_pass(err); 561 562 child = hdf->child; 563 while (child) 564 { 565 err = ne_hash_insert(hdf->hash, child, child); 566 if (err) return nerr_pass(err); 567 child = child->next; 568 } 569 return STATUS_OK; 570} 571 572static NEOERR* _set_value (HDF *hdf, const char *name, const char *value, 573 int dup, int wf, int link, HDF_ATTR *attr, 574 HDF **set_node) 575{ 576 NEOERR *err; 577 HDF *hn, *hp, *hs; 578 HDF hash_key; 579 int x = 0; 580 const char *s = name; 581 const char *n = name; 582 int count = 0; 583 584 if (set_node != NULL) *set_node = NULL; 585 if (hdf == NULL) 586 { 587 return nerr_raise(NERR_ASSERT, "Unable to set %s on NULL hdf", name); 588 } 589 590 /* HACK: allow setting of this node by passing an empty name */ 591 if (name == NULL || name[0] == '\0') 592 { 593 /* handle setting attr first */ 594 if (hdf->attr == NULL) 595 { 596 hdf->attr = attr; 597 } 598 else 599 { 600 _merge_attr(hdf->attr, attr); 601 } 602 /* if we're setting ourselves to ourselves... */ 603 if (hdf->value == value) 604 { 605 if (set_node != NULL) *set_node = hdf; 606 return STATUS_OK; 607 } 608 if (hdf->alloc_value) 609 { 610 free(hdf->value); 611 hdf->value = NULL; 612 } 613 if (value == NULL) 614 { 615 hdf->alloc_value = 0; 616 hdf->value = NULL; 617 } 618 else if (dup) 619 { 620 hdf->alloc_value = 1; 621 hdf->value = strdup(value); 622 if (hdf->value == NULL) 623 return nerr_raise (NERR_NOMEM, "Unable to duplicate value %s for %s", 624 value, name); 625 } 626 else 627 { 628 hdf->alloc_value = wf; 629 hdf->value = (char *)value; 630 } 631 if (set_node != NULL) *set_node = hdf; 632 return STATUS_OK; 633 } 634 635 n = name; 636 s = strchr (n, '.'); 637 x = (s != NULL) ? s - n : strlen(n); 638 if (x == 0) 639 { 640 return nerr_raise(NERR_ASSERT, "Unable to set Empty component %s", name); 641 } 642 643 if (hdf->link) 644 { 645 char *new_name = (char *) malloc(strlen(hdf->value) + 1 + strlen(name) + 1); 646 if (new_name == NULL) 647 { 648 return nerr_raise(NERR_NOMEM, "Unable to allocate memory"); 649 } 650 strcpy(new_name, hdf->value); 651 strcat(new_name, "."); 652 strcat(new_name, name); 653 err = _set_value (hdf->top, new_name, value, dup, wf, link, attr, set_node); 654 free(new_name); 655 return nerr_pass(err); 656 } 657 else 658 { 659 hn = hdf; 660 } 661 662 while (1) 663 { 664 /* examine cache to see if we have a match */ 665 count = 0; 666 hp = hn->last_hp; 667 hs = hn->last_hs; 668 669 if ((hs == NULL && hp == hn->child) || (hs && hs->next == hp)) 670 { 671 if (hp && hp->name && (x == hp->name_len) && !strncmp (hp->name, n, x)) 672 { 673 goto skip_search; 674 } 675 } 676 677 hp = hn->child; 678 hs = NULL; 679 680 /* Look for a matching node at this level */ 681 if (hn->hash != NULL) 682 { 683 hash_key.name = (char *)n; 684 hash_key.name_len = x; 685 hp = ne_hash_lookup(hn->hash, &hash_key); 686 hs = hn->last_child; 687 } 688 else 689 { 690 while (hp != NULL) 691 { 692 if (hp->name && (x == hp->name_len) && !strncmp(hp->name, n, x)) 693 { 694 break; 695 } 696 hs = hp; 697 hp = hp->next; 698 count++; 699 } 700 } 701 702 /* save in cache any value we found */ 703 if (hp) { 704 hn->last_hp = hp; 705 hn->last_hs = hs; 706 } 707 708skip_search: 709 710 if (hp == NULL) 711 { 712 /* If there was no matching node at this level, we need to 713 * allocate an intersitial node (or the actual node if we're 714 * at the last part of the HDF name) */ 715 if (s != NULL) 716 { 717 /* intersitial */ 718 err = _alloc_hdf (&hp, n, x, NULL, 0, 0, hdf->top); 719 } 720 else 721 { 722 err = _alloc_hdf (&hp, n, x, value, dup, wf, hdf->top); 723 if (link) hp->link = 1; 724 else hp->link = 0; 725 hp->attr = attr; 726 } 727 if (err != STATUS_OK) 728 return nerr_pass (err); 729 if (hn->child == NULL) 730 hn->child = hp; 731 else 732 hs->next = hp; 733 hn->last_child = hp; 734 735 /* This is the point at which we convert to a hash table 736 * at this level, if we're over the count */ 737 if (count > FORCE_HASH_AT && hn->hash == NULL) 738 { 739 err = _hdf_hash_level(hn); 740 if (err) return nerr_pass(err); 741 } 742 else if (hn->hash != NULL) 743 { 744 err = ne_hash_insert(hn->hash, hp, hp); 745 if (err) return nerr_pass(err); 746 } 747 } 748 else if (s == NULL) 749 { 750 /* If there is a matching node and we're at the end of the HDF 751 * name, then we update the value of the node */ 752 /* handle setting attr first */ 753 if (hp->attr == NULL) 754 { 755 hp->attr = attr; 756 } 757 else 758 { 759 _merge_attr(hp->attr, attr); 760 } 761 if (hp->value != value) 762 { 763 if (hp->alloc_value) 764 { 765 free(hp->value); 766 hp->value = NULL; 767 } 768 if (value == NULL) 769 { 770 hp->alloc_value = 0; 771 hp->value = NULL; 772 } 773 else if (dup) 774 { 775 hp->alloc_value = 1; 776 hp->value = strdup(value); 777 if (hp->value == NULL) 778 return nerr_raise (NERR_NOMEM, "Unable to duplicate value %s for %s", 779 value, name); 780 } 781 else 782 { 783 hp->alloc_value = wf; 784 hp->value = (char *)value; 785 } 786 } 787 if (link) hp->link = 1; 788 else hp->link = 0; 789 } 790 else if (hp->link) 791 { 792 char *new_name = (char *) malloc(strlen(hp->value) + strlen(s) + 1); 793 if (new_name == NULL) 794 { 795 return nerr_raise(NERR_NOMEM, "Unable to allocate memory"); 796 } 797 strcpy(new_name, hp->value); 798 strcat(new_name, s); 799 err = _set_value (hdf->top, new_name, value, dup, wf, link, attr, set_node); 800 free(new_name); 801 return nerr_pass(err); 802 } 803 /* At this point, we're done if there is not more HDF name space to 804 * traverse */ 805 if (s == NULL) 806 break; 807 /* Otherwise, we need to find the next part of the namespace */ 808 n = s + 1; 809 s = strchr (n, '.'); 810 x = (s != NULL) ? s - n : strlen(n); 811 if (x == 0) 812 { 813 return nerr_raise(NERR_ASSERT, "Unable to set Empty component %s", name); 814 } 815 hn = hp; 816 } 817 if (set_node != NULL) *set_node = hp; 818 return STATUS_OK; 819} 820 821NEOERR* hdf_set_value (HDF *hdf, const char *name, const char *value) 822{ 823 return nerr_pass(_set_value (hdf, name, value, 1, 1, 0, NULL, NULL)); 824} 825 826NEOERR* hdf_set_value_attr (HDF *hdf, const char *name, const char *value, 827 HDF_ATTR *attr) 828{ 829 return nerr_pass(_set_value (hdf, name, value, 1, 1, 0, attr, NULL)); 830} 831 832NEOERR* hdf_set_symlink (HDF *hdf, const char *src, const char *dest) 833{ 834 return nerr_pass(_set_value (hdf, src, dest, 1, 1, 1, NULL, NULL)); 835} 836 837NEOERR* hdf_set_int_value (HDF *hdf, const char *name, int value) 838{ 839 char buf[256]; 840 841 snprintf (buf, sizeof(buf), "%d", value); 842 return nerr_pass(_set_value (hdf, name, buf, 1, 1, 0, NULL, NULL)); 843} 844 845NEOERR* hdf_set_buf (HDF *hdf, const char *name, char *value) 846{ 847 return nerr_pass(_set_value (hdf, name, value, 0, 1, 0, NULL, NULL)); 848} 849 850NEOERR* hdf_set_copy (HDF *hdf, const char *dest, const char *src) 851{ 852 HDF *node; 853 if ((_walk_hdf(hdf, src, &node) == 0) && (node->value != NULL)) 854 { 855 return nerr_pass(_set_value (hdf, dest, node->value, 0, 0, 0, NULL, NULL)); 856 } 857 return nerr_raise (NERR_NOT_FOUND, "Unable to find %s", src); 858} 859 860NEOERR* hdf_set_valuevf (HDF *hdf, const char *fmt, va_list ap) 861{ 862 NEOERR *err; 863 char *k; 864 char *v; 865 866 k = vsprintf_alloc(fmt, ap); 867 if (k == NULL) 868 { 869 return nerr_raise(NERR_NOMEM, "Unable to allocate memory for format string"); 870 } 871 v = strchr(k, '='); 872 if (v == NULL) 873 { 874 err = nerr_raise(NERR_ASSERT, "No equals found: %s", k); 875 free(k); 876 return err; 877 } 878 *v++ = '\0'; 879 err = hdf_set_value(hdf, k, v); 880 free(k); 881 return nerr_pass(err); 882} 883 884NEOERR* hdf_set_valuef (HDF *hdf, const char *fmt, ...) 885{ 886 NEOERR *err; 887 va_list ap; 888 889 va_start(ap, fmt); 890 err = hdf_set_valuevf(hdf, fmt, ap); 891 va_end(ap); 892 return nerr_pass(err); 893} 894 895NEOERR* hdf_get_node (HDF *hdf, const char *name, HDF **ret) 896{ 897 _walk_hdf(hdf, name, ret); 898 if (*ret == NULL) 899 { 900 return nerr_pass(_set_value (hdf, name, NULL, 0, 1, 0, NULL, ret)); 901 } 902 return STATUS_OK; 903} 904 905/* Ok, this version avoids the bubble sort by walking the level once to 906 * load them all into a ULIST, qsort'ing the list, and then dumping them 907 * back out... */ 908NEOERR *hdf_sort_obj (HDF *h, int (*compareFunc)(const void *, const void *)) 909{ 910 NEOERR *err = STATUS_OK; 911 ULIST *level = NULL; 912 HDF *p, *c; 913 int x; 914 915 if (h == NULL) return STATUS_OK; 916 c = h->child; 917 if (c == NULL) return STATUS_OK; 918 919 do { 920 err = uListInit(&level, 40, 0); 921 if (err) return nerr_pass(err); 922 for (p = c; p; p = p->next) { 923 err = uListAppend(level, p); 924 if (err) break; 925 } 926 err = uListSort(level, compareFunc); 927 if (err) break; 928 uListGet(level, 0, (void *)&c); 929 h->child = c; 930 for (x = 1; x < uListLength(level); x++) 931 { 932 uListGet(level, x, (void *)&p); 933 c->next = p; 934 p->next = NULL; 935 c = p; 936 } 937 h->last_child = c; 938 } while (0); 939 uListDestroy(&level, 0); 940 return nerr_pass(err); 941} 942 943NEOERR* hdf_remove_tree (HDF *hdf, const char *name) 944{ 945 HDF *hp = hdf; 946 HDF *lp = NULL, *ln = NULL; /* last parent, last node */ 947 int x = 0; 948 const char *s = name; 949 const char *n = name; 950 951 if (hdf == NULL) return STATUS_OK; 952 953 hp = hdf->child; 954 if (hp == NULL) 955 { 956 return STATUS_OK; 957 } 958 959 lp = hdf; 960 ln = NULL; 961 962 n = name; 963 s = strchr (n, '.'); 964 x = (s == NULL) ? strlen(n) : s - n; 965 966 while (1) 967 { 968 while (hp != NULL) 969 { 970 if (hp->name && (x == hp->name_len) && !strncmp(hp->name, n, x)) 971 { 972 break; 973 } 974 else 975 { 976 ln = hp; 977 hp = hp->next; 978 } 979 } 980 if (hp == NULL) 981 { 982 return STATUS_OK; 983 } 984 if (s == NULL) break; 985 986 lp = hp; 987 ln = NULL; 988 hp = hp->child; 989 n = s + 1; 990 s = strchr (n, '.'); 991 x = (s == NULL) ? strlen(n) : s - n; 992 } 993 994 if (lp->hash != NULL) 995 { 996 ne_hash_remove(lp->hash, hp); 997 } 998 if (ln) 999 { 1000 ln->next = hp->next; 1001 /* check to see if we are the last parent's last_child, if so 1002 * repoint so hash table inserts will go to the right place */ 1003 if (hp == lp->last_child) 1004 lp->last_child = ln; 1005 hp->next = NULL; 1006 } 1007 else 1008 { 1009 lp->child = hp->next; 1010 hp->next = NULL; 1011 } 1012 _dealloc_hdf (&hp); 1013 1014 return STATUS_OK; 1015} 1016 1017static NEOERR * _copy_attr (HDF_ATTR **dest, HDF_ATTR *src) 1018{ 1019 HDF_ATTR *copy, *last = NULL; 1020 1021 *dest = NULL; 1022 while (src != NULL) 1023 { 1024 copy = (HDF_ATTR *)malloc(sizeof(HDF_ATTR)); 1025 if (copy == NULL) 1026 { 1027 _dealloc_hdf_attr(dest); 1028 return nerr_raise(NERR_NOMEM, "Unable to allocate copy of HDF_ATTR"); 1029 } 1030 copy->key = strdup(src->key); 1031 copy->value = strdup(src->value); 1032 copy->next = NULL; 1033 if ((copy->key == NULL) || (copy->value == NULL)) 1034 { 1035 _dealloc_hdf_attr(dest); 1036 return nerr_raise(NERR_NOMEM, "Unable to allocate copy of HDF_ATTR"); 1037 } 1038 if (last) { 1039 last->next = copy; 1040 } 1041 else 1042 { 1043 *dest = copy; 1044 } 1045 last = copy; 1046 src = src->next; 1047 } 1048 return STATUS_OK; 1049} 1050 1051static NEOERR * _copy_nodes (HDF *dest, HDF *src) 1052{ 1053 NEOERR *err = STATUS_OK; 1054 HDF *dt, *st; 1055 HDF_ATTR *attr_copy; 1056 1057 st = src->child; 1058 while (st != NULL) 1059 { 1060 err = _copy_attr(&attr_copy, st->attr); 1061 if (err) return nerr_pass(err); 1062 err = _set_value(dest, st->name, st->value, 1, 1, 0, attr_copy, &dt); 1063 if (err) { 1064 _dealloc_hdf_attr(&attr_copy); 1065 return nerr_pass(err); 1066 } 1067 if (src->child) 1068 { 1069 err = _copy_nodes (dt, st); 1070 if (err) return nerr_pass(err); 1071 } 1072 st = st->next; 1073 } 1074 return STATUS_OK; 1075} 1076 1077NEOERR* hdf_copy (HDF *dest, const char *name, HDF *src) 1078{ 1079 NEOERR *err; 1080 HDF *node; 1081 1082 if (_walk_hdf(dest, name, &node) == -1) 1083 { 1084 err = _set_value (dest, name, NULL, 0, 0, 0, NULL, &node); 1085 if (err) return nerr_pass (err); 1086 } 1087 return nerr_pass (_copy_nodes (node, src)); 1088} 1089 1090/* BUG: currently, this only prints something if there is a value... 1091 * but we now allow attributes on nodes with no value... */ 1092 1093static void gen_ml_break(char *ml, size_t len) 1094{ 1095 int nlen; 1096 int x = 0; 1097 1098 ml[x++] = '\n'; 1099 nlen = 2 + neo_rand(len-5); 1100 if (nlen == 0) 1101 { 1102 nlen = len / 2; 1103 } 1104 while (nlen) 1105 { 1106 ml[x++] = ('A' + neo_rand(26)); 1107 nlen--; 1108 } 1109 ml[x++] = '\n'; 1110 ml[x] = '\0'; 1111} 1112 1113typedef NEOERR *(*DUMPF_CB)(void *rock, const char *fmt, ...); 1114 1115static NEOERR *_fp_dump_cb (void *rock, const char *fmt, ...) 1116{ 1117 FILE *fp = (FILE *)rock; 1118 va_list ap; 1119 1120 va_start (ap, fmt); 1121 vfprintf(fp, fmt, ap); 1122 va_end(ap); 1123 return STATUS_OK; 1124} 1125 1126static NEOERR *_string_dump_cb (void *rock, const char *fmt, ...) 1127{ 1128 NEOERR *err; 1129 STRING *str = (STRING *)rock; 1130 va_list ap; 1131 1132 va_start (ap, fmt); 1133 err = string_appendvf(str, fmt, ap); 1134 va_end(ap); 1135 return nerr_pass(err); 1136} 1137 1138#define DUMP_TYPE_DOTTED 0 1139#define DUMP_TYPE_COMPACT 1 1140#define DUMP_TYPE_PRETTY 2 1141 1142static NEOERR* hdf_dump_cb(HDF *hdf, const char *prefix, int dtype, int lvl, 1143 void *rock, DUMPF_CB dump_cbf) 1144{ 1145 NEOERR *err; 1146 char *p, op; 1147 char ml[10] = "\nEOM\n"; 1148 int ml_len = strlen(ml); 1149 char whsp[256] = ""; 1150 1151 if (dtype == DUMP_TYPE_PRETTY) 1152 { 1153 memset(whsp, ' ', 256); 1154 if (lvl > 127) 1155 lvl = 127; 1156 whsp[lvl*2] = '\0'; 1157 } 1158 1159 if (hdf != NULL) hdf = hdf->child; 1160 1161 while (hdf != NULL) 1162 { 1163 op = '='; 1164 if (hdf->value) 1165 { 1166 if (hdf->link) op = ':'; 1167 if (prefix && (dtype == DUMP_TYPE_DOTTED)) 1168 { 1169 err = dump_cbf(rock, "%s.%s", prefix, hdf->name); 1170 } 1171 else 1172 { 1173 err = dump_cbf(rock, "%s%s", whsp, hdf->name); 1174 } 1175 if (err) return nerr_pass (err); 1176 if (hdf->attr) 1177 { 1178 HDF_ATTR *attr = hdf->attr; 1179 char *v = NULL; 1180 1181 err = dump_cbf(rock, " ["); 1182 if (err) return nerr_pass(err); 1183 while (attr != NULL) 1184 { 1185 if (attr->value == NULL || !strcmp(attr->value, "1")) 1186 err = dump_cbf(rock, "%s", attr->key); 1187 else 1188 { 1189 v = repr_string_alloc(attr->value); 1190 1191 if (v == NULL) 1192 return nerr_raise(NERR_NOMEM, "Unable to repr attr %s value %s", attr->key, attr->value); 1193 err = dump_cbf(rock, "%s=%s", attr->key, v); 1194 free(v); 1195 } 1196 if (err) return nerr_pass(err); 1197 if (attr->next) 1198 { 1199 err = dump_cbf(rock, ", "); 1200 if (err) return nerr_pass(err); 1201 } 1202 attr = attr->next; 1203 } 1204 err = dump_cbf(rock, "] "); 1205 if (err) return nerr_pass(err); 1206 } 1207 if (strchr (hdf->value, '\n')) 1208 { 1209 int vlen = strlen(hdf->value); 1210 1211 while (strstr(hdf->value, ml) || ((vlen > ml_len) && !strncmp(hdf->value + vlen - ml_len + 1, ml, strlen(ml) - 1))) 1212 { 1213 gen_ml_break(ml, sizeof(ml)); 1214 ml_len = strlen(ml); 1215 } 1216 if (hdf->value[strlen(hdf->value)-1] != '\n') 1217 err = dump_cbf(rock, " << %s%s%s", ml+1, hdf->value, ml); 1218 else 1219 err = dump_cbf(rock, " << %s%s%s", ml+1, hdf->value, ml+1); 1220 } 1221 else 1222 { 1223 err = dump_cbf(rock, " %c %s\n", op, hdf->value); 1224 } 1225 if (err) return nerr_pass (err); 1226 } 1227 if (hdf->child) 1228 { 1229 if (prefix && (dtype == DUMP_TYPE_DOTTED)) 1230 { 1231 p = (char *) malloc (strlen(hdf->name) + strlen(prefix) + 2); 1232 sprintf (p, "%s.%s", prefix, hdf->name); 1233 err = hdf_dump_cb (hdf, p, dtype, lvl+1, rock, dump_cbf); 1234 free(p); 1235 } 1236 else 1237 { 1238 if (hdf->name && (dtype != DUMP_TYPE_DOTTED)) 1239 { 1240 err = dump_cbf(rock, "%s%s {\n", whsp, hdf->name); 1241 if (err) return nerr_pass (err); 1242 err = hdf_dump_cb (hdf, hdf->name, dtype, lvl+1, rock, dump_cbf); 1243 if (err) return nerr_pass (err); 1244 err = dump_cbf(rock, "%s}\n", whsp); 1245 } 1246 else 1247 { 1248 err = hdf_dump_cb (hdf, hdf->name, dtype, lvl+1, rock, dump_cbf); 1249 } 1250 } 1251 if (err) return nerr_pass (err); 1252 } 1253 hdf = hdf->next; 1254 } 1255 return STATUS_OK; 1256} 1257 1258NEOERR* hdf_dump_str (HDF *hdf, const char *prefix, int dtype, STRING *str) 1259{ 1260 return nerr_pass(hdf_dump_cb(hdf, prefix, dtype, 0, str, _string_dump_cb)); 1261} 1262 1263NEOERR* hdf_dump(HDF *hdf, const char *prefix) 1264{ 1265 return nerr_pass(hdf_dump_cb(hdf, prefix, DUMP_TYPE_DOTTED, 0, stdout, _fp_dump_cb)); 1266} 1267 1268NEOERR* hdf_dump_format (HDF *hdf, int lvl, FILE *fp) 1269{ 1270 return nerr_pass(hdf_dump_cb(hdf, "", DUMP_TYPE_PRETTY, 0, fp, _fp_dump_cb)); 1271} 1272 1273NEOERR *hdf_write_file (HDF *hdf, const char *path) 1274{ 1275 NEOERR *err; 1276 FILE *fp; 1277 1278 fp = fopen(path, "w"); 1279 if (fp == NULL) 1280 return nerr_raise_errno (NERR_IO, "Unable to open %s for writing", path); 1281 1282 err = hdf_dump_format (hdf, 0, fp); 1283 1284 fclose (fp); 1285 if (err) 1286 { 1287 unlink(path); 1288 } 1289 return nerr_pass(err); 1290} 1291 1292NEOERR *hdf_write_file_atomic (HDF *hdf, const char *path) 1293{ 1294 NEOERR *err; 1295 FILE *fp; 1296 char tpath[_POSIX_PATH_MAX]; 1297 static int count = 0; 1298 1299 snprintf(tpath, sizeof(tpath), "%s.%5.5f.%d", path, ne_timef(), count++); 1300 1301 fp = fopen(tpath, "w"); 1302 if (fp == NULL) 1303 return nerr_raise_errno (NERR_IO, "Unable to open %s for writing", tpath); 1304 1305 err = hdf_dump_format (hdf, 0, fp); 1306 1307 fclose (fp); 1308 1309 if (err) 1310 { 1311 unlink(tpath); 1312 return nerr_pass(err); 1313 } 1314 if (rename(tpath, path) == -1) 1315 { 1316 unlink (tpath); 1317 return nerr_raise_errno (NERR_IO, "Unable to rename file %s to %s", 1318 tpath, path); 1319 } 1320 1321 return STATUS_OK; 1322} 1323 1324NEOERR *hdf_write_string (HDF *hdf, char **s) 1325{ 1326 STRING str; 1327 NEOERR *err; 1328 1329 *s = NULL; 1330 1331 string_init (&str); 1332 1333 err = hdf_dump_str (hdf, NULL, 1, &str); 1334 if (err) 1335 { 1336 string_clear (&str); 1337 return nerr_pass(err); 1338 } 1339 if (str.buf == NULL) 1340 { 1341 *s = strdup(""); 1342 if (*s == NULL) return nerr_raise(NERR_NOMEM, "Unable to allocate empty string"); 1343 } 1344 else 1345 { 1346 *s = str.buf; 1347 } 1348 1349 return STATUS_OK; 1350} 1351 1352 1353#define SKIPWS(s) while (*s && isspace(*s)) s++; 1354 1355static int _copy_line (const char **s, char *buf, size_t buf_len) 1356{ 1357 int x = 0; 1358 const char *st = *s; 1359 1360 while (*st && x < buf_len-1) 1361 { 1362 buf[x++] = *st; 1363 if (*st++ == '\n') break; 1364 } 1365 buf[x] = '\0'; 1366 *s = st; 1367 1368 return x; 1369} 1370 1371/* Copy the characters in the file (up to the next newline) into line 1372 * and advance s to the next line */ 1373static NEOERR *_copy_line_advance(const char **s, STRING *line) 1374{ 1375 NEOERR *err; 1376 int x = 0; 1377 const char *st = *s; 1378 const char *nl; 1379 1380 nl = strchr(st, '\n'); 1381 if (nl == NULL) 1382 { 1383 x = strlen(st); 1384 err = string_appendn(line, st, x); 1385 if (err) return nerr_pass(err); 1386 *s = st + x; 1387 } 1388 else 1389 { 1390 x = nl - st; 1391 err = string_appendn(line, st, x); 1392 if (err) return nerr_pass(err); 1393 *s = nl + 1; 1394 } 1395 1396 return STATUS_OK; 1397} 1398 1399char *_strndup(const char *s, int len) { 1400 int x; 1401 char *dup; 1402 if (s == NULL) return NULL; 1403 dup = (char *) malloc(len+1); 1404 if (dup == NULL) return NULL; 1405 for (x = 0; x < len && s[x]; x++) 1406 { 1407 dup[x] = s[x]; 1408 } 1409 dup[x] = '\0'; 1410 dup[len] = '\0'; 1411 return dup; 1412} 1413 1414/* attributes are of the form [key1, key2, key3=value, key4="repr"] */ 1415static NEOERR* parse_attr(char **str, HDF_ATTR **attr) 1416{ 1417 NEOERR *err = STATUS_OK; 1418 char *s = *str; 1419 char *k, *v; 1420 int k_l, v_l; 1421 STRING buf; 1422 char c; 1423 HDF_ATTR *ha, *hal = NULL; 1424 1425 *attr = NULL; 1426 1427 string_init(&buf); 1428 while (*s && *s != ']') 1429 { 1430 k = s; 1431 k_l = 0; 1432 v = NULL; 1433 v_l = 0; 1434 while (*s && isalnum(*s)) s++; 1435 k_l = s-k; 1436 if (*s == '\0' || k_l == 0) 1437 { 1438 _dealloc_hdf_attr(attr); 1439 return nerr_raise(NERR_PARSE, "Misformed attribute specification: %s", *str); 1440 } 1441 SKIPWS(s); 1442 if (*s == '=') 1443 { 1444 s++; 1445 SKIPWS(s); 1446 if (*s == '"') 1447 { 1448 s++; 1449 while (*s && *s != '"') 1450 { 1451 if (*s == '\\') 1452 { 1453 if (isdigit(*(s+1))) 1454 { 1455 s++; 1456 c = *s - '0'; 1457 if (isdigit(*(s+1))) 1458 { 1459 s++; 1460 c = (c * 8) + (*s - '0'); 1461 if (isdigit(*(s+1))) 1462 { 1463 s++; 1464 c = (c * 8) + (*s - '0'); 1465 } 1466 } 1467 } 1468 else 1469 { 1470 s++; 1471 if (*s == 'n') c = '\n'; 1472 else if (*s == 't') c = '\t'; 1473 else if (*s == 'r') c = '\r'; 1474 else c = *s; 1475 } 1476 err = string_append_char(&buf, c); 1477 } 1478 else 1479 { 1480 err = string_append_char(&buf, *s); 1481 } 1482 if (err) 1483 { 1484 string_clear(&buf); 1485 _dealloc_hdf_attr(attr); 1486 return nerr_pass(err); 1487 } 1488 s++; 1489 } 1490 if (*s == '\0') 1491 { 1492 _dealloc_hdf_attr(attr); 1493 string_clear(&buf); 1494 return nerr_raise(NERR_PARSE, "Misformed attribute specification: %s", *str); 1495 } 1496 s++; 1497 v = buf.buf; 1498 v_l = buf.len; 1499 } 1500 else 1501 { 1502 v = s; 1503 while (*s && *s != ' ' && *s != ',' && *s != ']') s++; 1504 if (*s == '\0') 1505 { 1506 _dealloc_hdf_attr(attr); 1507 return nerr_raise(NERR_PARSE, "Misformed attribute specification: %s", *str); 1508 } 1509 v_l = s-v; 1510 } 1511 } 1512 else 1513 { 1514 v = "1"; 1515 } 1516 ha = (HDF_ATTR*) calloc (1, sizeof(HDF_ATTR)); 1517 if (ha == NULL) 1518 { 1519 _dealloc_hdf_attr(attr); 1520 string_clear(&buf); 1521 return nerr_raise(NERR_NOMEM, "Unable to load attributes: %s", s); 1522 } 1523 if (*attr == NULL) *attr = ha; 1524 ha->key = _strndup(k, k_l); 1525 if (v) 1526 ha->value = _strndup(v, v_l); 1527 else 1528 ha->value = strdup(""); 1529 if (ha->key == NULL || ha->value == NULL) 1530 { 1531 _dealloc_hdf_attr(attr); 1532 string_clear(&buf); 1533 return nerr_raise(NERR_NOMEM, "Unable to load attributes: %s", s); 1534 } 1535 if (hal != NULL) hal->next = ha; 1536 hal = ha; 1537 string_clear(&buf); 1538 SKIPWS(s); 1539 if (*s == ',') 1540 { 1541 s++; 1542 SKIPWS(s); 1543 } 1544 } 1545 if (*s == '\0') 1546 { 1547 _dealloc_hdf_attr(attr); 1548 return nerr_raise(NERR_PARSE, "Misformed attribute specification: %s", *str); 1549 } 1550 *str = s+1; 1551 return STATUS_OK; 1552} 1553 1554#define INCLUDE_ERROR 0 1555#define INCLUDE_IGNORE 1 1556#define INCLUDE_FILE 2 1557 1558static NEOERR* _hdf_read_string (HDF *hdf, const char **str, STRING *line, 1559 const char *path, int *lineno, int include_handle) 1560{ 1561 NEOERR *err; 1562 HDF *lower; 1563 char *s; 1564 char *name, *value; 1565 HDF_ATTR *attr = NULL; 1566 1567 while (**str != '\0') 1568 { 1569 /* Reset string length, but don't free the reserved buffer */ 1570 line->len = 0; 1571 err = _copy_line_advance(str, line); 1572 if (err) return nerr_pass(err); 1573 attr = NULL; 1574 (*lineno)++; 1575 s = line->buf; 1576 SKIPWS(s); 1577 if (!strncmp(s, "#include ", 9)) 1578 { 1579 if (include_handle == INCLUDE_ERROR) 1580 { 1581 return nerr_raise (NERR_PARSE, 1582 "[%d]: #include not supported in string parse", 1583 *lineno); 1584 } 1585 else if (include_handle == INCLUDE_FILE) 1586 { 1587 int l; 1588 s += 9; 1589 name = neos_strip(s); 1590 l = strlen(name); 1591 if (name[0] == '"' && name[l-1] == '"') 1592 { 1593 name[l-1] = '\0'; 1594 name++; 1595 } 1596 err = hdf_read_file(hdf, name); 1597 if (err != STATUS_OK) 1598 { 1599 return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); 1600 } 1601 } 1602 } 1603 else if (s[0] == '#') 1604 { 1605 /* comment: pass */ 1606 } 1607 else if (s[0] == '}') /* up */ 1608 { 1609 s = neos_strip(s); 1610 if (strcmp(s, "}")) 1611 { 1612 err = nerr_raise(NERR_PARSE, 1613 "[%s:%d] Trailing garbage on line following }: %s", path, *lineno, 1614 line->buf); 1615 return err; 1616 } 1617 return STATUS_OK; 1618 } 1619 else if (s[0]) 1620 { 1621 /* Valid hdf name is [0-9a-zA-Z_.]+ */ 1622 name = s; 1623 while (*s && (isalnum(*s) || *s == '_' || *s == '.')) s++; 1624 SKIPWS(s); 1625 1626 if (s[0] == '[') /* attributes */ 1627 { 1628 *s = '\0'; 1629 name = neos_strip(name); 1630 s++; 1631 err = parse_attr(&s, &attr); 1632 if (err) 1633 { 1634 return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); 1635 } 1636 SKIPWS(s); 1637 } 1638 if (s[0] == '=') /* assignment */ 1639 { 1640 *s = '\0'; 1641 name = neos_strip(name); 1642 s++; 1643 value = neos_strip(s); 1644 err = _set_value (hdf, name, value, 1, 1, 0, attr, NULL); 1645 if (err != STATUS_OK) 1646 { 1647 return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); 1648 } 1649 } 1650 else if (s[0] == ':' && s[1] == '=') /* copy */ 1651 { 1652 *s = '\0'; 1653 name = neos_strip(name); 1654 s+=2; 1655 value = neos_strip(s); 1656 value = hdf_get_value(hdf->top, value, ""); 1657 err = _set_value (hdf, name, value, 1, 1, 0, attr, NULL); 1658 if (err != STATUS_OK) 1659 { 1660 return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); 1661 } 1662 } 1663 else if (s[0] == ':') /* link */ 1664 { 1665 *s = '\0'; 1666 name = neos_strip(name); 1667 s++; 1668 value = neos_strip(s); 1669 err = _set_value (hdf, name, value, 1, 1, 1, attr, NULL); 1670 if (err != STATUS_OK) 1671 { 1672 return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); 1673 } 1674 } 1675 else if (s[0] == '{') /* deeper */ 1676 { 1677 *s = '\0'; 1678 name = neos_strip(name); 1679 lower = hdf_get_obj (hdf, name); 1680 if (lower == NULL) 1681 { 1682 err = _set_value (hdf, name, NULL, 1, 1, 0, attr, &lower); 1683 } 1684 else 1685 { 1686 err = _set_value (lower, NULL, lower->value, 1, 1, 0, attr, NULL); 1687 } 1688 if (err != STATUS_OK) 1689 { 1690 return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); 1691 } 1692 err = _hdf_read_string (lower, str, line, path, lineno, include_handle); 1693 if (err != STATUS_OK) 1694 { 1695 return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); 1696 } 1697 } 1698 else if (s[0] == '<' && s[1] == '<') /* multi-line assignment */ 1699 { 1700 char *m; 1701 int msize = 0; 1702 int mmax = 128; 1703 int l; 1704 1705 *s = '\0'; 1706 name = neos_strip(name); 1707 s+=2; 1708 value = neos_strip(s); 1709 l = strlen(value); 1710 if (l == 0) 1711 { 1712 err = nerr_raise(NERR_PARSE, 1713 "[%s:%d] No multi-assignment terminator given: %s", path, *lineno, 1714 line->buf); 1715 return err; 1716 } 1717 m = (char *) malloc (mmax * sizeof(char)); 1718 if (m == NULL) 1719 { 1720 return nerr_raise(NERR_NOMEM, 1721 "[%s:%d] Unable to allocate memory for multi-line assignment to %s", 1722 path, *lineno, name); 1723 } 1724 while (_copy_line (str, m+msize, mmax-msize) != 0) 1725 { 1726 (*lineno)++; 1727 if (!strncmp(value, m+msize, l) && isspace(m[msize+l])) 1728 { 1729 m[msize] = '\0'; 1730 break; 1731 } 1732 msize += strlen(m+msize); 1733 if (msize + l + 10 > mmax) 1734 { 1735 mmax += 128; 1736 m = (char *) realloc (m, mmax * sizeof(char)); 1737 if (m == NULL) 1738 { 1739 return nerr_raise(NERR_NOMEM, 1740 "[%s:%d] Unable to allocate memory for multi-line assignment to %s: size=%d", 1741 path, *lineno, name, mmax); 1742 } 1743 } 1744 } 1745 err = _set_value (hdf, name, m, 0, 1, 0, attr, NULL); 1746 if (err != STATUS_OK) 1747 { 1748 free (m); 1749 return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); 1750 } 1751 1752 } 1753 else 1754 { 1755 err = nerr_raise(NERR_PARSE, "[%s:%d] Unable to parse line %s", path, 1756 *lineno, line->buf); 1757 return err; 1758 } 1759 } 1760 } 1761 return STATUS_OK; 1762} 1763 1764NEOERR * hdf_read_string (HDF *hdf, const char *str) 1765{ 1766 NEOERR *err; 1767 int lineno = 0; 1768 STRING line; 1769 string_init(&line); 1770 err = _hdf_read_string(hdf, &str, &line, "<string>", &lineno, INCLUDE_ERROR); 1771 string_clear(&line); 1772 return nerr_pass(err); 1773} 1774 1775NEOERR * hdf_read_string_ignore (HDF *hdf, const char *str, int ignore) 1776{ 1777 NEOERR *err; 1778 int lineno = 0; 1779 STRING line; 1780 string_init(&line); 1781 err = _hdf_read_string(hdf, &str, &line, "<string>", &lineno, 1782 (ignore ? INCLUDE_IGNORE : INCLUDE_ERROR)); 1783 string_clear(&line); 1784 return nerr_pass(err); 1785} 1786 1787/* The search path is part of the HDF by convention */ 1788NEOERR* hdf_search_path (HDF *hdf, const char *path, char *full) 1789{ 1790 HDF *paths; 1791 struct stat s; 1792 1793 for (paths = hdf_get_child (hdf, "hdf.loadpaths"); 1794 paths; 1795 paths = hdf_obj_next (paths)) 1796 { 1797 snprintf (full, _POSIX_PATH_MAX, "%s/%s", hdf_obj_value(paths), path); 1798 errno = 0; 1799 if (stat (full, &s) == -1) 1800 { 1801 if (errno != ENOENT) 1802 return nerr_raise_errno (NERR_SYSTEM, "Stat of %s failed", full); 1803 } 1804 else 1805 { 1806 return STATUS_OK; 1807 } 1808 } 1809 1810 strncpy (full, path, _POSIX_PATH_MAX); 1811 if (stat (full, &s) == -1) 1812 { 1813 if (errno != ENOENT) 1814 return nerr_raise_errno (NERR_SYSTEM, "Stat of %s failed", full); 1815 } 1816 else return STATUS_OK; 1817 1818 return nerr_raise (NERR_NOT_FOUND, "Path %s not found", path); 1819} 1820 1821NEOERR* hdf_read_file (HDF *hdf, const char *path) 1822{ 1823 NEOERR *err; 1824 int lineno = 0; 1825 char fpath[_POSIX_PATH_MAX]; 1826 char *ibuf = NULL; 1827 const char *ptr = NULL; 1828 HDF *top = hdf->top; 1829 STRING line; 1830 1831 string_init(&line); 1832 1833 if (path == NULL) 1834 return nerr_raise(NERR_ASSERT, "Can't read NULL file"); 1835 1836 if (top->fileload) 1837 { 1838 err = top->fileload(top->fileload_ctx, hdf, path, &ibuf); 1839 } 1840 else 1841 { 1842 if (path[0] != '/') 1843 { 1844 err = hdf_search_path (hdf, path, fpath); 1845 if (err != STATUS_OK) return nerr_pass(err); 1846 path = fpath; 1847 } 1848 1849 err = ne_load_file (path, &ibuf); 1850 } 1851 if (err) return nerr_pass(err); 1852 1853 ptr = ibuf; 1854 err = _hdf_read_string(hdf, &ptr, &line, path, &lineno, INCLUDE_FILE); 1855 free(ibuf); 1856 string_clear(&line); 1857 return nerr_pass(err); 1858} 1859 1860void hdf_register_fileload(HDF *hdf, void *ctx, HDFFILELOAD fileload) 1861{ 1862 if (hdf == NULL) return; 1863 if (hdf->top != NULL) hdf = hdf->top; 1864 hdf->fileload_ctx = ctx; 1865 hdf->fileload = fileload; 1866} 1867 1868