Fix catch trace bug and inline cost bug
[hiphop-php.git] / hphp / neo / neo_hdf.c
blob491f1b3b63812d0598a83dba4568e525eff3ec36
1 /*
2 * Copyright 2001-2004 Brandon Long
3 * All Rights Reserved.
5 * ClearSilver Templating System
7 * This code is made available under the terms of the ClearSilver License.
8 * http://www.clearsilver.net/license.hdf
12 #include "cs_config.h"
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"
31 static NEOERR* hdf_read_file_internal (HDF *hdf, const char *path,
32 int include_handle);
35 static char *_read_file(FILE *f) {
36 int size = 1024;
37 char *ret = malloc(size + 1);
38 char *newret;
40 size_t nread;
41 char *buf = ret;
42 int len = size;
43 while ((nread = fread(buf, 1, len, f))) {
44 buf += nread;
45 len -= nread;
46 if (len == 0) {
47 len = size;
48 size <<= 1;
50 newret = realloc(ret, size + 1);
51 buf = buf - ret + newret;
52 ret = newret;
55 *buf = '\0';
56 return ret;
59 /* Ok, in order to use the hash, we have to support n-len strings
60 * instead of null terminated strings (since in set_value and walk_hdf
61 * we are merely using part of the HDF name for lookup, and that might
62 * be a const, and we don't want the overhead of allocating/copying
63 * that data out...)
65 * Since HASH doesn't maintain any data placed in it, merely pointers to
66 * it, we use the HDF node itself as the key, and have specific
67 * comp/hash functions which just use the name/name_len as the key.
70 static int hash_hdf_comp(const void *a, const void *b)
72 HDF *ha = (HDF *)a;
73 HDF *hb = (HDF *)b;
75 return (ha->name_len == hb->name_len) && !strncmp(ha->name, hb->name, ha->name_len);
78 static UINT32 hash_hdf_hash(const void *a)
80 HDF *ha = (HDF *)a;
81 return ne_crc((UINT8 *)(ha->name), ha->name_len);
84 static NEOERR *_alloc_hdf (HDF **hdf, const char *name, size_t nlen,
85 const char *value, int dupl, int wf, HDF *top)
87 *hdf = calloc (1, sizeof (HDF));
88 if (*hdf == NULL)
90 return nerr_raise (NERR_NOMEM, "Unable to allocate memory for hdf element");
93 (*hdf)->top = top;
95 if (name != NULL)
97 (*hdf)->name_len = nlen;
98 (*hdf)->name = (char *) malloc (nlen + 1);
99 if ((*hdf)->name == NULL)
101 free((*hdf));
102 (*hdf) = NULL;
103 return nerr_raise (NERR_NOMEM,
104 "Unable to allocate memory for hdf element: %s", name);
106 strncpy((*hdf)->name, name, nlen);
107 (*hdf)->name[nlen] = '\0';
109 if (value != NULL)
111 if (dupl)
113 (*hdf)->alloc_value = 1;
114 (*hdf)->value = strdup(value);
115 if ((*hdf)->value == NULL)
117 free((*hdf)->name);
118 free((*hdf));
119 (*hdf) = NULL;
120 return nerr_raise (NERR_NOMEM,
121 "Unable to allocate memory for hdf element %s", name);
124 else
126 (*hdf)->alloc_value = wf;
127 /* We're overriding the const of value here for the set_buf case
128 * where we overrode the char * to const char * earlier, since
129 * alloc_value actually keeps track of the const-ness for us */
130 (*hdf)->value = (char *)value;
133 return STATUS_OK;
136 static void _dealloc_hdf_attr(HDF_ATTR **attr)
138 HDF_ATTR *next;
140 while ((*attr) != NULL)
142 next = (*attr)->next;
143 if ((*attr)->key) free((*attr)->key);
144 if ((*attr)->value) free((*attr)->value);
145 free(*attr);
146 *attr = next;
148 *attr = NULL;
151 static void _dealloc_hdf (HDF **hdf)
153 HDF *myhdf = *hdf;
154 HDF *next = NULL;
156 if (myhdf == NULL) return;
157 if (myhdf->child != NULL)
158 _dealloc_hdf(&(myhdf->child));
160 /* This was easier recursively, but dangerous on long lists, so we
161 * walk it ourselves */
162 next = myhdf->next;
163 while (next != NULL)
165 myhdf->next = next->next;
166 next->next = NULL;
167 _dealloc_hdf(&next);
168 next = myhdf->next;
170 if (myhdf->name != NULL)
172 free (myhdf->name);
173 myhdf->name = NULL;
175 if (myhdf->value != NULL)
177 if (myhdf->alloc_value)
178 free (myhdf->value);
179 myhdf->value = NULL;
181 if (myhdf->attr != NULL)
183 _dealloc_hdf_attr(&(myhdf->attr));
185 if (myhdf->hash != NULL)
187 ne_hash_destroy(&myhdf->hash);
189 free(myhdf);
190 *hdf = NULL;
193 NEOERR* hdf_init (HDF **hdf)
195 NEOERR *err;
196 HDF *my_hdf;
198 *hdf = NULL;
200 err = nerr_init();
201 if (err != STATUS_OK)
202 return nerr_pass (err);
204 err = _alloc_hdf (&my_hdf, NULL, 0, NULL, 0, 0, NULL);
205 if (err != STATUS_OK)
206 return nerr_pass (err);
208 my_hdf->top = my_hdf;
210 *hdf = my_hdf;
212 return STATUS_OK;
215 void hdf_destroy (HDF **hdf)
217 if (*hdf == NULL) return;
218 if ((*hdf)->top == (*hdf))
220 _dealloc_hdf(hdf);
224 static int _walk_hdf (HDF *hdf, const char *name, HDF **node)
226 HDF *parent = NULL;
227 HDF *hp = hdf;
228 HDF hash_key;
229 int x = 0;
230 const char *s, *n;
231 int r;
233 *node = NULL;
235 if (hdf == NULL) return -1;
236 if (name == NULL || name[0] == '\0')
238 *node = hdf;
239 return 0;
242 if (hdf->link)
244 r = _walk_hdf (hdf->top, hdf->value, &hp);
245 if (r) return r;
246 if (hp)
248 parent = hp;
249 hp = hp->child;
252 else
254 parent = hdf;
255 hp = hdf->child;
257 if (hp == NULL)
259 return -1;
262 n = name;
263 s = strchr (n, '.');
264 x = (s == NULL) ? strlen(n) : s - n;
266 while (1)
268 if (parent && parent->hash)
270 hash_key.name = (char *)n;
271 hash_key.name_len = x;
272 hp = ne_hash_lookup(parent->hash, &hash_key);
274 else
276 while (hp != NULL)
278 if (hp->name && (x == hp->name_len) && !strncmp(hp->name, n, x))
280 break;
282 else
284 hp = hp->next;
288 if (hp == NULL)
290 return -1;
292 if (s == NULL) break;
294 if (hp->link)
296 r = _walk_hdf (hp->top, hp->value, &hp);
297 if (r) {
298 return r;
300 parent = hp;
301 hp = hp->child;
303 else
305 parent = hp;
306 hp = hp->child;
308 n = s + 1;
309 s = strchr (n, '.');
310 x = (s == NULL) ? strlen(n) : s - n;
312 if (hp->link)
314 return _walk_hdf (hp->top, hp->value, node);
317 *node = hp;
318 return 0;
321 int hdf_get_int_value (HDF *hdf, const char *name, int defval)
323 HDF *node;
324 int v;
325 char *n;
327 if ((_walk_hdf(hdf, name, &node) == 0) && (node->value != NULL))
329 v = strtol (node->value, &n, 10);
330 if (node->value == n) v = defval;
331 return v;
333 return defval;
336 /* This should return a const char *, but changing this would have big
337 * repurcussions for any C code using this function, so no change for now */
338 char* hdf_get_value (HDF *hdf, const char *name, const char *defval)
340 HDF *node;
342 if ((_walk_hdf(hdf, name, &node) == 0) && (node->value != NULL))
344 return node->value;
346 return (char *)defval;
349 char* hdf_get_valuevf (HDF *hdf, const char *namefmt, va_list ap)
351 HDF *node;
352 char *name;
354 name = vsprintf_alloc(namefmt, ap);
355 if (name == NULL) return NULL;
356 if ((_walk_hdf(hdf, name, &node) == 0) && (node->value != NULL))
358 free(name);
359 return node->value;
361 free(name);
362 return NULL;
365 char* hdf_get_valuef (HDF *hdf, const char *namefmt, ...)
367 char *val;
368 va_list ap;
370 va_start(ap, namefmt);
371 val = hdf_get_valuevf(hdf, namefmt, ap);
372 va_end(ap);
373 return val;
376 NEOERR* hdf_get_copy (HDF *hdf, const char *name, char **value,
377 const char *defval)
379 HDF *node;
381 if ((_walk_hdf(hdf, name, &node) == 0) && (node->value != NULL))
383 *value = strdup(node->value);
384 if (*value == NULL)
386 return nerr_raise (NERR_NOMEM, "Unable to allocate copy of %s", name);
389 else
391 if (defval == NULL)
392 *value = NULL;
393 else
395 *value = strdup(defval);
396 if (*value == NULL)
398 return nerr_raise (NERR_NOMEM, "Unable to allocate copy of %s", name);
402 return STATUS_OK;
405 HDF* hdf_get_obj (HDF *hdf, const char *name)
407 HDF *obj;
409 _walk_hdf(hdf, name, &obj);
410 return obj;
413 HDF* hdf_get_child (HDF *hdf, const char *name)
415 HDF *obj;
416 _walk_hdf(hdf, name, &obj);
417 if (obj != NULL) return obj->child;
418 return obj;
421 HDF_ATTR* hdf_get_attr (HDF *hdf, const char *name)
423 HDF *obj;
424 _walk_hdf(hdf, name, &obj);
425 if (obj != NULL) return obj->attr;
426 return NULL;
429 NEOERR* hdf_set_attr (HDF *hdf, const char *name, const char *key,
430 const char *value)
432 HDF *obj;
433 HDF_ATTR *attr, *last;
435 _walk_hdf(hdf, name, &obj);
436 if (obj == NULL)
437 return nerr_raise(NERR_ASSERT, "Unable to set attribute on none existant node");
439 if (obj->attr != NULL)
441 attr = obj->attr;
442 last = attr;
443 while (attr != NULL)
445 if (!strcmp(attr->key, key))
447 if (attr->value) free(attr->value);
448 /* a set of NULL deletes the attr */
449 if (value == NULL)
451 if (attr == obj->attr)
452 obj->attr = attr->next;
453 else
454 last->next = attr->next;
455 free(attr->key);
456 free(attr);
457 return STATUS_OK;
459 attr->value = strdup(value);
460 if (attr->value == NULL)
461 return nerr_raise(NERR_NOMEM, "Unable to set attr %s to %s", key, value);
462 return STATUS_OK;
464 last = attr;
465 attr = attr->next;
467 last->next = (HDF_ATTR *) calloc(1, sizeof(HDF_ATTR));
468 if (last->next == NULL)
469 return nerr_raise(NERR_NOMEM, "Unable to set attr %s to %s", key, value);
470 attr = last->next;
472 else
474 if (value == NULL) return STATUS_OK;
475 obj->attr = (HDF_ATTR *) calloc(1, sizeof(HDF_ATTR));
476 if (obj->attr == NULL)
477 return nerr_raise(NERR_NOMEM, "Unable to set attr %s to %s", key, value);
478 attr = obj->attr;
480 attr->key = strdup(key);
481 attr->value = strdup(value);
482 if (attr->key == NULL || attr->value == NULL)
483 return nerr_raise(NERR_NOMEM, "Unable to set attr %s to %s", key, value);
485 return STATUS_OK;
488 void hdf_set_visited (HDF *hdf, int visited) {
489 if (hdf) hdf->visited = visited;
492 int hdf_is_visited (HDF *hdf) {
493 return hdf ? hdf->visited : 0;
496 HDF* hdf_obj_child (HDF *hdf)
498 HDF *obj;
499 if (hdf == NULL) return NULL;
500 if (hdf->link)
502 if (_walk_hdf(hdf->top, hdf->value, &obj))
503 return NULL;
504 return obj->child;
506 return hdf->child;
509 HDF* hdf_obj_next (HDF *hdf)
511 if (hdf == NULL) return NULL;
512 return hdf->next;
515 HDF* hdf_obj_top (HDF *hdf)
517 if (hdf == NULL) return NULL;
518 return hdf->top;
521 HDF_ATTR* hdf_obj_attr (HDF *hdf)
523 if (hdf == NULL) return NULL;
524 return hdf->attr;
527 char* hdf_obj_name (HDF *hdf)
529 if (hdf == NULL) return NULL;
530 return hdf->name;
533 char* hdf_obj_value (HDF *hdf)
535 int count = 0;
537 if (hdf == NULL) return NULL;
538 while (hdf->link && count < 100)
540 if (_walk_hdf (hdf->top, hdf->value, &hdf))
541 return NULL;
542 count++;
544 return hdf->value;
547 void _merge_attr (HDF_ATTR *dest, HDF_ATTR *src)
549 HDF_ATTR *da, *ld;
550 HDF_ATTR *sa, *ls;
551 BOOL found;
553 sa = src;
554 ls = src;
555 while (sa != NULL)
557 da = dest;
558 ld = da;
559 found = 0;
560 while (da != NULL)
562 if (!strcmp(da->key, sa->key))
564 if (da->value) free(da->value);
565 da->value = sa->value;
566 sa->value = NULL;
567 found = 1;
568 break;
570 ld = da;
571 da = da->next;
573 if (!found)
575 ld->next = sa;
576 ls->next = sa->next;
577 if (src == sa) src = sa->next;
578 ld->next->next = NULL;
579 sa = ls->next;
581 else
583 ls = sa;
584 sa = sa->next;
587 _dealloc_hdf_attr(&src);
590 NEOERR* _hdf_hash_level(HDF *hdf)
592 NEOERR *err;
593 HDF *child;
595 err = ne_hash_init(&(hdf->hash), hash_hdf_hash, hash_hdf_comp);
596 if (err) return nerr_pass(err);
598 child = hdf->child;
599 while (child)
601 err = ne_hash_insert(hdf->hash, child, child);
602 if (err) return nerr_pass(err);
603 child = child->next;
605 return STATUS_OK;
608 static NEOERR* _set_value (HDF *hdf, const char *name, const char *value,
609 int dupl, int wf, int lnk, HDF_ATTR *attr,
610 HDF **set_node)
612 NEOERR *err;
613 HDF *hn, *hp, *hs;
614 HDF hash_key;
615 int x = 0;
616 const char *s = name;
617 const char *n = name;
618 int count = 0;
620 if (set_node != NULL) *set_node = NULL;
621 if (hdf == NULL)
623 return nerr_raise(NERR_ASSERT, "Unable to set %s on NULL hdf", name);
626 /* HACK: allow setting of this node by passing an empty name */
627 if (name == NULL || name[0] == '\0')
629 /* handle setting attr first */
630 if (hdf->attr == NULL)
632 hdf->attr = attr;
634 else
636 _merge_attr(hdf->attr, attr);
638 /* set link flag */
639 if (lnk) hdf->link = 1;
640 else hdf->link = 0;
641 /* if we're setting ourselves to ourselves... */
642 if (hdf->value == value)
644 if (set_node != NULL) *set_node = hdf;
645 return STATUS_OK;
647 if (hdf->alloc_value)
649 free(hdf->value);
650 hdf->value = NULL;
652 if (value == NULL)
654 hdf->alloc_value = 0;
655 hdf->value = NULL;
657 else if (dupl)
659 hdf->alloc_value = 1;
660 hdf->value = strdup(value);
661 if (hdf->value == NULL)
662 return nerr_raise (NERR_NOMEM, "Unable to duplicate value %s for %s",
663 value, name);
665 else
667 hdf->alloc_value = wf;
668 hdf->value = (char *)value;
670 if (set_node != NULL) *set_node = hdf;
671 return STATUS_OK;
674 n = name;
675 s = strchr (n, '.');
676 x = (s != NULL) ? s - n : strlen(n);
677 if (x == 0)
679 return nerr_raise(NERR_ASSERT, "Unable to set Empty component %s", name);
682 if (hdf->link)
684 char *new_name = (char *) malloc(strlen(hdf->value) + 1 + strlen(name) + 1);
685 if (new_name == NULL)
687 return nerr_raise(NERR_NOMEM, "Unable to allocate memory");
689 strcpy(new_name, hdf->value);
690 strcat(new_name, ".");
691 strcat(new_name, name);
692 err = _set_value (hdf->top, new_name, value, dupl, wf, lnk, attr, set_node);
693 free(new_name);
694 return nerr_pass(err);
696 else
698 hn = hdf;
701 while (1)
703 /* examine cache to see if we have a match */
704 count = 0;
705 hp = hn->last_hp;
706 hs = hn->last_hs;
708 if ((hs == NULL && hp == hn->child) || (hs && hs->next == hp))
710 if (hp && hp->name && (x == hp->name_len) && !strncmp (hp->name, n, x))
712 goto skip_search;
716 hp = hn->child;
717 hs = NULL;
719 /* Look for a matching node at this level */
720 if (hn->hash != NULL)
722 hash_key.name = (char *)n;
723 hash_key.name_len = x;
724 hp = ne_hash_lookup(hn->hash, &hash_key);
725 hs = hn->last_child;
727 else
729 while (hp != NULL)
731 if (hp->name && (x == hp->name_len) && !strncmp(hp->name, n, x))
733 break;
735 hs = hp;
736 hp = hp->next;
737 count++;
741 /* save in cache any value we found */
742 if (hp) {
743 hn->last_hp = hp;
744 hn->last_hs = hs;
747 skip_search:
749 if (hp == NULL)
751 /* If there was no matching node at this level, we need to
752 * allocate an intersitial node (or the actual node if we're
753 * at the last part of the HDF name) */
754 if (s != NULL)
756 /* intersitial */
757 err = _alloc_hdf (&hp, n, x, NULL, 0, 0, hdf->top);
759 else
761 err = _alloc_hdf (&hp, n, x, value, dupl, wf, hdf->top);
762 if (lnk) hp->link = 1;
763 else hp->link = 0;
764 hp->attr = attr;
766 if (err != STATUS_OK)
767 return nerr_pass (err);
768 if (hn->child == NULL)
769 hn->child = hp;
770 else
771 hs->next = hp;
772 hn->last_child = hp;
774 /* This is the point at which we convert to a hash table
775 * at this level, if we're over the count */
776 if (count > FORCE_HASH_AT && hn->hash == NULL)
778 err = _hdf_hash_level(hn);
779 if (err) return nerr_pass(err);
781 else if (hn->hash != NULL)
783 err = ne_hash_insert(hn->hash, hp, hp);
784 if (err) return nerr_pass(err);
787 else if (s == NULL)
789 /* If there is a matching node and we're at the end of the HDF
790 * name, then we update the value of the node */
791 /* handle setting attr first */
792 if (hp->attr == NULL)
794 hp->attr = attr;
796 else
798 _merge_attr(hp->attr, attr);
800 if (hp->value != value)
802 if (hp->alloc_value)
804 free(hp->value);
805 hp->value = NULL;
807 if (value == NULL)
809 hp->alloc_value = 0;
810 hp->value = NULL;
812 else if (dupl)
814 hp->alloc_value = 1;
815 hp->value = strdup(value);
816 if (hp->value == NULL)
817 return nerr_raise (NERR_NOMEM, "Unable to duplicate value %s for %s",
818 value, name);
820 else
822 hp->alloc_value = wf;
823 hp->value = (char *)value;
826 if (lnk) hp->link = 1;
827 else hp->link = 0;
829 else if (hp->link)
831 char *new_name = (char *) malloc(strlen(hp->value) + strlen(s) + 1);
832 if (new_name == NULL)
834 return nerr_raise(NERR_NOMEM, "Unable to allocate memory");
836 strcpy(new_name, hp->value);
837 strcat(new_name, s);
838 err = _set_value (hdf->top, new_name, value, dupl, wf, lnk, attr, set_node);
839 free(new_name);
840 return nerr_pass(err);
842 /* At this point, we're done if there is not more HDF name space to
843 * traverse */
844 if (s == NULL)
845 break;
846 /* Otherwise, we need to find the next part of the namespace */
847 n = s + 1;
848 s = strchr (n, '.');
849 x = (s != NULL) ? s - n : strlen(n);
850 if (x == 0)
852 return nerr_raise(NERR_ASSERT, "Unable to set Empty component %s", name);
854 hn = hp;
856 if (set_node != NULL) *set_node = hp;
857 return STATUS_OK;
860 NEOERR* hdf_set_value (HDF *hdf, const char *name, const char *value)
862 return nerr_pass(_set_value (hdf, name, value, 1, 1, 0, NULL, NULL));
865 NEOERR* hdf_set_value_attr (HDF *hdf, const char *name, const char *value,
866 HDF_ATTR *attr)
868 return nerr_pass(_set_value (hdf, name, value, 1, 1, 0, attr, NULL));
871 NEOERR* hdf_set_symlink (HDF *hdf, const char *src, const char *dest)
873 return nerr_pass(_set_value (hdf, src, dest, 1, 1, 1, NULL, NULL));
876 NEOERR* hdf_set_int_value (HDF *hdf, const char *name, int value)
878 char buf[256];
880 snprintf (buf, sizeof(buf), "%d", value);
881 return nerr_pass(_set_value (hdf, name, buf, 1, 1, 0, NULL, NULL));
884 NEOERR* hdf_set_buf (HDF *hdf, const char *name, char *value)
886 return nerr_pass(_set_value (hdf, name, value, 0, 1, 0, NULL, NULL));
889 NEOERR* hdf_set_copy (HDF *hdf, const char *dest, const char *src)
891 HDF *node;
892 if ((_walk_hdf(hdf, src, &node) == 0) && (node->value != NULL))
894 return nerr_pass(_set_value (hdf, dest, node->value, 0, 0, 0, NULL, NULL));
896 return nerr_raise (NERR_NOT_FOUND, "Unable to find %s", src);
899 NEOERR* hdf_set_valuevf (HDF *hdf, const char *fmt, va_list ap)
901 NEOERR *err;
902 char *k;
903 char *v;
905 k = vsprintf_alloc(fmt, ap);
906 if (k == NULL)
908 return nerr_raise(NERR_NOMEM, "Unable to allocate memory for format string");
910 v = strchr(k, '=');
911 if (v == NULL)
913 err = nerr_raise(NERR_ASSERT, "No equals found: %s", k);
914 free(k);
915 return err;
917 *v++ = '\0';
918 err = hdf_set_value(hdf, k, v);
919 free(k);
920 return nerr_pass(err);
923 NEOERR* hdf_set_valuef (HDF *hdf, const char *fmt, ...)
925 NEOERR *err;
926 va_list ap;
928 va_start(ap, fmt);
929 err = hdf_set_valuevf(hdf, fmt, ap);
930 va_end(ap);
931 return nerr_pass(err);
934 NEOERR* hdf_get_node (HDF *hdf, const char *name, HDF **ret)
936 _walk_hdf(hdf, name, ret);
937 if (*ret == NULL)
939 return nerr_pass(_set_value (hdf, name, NULL, 0, 1, 0, NULL, ret));
941 return STATUS_OK;
944 /* Ok, this version avoids the bubble sort by walking the level once to
945 * load them all into a ULIST, qsort'ing the list, and then dumping them
946 * back out... */
947 NEOERR *hdf_sort_obj (HDF *h, int (*compareFunc)(const void *, const void *))
949 NEOERR *err = STATUS_OK;
950 ULIST *level = NULL;
951 HDF *p, *c;
952 int x;
954 if (h == NULL) return STATUS_OK;
955 c = h->child;
956 if (c == NULL) return STATUS_OK;
958 do {
959 err = uListInit(&level, 40, 0);
960 if (err) return nerr_pass(err);
961 for (p = c; p; p = p->next) {
962 err = uListAppend(level, p);
963 if (err) break;
965 err = uListSort(level, compareFunc);
966 if (err) break;
967 uListGet(level, 0, (void *)&c);
968 h->child = c;
969 for (x = 1; x < uListLength(level); x++)
971 uListGet(level, x, (void *)&p);
972 c->next = p;
973 p->next = NULL;
974 c = p;
976 h->last_child = c;
977 } while (0);
978 uListDestroy(&level, 0);
979 return nerr_pass(err);
982 NEOERR* hdf_remove_tree (HDF *hdf, const char *name)
984 HDF *hp = hdf;
985 HDF *lp = NULL, *ln = NULL; /* last parent, last node */
986 int x = 0;
987 const char *s = name;
988 const char *n = name;
990 if (hdf == NULL) return STATUS_OK;
992 hp = hdf->child;
993 if (hp == NULL)
995 return STATUS_OK;
998 lp = hdf;
999 ln = NULL;
1001 n = name;
1002 s = strchr (n, '.');
1003 x = (s == NULL) ? strlen(n) : s - n;
1005 while (1)
1007 while (hp != NULL)
1009 if (hp->name && (x == hp->name_len) && !strncmp(hp->name, n, x))
1011 break;
1013 else
1015 ln = hp;
1016 hp = hp->next;
1019 if (hp == NULL)
1021 return STATUS_OK;
1023 if (s == NULL) break;
1025 lp = hp;
1026 ln = NULL;
1027 hp = hp->child;
1028 n = s + 1;
1029 s = strchr (n, '.');
1030 x = (s == NULL) ? strlen(n) : s - n;
1033 if (lp->hash != NULL)
1035 ne_hash_remove(lp->hash, hp);
1037 if (ln)
1039 ln->next = hp->next;
1040 /* check to see if we are the last parent's last_child, if so
1041 * repoint so hash table inserts will go to the right place */
1042 if (hp == lp->last_child)
1043 lp->last_child = ln;
1044 hp->next = NULL;
1046 else
1048 lp->child = hp->next;
1049 hp->next = NULL;
1051 _dealloc_hdf (&hp);
1053 return STATUS_OK;
1056 static NEOERR * _copy_attr (HDF_ATTR **dest, HDF_ATTR *src)
1058 HDF_ATTR *copy, *last = NULL;
1060 *dest = NULL;
1061 while (src != NULL)
1063 copy = (HDF_ATTR *)malloc(sizeof(HDF_ATTR));
1064 if (copy == NULL)
1066 _dealloc_hdf_attr(dest);
1067 return nerr_raise(NERR_NOMEM, "Unable to allocate copy of HDF_ATTR");
1069 copy->key = strdup(src->key);
1070 copy->value = strdup(src->value);
1071 copy->next = NULL;
1072 if ((copy->key == NULL) || (copy->value == NULL))
1074 _dealloc_hdf_attr(dest);
1075 return nerr_raise(NERR_NOMEM, "Unable to allocate copy of HDF_ATTR");
1077 if (last) {
1078 last->next = copy;
1080 else
1082 *dest = copy;
1084 last = copy;
1085 src = src->next;
1087 return STATUS_OK;
1090 static NEOERR * _copy_nodes (HDF *dest, HDF *src)
1092 NEOERR *err = STATUS_OK;
1093 HDF *dt, *st;
1094 HDF_ATTR *attr_copy;
1096 st = src->child;
1097 while (st != NULL)
1099 err = _copy_attr(&attr_copy, st->attr);
1100 if (err) return nerr_pass(err);
1101 err = _set_value(dest, st->name, st->value, 1, 1, st->link, attr_copy, &dt);
1102 if (err) {
1103 _dealloc_hdf_attr(&attr_copy);
1104 return nerr_pass(err);
1106 if (src->child)
1108 err = _copy_nodes (dt, st);
1109 if (err) return nerr_pass(err);
1111 st = st->next;
1113 return STATUS_OK;
1116 NEOERR* hdf_copy (HDF *dest, const char *name, HDF *src)
1118 NEOERR *err;
1119 HDF *node;
1120 HDF_ATTR *attr_copy;
1122 if (_walk_hdf(dest, name, &node) == -1)
1124 err = _copy_attr(&attr_copy, src->attr);
1125 if (err) return nerr_pass(err);
1126 err = _set_value (dest, name, src->value, 1, 1, src->link, attr_copy,
1127 &node);
1128 if (err) {
1129 _dealloc_hdf_attr(&attr_copy);
1130 return nerr_pass(err);
1133 return nerr_pass (_copy_nodes (node, src));
1136 /* BUG: currently, this only prints something if there is a value...
1137 * but we now allow attributes on nodes with no value... */
1139 static void gen_ml_break(char *ml, size_t len)
1141 int nlen;
1142 int x = 0;
1144 ml[x++] = '\n';
1145 nlen = 2 + neo_rand(len-5);
1146 if (nlen == 0)
1148 nlen = len / 2;
1150 while (nlen)
1152 ml[x++] = ('A' + neo_rand(26));
1153 nlen--;
1155 ml[x++] = '\n';
1156 ml[x] = '\0';
1159 typedef NEOERR *(*DUMPF_CB)(void *rock, const char *fmt, ...);
1161 static NEOERR *_fp_dump_cb (void *rock, const char *fmt, ...)
1163 FILE *fp = (FILE *)rock;
1164 va_list ap;
1166 va_start (ap, fmt);
1167 vfprintf(fp, fmt, ap);
1168 va_end(ap);
1169 return STATUS_OK;
1172 static NEOERR *_string_dump_cb (void *rock, const char *fmt, ...)
1174 NEOERR *err;
1175 NEOSTRING *str = (NEOSTRING *)rock;
1176 va_list ap;
1178 va_start (ap, fmt);
1179 err = string_appendvf(str, fmt, ap);
1180 va_end(ap);
1181 return nerr_pass(err);
1184 #define DUMP_TYPE_DOTTED 0
1185 #define DUMP_TYPE_COMPACT 1
1186 #define DUMP_TYPE_PRETTY 2
1188 static NEOERR* hdf_dump_cb(HDF *hdf, const char *prefix, int dtype, int lvl,
1189 void *rock, DUMPF_CB dump_cbf)
1191 NEOERR *err;
1192 char *p, op;
1193 char ml[10] = "\nEOM\n";
1194 int ml_len = strlen(ml);
1195 char whsp[256] = "";
1197 if (dtype == DUMP_TYPE_PRETTY)
1199 memset(whsp, ' ', 256);
1200 if (lvl > 127)
1201 lvl = 127;
1202 whsp[lvl*2] = '\0';
1205 if (hdf != NULL) hdf = hdf->child;
1207 while (hdf != NULL)
1209 op = '=';
1210 if (hdf->value)
1212 if (hdf->link) op = ':';
1213 if (prefix && (dtype == DUMP_TYPE_DOTTED))
1215 err = dump_cbf(rock, "%s.%s", prefix, hdf->name);
1217 else
1219 err = dump_cbf(rock, "%s%s", whsp, hdf->name);
1221 if (err) return nerr_pass (err);
1222 if (hdf->attr)
1224 HDF_ATTR *attr = hdf->attr;
1225 char *v = NULL;
1227 err = dump_cbf(rock, " [");
1228 if (err) return nerr_pass(err);
1229 while (attr != NULL)
1231 if (attr->value == NULL || !strcmp(attr->value, "1"))
1232 err = dump_cbf(rock, "%s", attr->key);
1233 else
1235 v = repr_string_alloc(attr->value);
1237 if (v == NULL)
1238 return nerr_raise(NERR_NOMEM, "Unable to repr attr %s value %s", attr->key, attr->value);
1239 err = dump_cbf(rock, "%s=%s", attr->key, v);
1240 free(v);
1242 if (err) return nerr_pass(err);
1243 if (attr->next)
1245 err = dump_cbf(rock, ", ");
1246 if (err) return nerr_pass(err);
1248 attr = attr->next;
1250 err = dump_cbf(rock, "] ");
1251 if (err) return nerr_pass(err);
1253 if (strchr (hdf->value, '\n'))
1255 int vlen = strlen(hdf->value);
1257 while (strstr(hdf->value, ml) || ((vlen > ml_len) && !strncmp(hdf->value + vlen - ml_len + 1, ml, strlen(ml) - 1)))
1259 gen_ml_break(ml, sizeof(ml));
1260 ml_len = strlen(ml);
1262 if (hdf->value[strlen(hdf->value)-1] != '\n')
1263 err = dump_cbf(rock, " << %s%s%s", ml+1, hdf->value, ml);
1264 else
1265 err = dump_cbf(rock, " << %s%s%s", ml+1, hdf->value, ml+1);
1267 else
1269 err = dump_cbf(rock, " %c %s\n", op, hdf->value);
1271 if (err) return nerr_pass (err);
1273 if (hdf->child)
1275 if (prefix && (dtype == DUMP_TYPE_DOTTED))
1277 p = (char *) malloc (strlen(hdf->name) + strlen(prefix) + 2);
1278 sprintf (p, "%s.%s", prefix, hdf->name);
1279 err = hdf_dump_cb (hdf, p, dtype, lvl+1, rock, dump_cbf);
1280 free(p);
1282 else
1284 if (hdf->name && (dtype != DUMP_TYPE_DOTTED))
1286 err = dump_cbf(rock, "%s%s {\n", whsp, hdf->name);
1287 if (err) return nerr_pass (err);
1288 err = hdf_dump_cb (hdf, hdf->name, dtype, lvl+1, rock, dump_cbf);
1289 if (err) return nerr_pass (err);
1290 err = dump_cbf(rock, "%s}\n", whsp);
1292 else
1294 err = hdf_dump_cb (hdf, hdf->name, dtype, lvl+1, rock, dump_cbf);
1297 if (err) return nerr_pass (err);
1299 hdf = hdf->next;
1301 return STATUS_OK;
1304 NEOERR* hdf_dump_str (HDF *hdf, const char *prefix, int dtype, NEOSTRING *str)
1306 return nerr_pass(hdf_dump_cb(hdf, prefix, dtype, 0, str, _string_dump_cb));
1309 NEOERR* hdf_dump(HDF *hdf, const char *prefix)
1311 return nerr_pass(hdf_dump_cb(hdf, prefix, DUMP_TYPE_DOTTED, 0, stdout, _fp_dump_cb));
1314 NEOERR* hdf_dump_format (HDF *hdf, int lvl, FILE *fp)
1316 return nerr_pass(hdf_dump_cb(hdf, "", DUMP_TYPE_PRETTY, 0, fp, _fp_dump_cb));
1319 NEOERR *hdf_write_file (HDF *hdf, const char *path)
1321 NEOERR *err;
1322 FILE *fp;
1324 fp = fopen(path, "w");
1325 if (fp == NULL)
1326 return nerr_raise_errno (NERR_IO, "Unable to open %s for writing", path);
1328 err = hdf_dump_format (hdf, 0, fp);
1330 fclose (fp);
1331 if (err)
1333 unlink(path);
1335 return nerr_pass(err);
1338 NEOERR *hdf_write_file_atomic (HDF *hdf, const char *path)
1340 NEOERR *err;
1341 FILE *fp;
1342 char tpath[PATH_BUF_SIZE];
1343 static int count = 0;
1345 snprintf(tpath, sizeof(tpath), "%s.%5.5f.%d", path, ne_timef(), count++);
1347 fp = fopen(tpath, "w");
1348 if (fp == NULL)
1349 return nerr_raise_errno (NERR_IO, "Unable to open %s for writing", tpath);
1351 err = hdf_dump_format (hdf, 0, fp);
1353 fclose (fp);
1355 if (err)
1357 unlink(tpath);
1358 return nerr_pass(err);
1360 if (rename(tpath, path) == -1)
1362 unlink (tpath);
1363 return nerr_raise_errno (NERR_IO, "Unable to rename file %s to %s",
1364 tpath, path);
1367 return STATUS_OK;
1370 NEOERR *hdf_write_string (HDF *hdf, char **s)
1372 NEOSTRING str;
1373 NEOERR *err;
1375 *s = NULL;
1377 string_init (&str);
1379 err = hdf_dump_str (hdf, NULL, 2, &str);
1380 if (err)
1382 string_clear (&str);
1383 return nerr_pass(err);
1385 if (str.buf == NULL)
1387 *s = strdup("");
1388 if (*s == NULL) return nerr_raise(NERR_NOMEM, "Unable to allocate empty string");
1390 else
1392 *s = str.buf;
1395 return STATUS_OK;
1399 #define SKIPWS(s) while (*s && isspace(*s)) s++;
1401 static int _copy_line (const char **s, char *buf, size_t buf_len)
1403 int x = 0;
1404 const char *st = *s;
1406 while (*st && x < buf_len-1)
1408 buf[x++] = *st;
1409 if (*st++ == '\n') break;
1411 buf[x] = '\0';
1412 *s = st;
1414 return x;
1417 /* Copy the characters in the file (up to the next newline) into line
1418 * and advance s to the next line */
1419 static NEOERR *_copy_line_advance(const char **s, NEOSTRING *line)
1421 NEOERR *err;
1422 int x = 0;
1423 const char *st = *s;
1424 const char *nl;
1426 nl = strchr(st, '\n');
1427 if (nl == NULL)
1429 x = strlen(st);
1430 err = string_appendn(line, st, x);
1431 if (err) return nerr_pass(err);
1432 *s = st + x;
1434 else
1436 x = nl - st;
1437 err = string_appendn(line, st, x);
1438 if (err) return nerr_pass(err);
1439 *s = nl + 1;
1442 return STATUS_OK;
1445 char *_strndup(const char *s, int len) {
1446 int x;
1447 char *dupl;
1448 if (s == NULL) return NULL;
1449 dupl = (char *) malloc(len+1);
1450 if (dupl == NULL) return NULL;
1451 for (x = 0; x < len && s[x]; x++)
1453 dupl[x] = s[x];
1455 dupl[x] = '\0';
1456 dupl[len] = '\0';
1457 return dupl;
1460 /* attributes are of the form [key1, key2, key3=value, key4="repr"] */
1461 static NEOERR* parse_attr(char **str, HDF_ATTR **attr)
1463 NEOERR *err = STATUS_OK;
1464 char *s = *str;
1465 char *k, *v;
1466 int k_l, v_l;
1467 NEOSTRING buf;
1468 char c;
1469 HDF_ATTR *ha, *hal = NULL;
1471 *attr = NULL;
1473 string_init(&buf);
1474 while (*s && *s != ']')
1476 k = s;
1477 k_l = 0;
1478 v = NULL;
1479 v_l = 0;
1480 while (*s && isalnum(*s)) s++;
1481 k_l = s-k;
1482 if (*s == '\0' || k_l == 0)
1484 _dealloc_hdf_attr(attr);
1485 return nerr_raise(NERR_PARSE, "Misformed attribute specification: %s", *str);
1487 SKIPWS(s);
1488 if (*s == '=')
1490 s++;
1491 SKIPWS(s);
1492 if (*s == '"')
1494 s++;
1495 while (*s && *s != '"')
1497 if (*s == '\\')
1499 if (isdigit(*(s+1)))
1501 s++;
1502 c = *s - '0';
1503 if (isdigit(*(s+1)))
1505 s++;
1506 c = (c * 8) + (*s - '0');
1507 if (isdigit(*(s+1)))
1509 s++;
1510 c = (c * 8) + (*s - '0');
1514 else
1516 s++;
1517 if (*s == 'n') c = '\n';
1518 else if (*s == 't') c = '\t';
1519 else if (*s == 'r') c = '\r';
1520 else c = *s;
1522 err = string_append_char(&buf, c);
1524 else
1526 err = string_append_char(&buf, *s);
1528 if (err)
1530 string_clear(&buf);
1531 _dealloc_hdf_attr(attr);
1532 return nerr_pass(err);
1534 s++;
1536 if (*s == '\0')
1538 _dealloc_hdf_attr(attr);
1539 string_clear(&buf);
1540 return nerr_raise(NERR_PARSE, "Misformed attribute specification: %s", *str);
1542 s++;
1543 v = buf.buf;
1544 v_l = buf.len;
1546 else
1548 v = s;
1549 while (*s && *s != ' ' && *s != ',' && *s != ']') s++;
1550 if (*s == '\0')
1552 _dealloc_hdf_attr(attr);
1553 return nerr_raise(NERR_PARSE, "Misformed attribute specification: %s", *str);
1555 v_l = s-v;
1558 else
1560 v = "1";
1562 ha = (HDF_ATTR*) calloc (1, sizeof(HDF_ATTR));
1563 if (ha == NULL)
1565 _dealloc_hdf_attr(attr);
1566 string_clear(&buf);
1567 return nerr_raise(NERR_NOMEM, "Unable to load attributes: %s", s);
1569 if (*attr == NULL) *attr = ha;
1570 ha->key = _strndup(k, k_l);
1571 if (v)
1572 ha->value = _strndup(v, v_l);
1573 else
1574 ha->value = strdup("");
1575 if (ha->key == NULL || ha->value == NULL)
1577 _dealloc_hdf_attr(attr);
1578 string_clear(&buf);
1579 return nerr_raise(NERR_NOMEM, "Unable to load attributes: %s", s);
1581 if (hal != NULL) hal->next = ha;
1582 hal = ha;
1583 string_clear(&buf);
1584 SKIPWS(s);
1585 if (*s == ',')
1587 s++;
1588 SKIPWS(s);
1591 if (*s == '\0')
1593 _dealloc_hdf_attr(attr);
1594 return nerr_raise(NERR_PARSE, "Misformed attribute specification: %s", *str);
1596 *str = s+1;
1597 return STATUS_OK;
1600 #define INCLUDE_ERROR -1
1601 #define INCLUDE_IGNORE -2
1602 #define INCLUDE_FILE 0
1603 #define INCLUDE_MAX_DEPTH 50
1605 static NEOERR* _hdf_read_string (HDF *hdf, const char **str, NEOSTRING *line,
1606 const char *path, int *lineno,
1607 int include_handle, int expect_end_brace) {
1608 NEOERR *err;
1609 HDF *lower;
1610 char *s;
1611 char *name, *value;
1612 HDF_ATTR *attr = NULL;
1614 while (**str != '\0')
1616 /* Reset string length, but don't free the reserved buffer */
1617 line->len = 0;
1618 err = _copy_line_advance(str, line);
1619 if (err) return nerr_pass(err);
1620 attr = NULL;
1621 (*lineno)++;
1622 s = line->buf;
1623 SKIPWS(s);
1624 if ((!strncmp(s, "#include ", 9) || !strncmp(s, "-include ", 9)) && include_handle != INCLUDE_IGNORE)
1626 int required = !strncmp(s, "#include ", 9);
1627 if (include_handle == INCLUDE_ERROR)
1629 return nerr_raise (NERR_PARSE,
1630 "[%d]: #include not supported in string parse",
1631 *lineno);
1633 else if (include_handle < INCLUDE_MAX_DEPTH)
1635 int l;
1636 s += 9;
1637 name = neos_strip(s);
1638 l = strlen(name);
1639 if (name[0] == '"' && name[l-1] == '"')
1641 name[l-1] = '\0';
1642 name++;
1644 char fullpath[PATH_MAX];
1645 if (name[0] != '/') {
1646 memset(fullpath, 0, PATH_MAX);
1648 char *p = strrchr(path, '/');
1649 if (p == NULL) {
1650 char pwd[PATH_MAX];
1651 memset(pwd, 0, PATH_MAX);
1652 getcwd(pwd, PATH_MAX);
1653 snprintf(fullpath, PATH_MAX, "%s/%s", pwd, name);
1654 } else {
1655 int dir_len = p - path + 1;
1656 snprintf(fullpath, PATH_MAX, "%s", path);
1657 snprintf(fullpath + dir_len, PATH_MAX - dir_len, "%s", name);
1659 name = fullpath;
1661 err = hdf_read_file_internal(hdf, name, include_handle + 1);
1662 if (err != STATUS_OK && required)
1664 return nerr_pass_ctx(err, "In file %s:%d", path, *lineno);
1667 else {
1668 return nerr_raise (NERR_MAX_RECURSION,
1669 "[%d]: Too many recursion levels.",
1670 *lineno
1674 else if (s[0] == '#')
1676 /* comment: pass */
1678 else if (s[0] == '}') /* up */
1680 s = neos_strip(s);
1681 if (strcmp(s, "}"))
1683 err = nerr_raise(NERR_PARSE,
1684 "[%s:%d] Trailing garbage on line following }: %s", path, *lineno,
1685 line->buf);
1686 return err;
1688 return STATUS_OK;
1690 else if (s[0])
1692 /* Valid hdf name is [0-9a-zA-Z_.*\]+ */
1693 int splice = *s == '@';
1694 if (splice) s++;
1695 name = s;
1696 while (*s && (isalnum(*s) || *s == '_' || *s == '.' || *s == '*' || *s == '\\')) s++;
1697 SKIPWS(s);
1699 char num[256];
1700 static int counter = 0;
1701 char *p;
1702 int i = 0;
1703 for (p = name; p < s && i < 200; p++) {
1704 if (*p != '*') {
1705 num[i++] = *p;
1706 } else {
1707 i += snprintf(num + i, 256 - i, "%d", counter++);
1708 name = num;
1711 num[i] = '\0';
1713 if (s[0] == '[') /* attributes */
1715 *s = '\0';
1716 name = neos_strip(name);
1717 s++;
1718 err = parse_attr(&s, &attr);
1719 if (err)
1721 return nerr_pass_ctx(err, "In file %s:%d", path, *lineno);
1723 SKIPWS(s);
1725 if (splice) {
1726 name = neos_strip(name);
1727 HDF *h = hdf_get_obj(hdf->top, name);
1728 if (h) {
1729 HDF *c = hdf_obj_child(h);
1730 while (c) {
1731 err = hdf_copy (hdf, hdf_obj_name(c), c);
1732 if (err != STATUS_OK) break;
1733 c = hdf_obj_next(c);
1736 if (err != STATUS_OK)
1738 return nerr_pass_ctx(err, "In file %s:%d", path, *lineno);
1740 } else if (s[0] == '=') /* assignment */
1742 *s = '\0';
1743 name = neos_strip(name);
1744 s++;
1745 value = neos_strip(s);
1746 err = _set_value (hdf, name, value, 1, 1, 0, attr, NULL);
1747 if (err != STATUS_OK)
1749 return nerr_pass_ctx(err, "In file %s:%d", path, *lineno);
1752 else if (s[0] == ':' && s[1] == '=') /* copy */
1754 *s = '\0';
1755 name = neos_strip(name);
1756 s+=2;
1757 value = neos_strip(s);
1758 HDF *h = hdf_get_obj(hdf->top, value);
1759 if (!h)
1761 err = nerr_raise(NERR_PARSE,
1762 "[%s:%d] Failed to copy a node that is not loaded "
1763 "yet: %s", path, *lineno, value);
1764 return err;
1766 err = hdf_copy(hdf, name, h);
1767 if (err != STATUS_OK)
1769 return nerr_pass_ctx(err, "In file %s:%d", path, *lineno);
1772 else if (s[0] == '!' && s[1] == '=') /* exec */
1774 *s = '\0';
1775 name = neos_strip(name);
1776 s+=2;
1777 value = neos_strip(s);
1779 FILE *f = popen(value, "r");
1780 if (f == NULL)
1782 err = nerr_raise(NERR_PARSE,
1783 "[%s:%d] Failed to exec specified command: %s",
1784 path, *lineno, line->buf);
1785 return err;
1787 char *content = _read_file(f);
1788 fclose(f);
1789 int len = strlen(content);
1790 if (len > 0 && content[len - 1] == '\n') {
1791 content[len - 1] = '\0'; // remove \n artifact
1793 err = _set_value (hdf, name, content, 1, 1, 0, attr, NULL);
1794 free(content);
1796 if (err != STATUS_OK)
1798 return nerr_pass_ctx(err, "In file %s:%d", path, *lineno);
1801 else if (s[0] == ':') /* link */
1803 *s = '\0';
1804 name = neos_strip(name);
1805 s++;
1806 value = neos_strip(s);
1807 err = _set_value (hdf, name, value, 1, 1, 1, attr, NULL);
1808 if (err != STATUS_OK)
1810 return nerr_pass_ctx(err, "In file %s:%d", path, *lineno);
1813 else if (s[0] == '{') /* deeper */
1815 *s = '\0';
1816 name = neos_strip(name);
1817 lower = hdf_get_obj (hdf, name);
1818 if (lower == NULL)
1820 err = _set_value (hdf, name, NULL, 1, 1, 0, attr, &lower);
1822 else
1824 err = _set_value (lower, NULL, lower->value, 1, 1, 0, attr, NULL);
1826 if (err != STATUS_OK)
1828 return nerr_pass_ctx(err, "In file %s:%d", path, *lineno);
1830 err = _hdf_read_string (lower, str, line, path, lineno, include_handle,
1832 if (err != STATUS_OK)
1834 return nerr_pass_ctx(err, "In file %s:%d", path, *lineno);
1837 else if (s[0] == '<' && s[1] == '<') /* multi-line assignment */
1839 char *m;
1840 int msize = 0;
1841 int mmax = 128;
1842 int l;
1844 *s = '\0';
1845 name = neos_strip(name);
1846 s+=2;
1847 value = neos_strip(s);
1848 l = strlen(value);
1849 if (l == 0)
1851 err = nerr_raise(NERR_PARSE,
1852 "[%s:%d] No multi-assignment terminator given: %s", path, *lineno,
1853 line->buf);
1854 return err;
1856 m = (char *) malloc (mmax * sizeof(char));
1857 if (m == NULL)
1859 return nerr_raise(NERR_NOMEM,
1860 "[%s:%d] Unable to allocate memory for multi-line assignment to %s",
1861 path, *lineno, name);
1863 while (_copy_line (str, m+msize, mmax-msize) != 0)
1865 (*lineno)++;
1866 if (!strncmp(value, m+msize, l) && isspace(m[msize+l]))
1868 m[msize] = '\0';
1869 break;
1871 msize += strlen(m+msize);
1872 if (msize + l + 10 > mmax)
1874 void *new_ptr;
1875 mmax += 128;
1876 new_ptr = realloc (m, mmax * sizeof(char));
1877 if (new_ptr == NULL)
1879 free(m);
1880 return nerr_raise(NERR_NOMEM,
1881 "[%s:%d] Unable to allocate memory for multi-line assignment to %s: size=%d",
1882 path, *lineno, name, mmax);
1884 m = (char *) new_ptr;
1887 err = _set_value (hdf, name, m, 0, 1, 0, attr, NULL);
1888 if (err != STATUS_OK)
1890 free (m);
1891 return nerr_pass_ctx(err, "In file %s:%d", path, *lineno);
1895 else
1897 err = nerr_raise(NERR_PARSE, "[%s:%d] Unable to parse line %s", path,
1898 *lineno, line->buf);
1899 return err;
1903 if (expect_end_brace) {
1904 err = nerr_raise(NERR_PARSE, "[%s:%d] Missing matching }", path, *lineno);
1905 return err;
1907 return STATUS_OK;
1910 NEOERR * hdf_read_string (HDF *hdf, const char *str)
1912 NEOERR *err;
1913 int lineno = 0;
1914 NEOSTRING line;
1915 string_init(&line);
1916 err = _hdf_read_string(hdf, &str, &line, "<string>", &lineno, INCLUDE_ERROR,
1918 string_clear(&line);
1919 return nerr_pass(err);
1922 NEOERR * hdf_read_string_ignore (HDF *hdf, const char *str, int ignore)
1924 NEOERR *err;
1925 int lineno = 0;
1926 NEOSTRING line;
1927 string_init(&line);
1928 err = _hdf_read_string(hdf, &str, &line, "<string>", &lineno,
1929 (ignore ? INCLUDE_IGNORE : INCLUDE_ERROR), 0);
1930 string_clear(&line);
1931 return nerr_pass(err);
1934 /* The search path is part of the HDF by convention */
1935 NEOERR* hdf_search_path (HDF *hdf, const char *path, char *full, int full_len)
1937 HDF *paths;
1938 struct stat s;
1940 for (paths = hdf_get_child (hdf, "hdf.loadpaths");
1941 paths;
1942 paths = hdf_obj_next (paths))
1944 snprintf (full, full_len, "%s/%s", hdf_obj_value(paths), path);
1945 errno = 0;
1946 if (stat (full, &s) == -1)
1948 if (errno != ENOENT)
1949 return nerr_raise_errno (NERR_SYSTEM, "Stat of %s failed", full);
1951 else
1953 return STATUS_OK;
1957 strncpy (full, path, full_len);
1958 if (stat (full, &s) == -1)
1960 if (errno != ENOENT)
1961 return nerr_raise_errno (NERR_SYSTEM, "Stat of %s failed", full);
1963 else return STATUS_OK;
1965 return nerr_raise (NERR_NOT_FOUND, "Path %s not found", path);
1968 static NEOERR* hdf_read_file_internal (HDF *hdf, const char *path,
1969 int include_handle)
1971 NEOERR *err;
1972 int lineno = 0;
1973 char fpath[PATH_BUF_SIZE];
1974 char *ibuf = NULL;
1975 const char *ptr = NULL;
1976 HDF *top = hdf->top;
1977 NEOSTRING line;
1979 string_init(&line);
1981 if (path == NULL)
1982 return nerr_raise(NERR_ASSERT, "Can't read NULL file");
1984 if (top->fileload)
1986 err = top->fileload(top->fileload_ctx, hdf, path, &ibuf);
1988 else
1990 if (path[0] != '/')
1992 err = hdf_search_path (hdf, path, fpath, PATH_BUF_SIZE);
1993 if (err != STATUS_OK) return nerr_pass(err);
1994 path = fpath;
1997 err = ne_load_file (path, &ibuf);
1999 if (err) return nerr_pass(err);
2001 ptr = ibuf;
2002 err = _hdf_read_string(hdf, &ptr, &line, path, &lineno, include_handle, 0);
2003 free(ibuf);
2004 string_clear(&line);
2005 return nerr_pass(err);
2008 NEOERR* hdf_read_file (HDF *hdf, const char *path)
2010 NEOERR *err;
2011 err = hdf_read_file_internal (hdf, path, INCLUDE_FILE);
2012 return nerr_pass(err);
2015 void hdf_register_fileload(HDF *hdf, void *ctx, HDFFILELOAD fileload)
2017 if (hdf == NULL) return;
2018 if (hdf->top != NULL) hdf = hdf->top;
2019 hdf->fileload_ctx = ctx;
2020 hdf->fileload = fileload;