2 * Copyright 2001-2004 Brandon Long
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"
28 #include "neo_files.h"
31 static NEOERR
* hdf_read_file_internal (HDF
*hdf
, const char *path
,
35 static char *_read_file(FILE *f
) {
37 char *ret
= malloc(size
+ 1);
43 while ((nread
= fread(buf
, 1, len
, f
))) {
50 newret
= realloc(ret
, size
+ 1);
51 buf
= buf
- ret
+ newret
;
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
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
)
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
)
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
));
90 return nerr_raise (NERR_NOMEM
, "Unable to allocate memory for hdf element");
97 (*hdf
)->name_len
= nlen
;
98 (*hdf
)->name
= (char *) malloc (nlen
+ 1);
99 if ((*hdf
)->name
== 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';
113 (*hdf
)->alloc_value
= 1;
114 (*hdf
)->value
= strdup(value
);
115 if ((*hdf
)->value
== NULL
)
120 return nerr_raise (NERR_NOMEM
,
121 "Unable to allocate memory for hdf element %s", name
);
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
;
136 static void _dealloc_hdf_attr(HDF_ATTR
**attr
)
140 while ((*attr
) != NULL
)
142 next
= (*attr
)->next
;
143 if ((*attr
)->key
) free((*attr
)->key
);
144 if ((*attr
)->value
) free((*attr
)->value
);
151 static void _dealloc_hdf (HDF
**hdf
)
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 */
165 myhdf
->next
= next
->next
;
170 if (myhdf
->name
!= NULL
)
175 if (myhdf
->value
!= NULL
)
177 if (myhdf
->alloc_value
)
181 if (myhdf
->attr
!= NULL
)
183 _dealloc_hdf_attr(&(myhdf
->attr
));
185 if (myhdf
->hash
!= NULL
)
187 ne_hash_destroy(&myhdf
->hash
);
193 NEOERR
* hdf_init (HDF
**hdf
)
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
;
215 void hdf_destroy (HDF
**hdf
)
217 if (*hdf
== NULL
) return;
218 if ((*hdf
)->top
== (*hdf
))
224 static int _walk_hdf (HDF
*hdf
, const char *name
, HDF
**node
)
235 if (hdf
== NULL
) return -1;
236 if (name
== NULL
|| name
[0] == '\0')
244 r
= _walk_hdf (hdf
->top
, hdf
->value
, &hp
);
264 x
= (s
== NULL
) ? strlen(n
) : s
- n
;
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
);
278 if (hp
->name
&& (x
== hp
->name_len
) && !strncmp(hp
->name
, n
, x
))
292 if (s
== NULL
) break;
296 r
= _walk_hdf (hp
->top
, hp
->value
, &hp
);
310 x
= (s
== NULL
) ? strlen(n
) : s
- n
;
314 return _walk_hdf (hp
->top
, hp
->value
, node
);
321 int hdf_get_int_value (HDF
*hdf
, const char *name
, int defval
)
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
;
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
)
342 if ((_walk_hdf(hdf
, name
, &node
) == 0) && (node
->value
!= NULL
))
346 return (char *)defval
;
349 char* hdf_get_valuevf (HDF
*hdf
, const char *namefmt
, va_list ap
)
354 name
= vsprintf_alloc(namefmt
, ap
);
355 if (name
== NULL
) return NULL
;
356 if ((_walk_hdf(hdf
, name
, &node
) == 0) && (node
->value
!= NULL
))
365 char* hdf_get_valuef (HDF
*hdf
, const char *namefmt
, ...)
370 va_start(ap
, namefmt
);
371 val
= hdf_get_valuevf(hdf
, namefmt
, ap
);
376 NEOERR
* hdf_get_copy (HDF
*hdf
, const char *name
, char **value
,
381 if ((_walk_hdf(hdf
, name
, &node
) == 0) && (node
->value
!= NULL
))
383 *value
= strdup(node
->value
);
386 return nerr_raise (NERR_NOMEM
, "Unable to allocate copy of %s", name
);
395 *value
= strdup(defval
);
398 return nerr_raise (NERR_NOMEM
, "Unable to allocate copy of %s", name
);
405 HDF
* hdf_get_obj (HDF
*hdf
, const char *name
)
409 _walk_hdf(hdf
, name
, &obj
);
413 HDF
* hdf_get_child (HDF
*hdf
, const char *name
)
416 _walk_hdf(hdf
, name
, &obj
);
417 if (obj
!= NULL
) return obj
->child
;
421 HDF_ATTR
* hdf_get_attr (HDF
*hdf
, const char *name
)
424 _walk_hdf(hdf
, name
, &obj
);
425 if (obj
!= NULL
) return obj
->attr
;
429 NEOERR
* hdf_set_attr (HDF
*hdf
, const char *name
, const char *key
,
433 HDF_ATTR
*attr
, *last
;
435 _walk_hdf(hdf
, name
, &obj
);
437 return nerr_raise(NERR_ASSERT
, "Unable to set attribute on none existant node");
439 if (obj
->attr
!= NULL
)
445 if (!strcmp(attr
->key
, key
))
447 if (attr
->value
) free(attr
->value
);
448 /* a set of NULL deletes the attr */
451 if (attr
== obj
->attr
)
452 obj
->attr
= attr
->next
;
454 last
->next
= attr
->next
;
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
);
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
);
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
);
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
);
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
)
499 if (hdf
== NULL
) return NULL
;
502 if (_walk_hdf(hdf
->top
, hdf
->value
, &obj
))
509 HDF
* hdf_obj_next (HDF
*hdf
)
511 if (hdf
== NULL
) return NULL
;
515 HDF
* hdf_obj_top (HDF
*hdf
)
517 if (hdf
== NULL
) return NULL
;
521 HDF_ATTR
* hdf_obj_attr (HDF
*hdf
)
523 if (hdf
== NULL
) return NULL
;
527 char* hdf_obj_name (HDF
*hdf
)
529 if (hdf
== NULL
) return NULL
;
533 char* hdf_obj_value (HDF
*hdf
)
537 if (hdf
== NULL
) return NULL
;
538 while (hdf
->link
&& count
< 100)
540 if (_walk_hdf (hdf
->top
, hdf
->value
, &hdf
))
547 void _merge_attr (HDF_ATTR
*dest
, HDF_ATTR
*src
)
562 if (!strcmp(da
->key
, sa
->key
))
564 if (da
->value
) free(da
->value
);
565 da
->value
= sa
->value
;
577 if (src
== sa
) src
= sa
->next
;
578 ld
->next
->next
= NULL
;
587 _dealloc_hdf_attr(&src
);
590 NEOERR
* _hdf_hash_level(HDF
*hdf
)
595 err
= ne_hash_init(&(hdf
->hash
), hash_hdf_hash
, hash_hdf_comp
);
596 if (err
) return nerr_pass(err
);
601 err
= ne_hash_insert(hdf
->hash
, child
, child
);
602 if (err
) return nerr_pass(err
);
608 static NEOERR
* _set_value (HDF
*hdf
, const char *name
, const char *value
,
609 int dupl
, int wf
, int lnk
, HDF_ATTR
*attr
,
616 const char *s
= name
;
617 const char *n
= name
;
620 if (set_node
!= NULL
) *set_node
= 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
)
636 _merge_attr(hdf
->attr
, attr
);
639 if (lnk
) hdf
->link
= 1;
641 /* if we're setting ourselves to ourselves... */
642 if (hdf
->value
== value
)
644 if (set_node
!= NULL
) *set_node
= hdf
;
647 if (hdf
->alloc_value
)
654 hdf
->alloc_value
= 0;
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",
667 hdf
->alloc_value
= wf
;
668 hdf
->value
= (char *)value
;
670 if (set_node
!= NULL
) *set_node
= hdf
;
676 x
= (s
!= NULL
) ? s
- n
: strlen(n
);
679 return nerr_raise(NERR_ASSERT
, "Unable to set Empty component %s", name
);
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
);
694 return nerr_pass(err
);
703 /* examine cache to see if we have a match */
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
))
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
);
731 if (hp
->name
&& (x
== hp
->name_len
) && !strncmp(hp
->name
, n
, x
))
741 /* save in cache any value we found */
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) */
757 err
= _alloc_hdf (&hp
, n
, x
, NULL
, 0, 0, hdf
->top
);
761 err
= _alloc_hdf (&hp
, n
, x
, value
, dupl
, wf
, hdf
->top
);
762 if (lnk
) hp
->link
= 1;
766 if (err
!= STATUS_OK
)
767 return nerr_pass (err
);
768 if (hn
->child
== NULL
)
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
);
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
)
798 _merge_attr(hp
->attr
, attr
);
800 if (hp
->value
!= value
)
815 hp
->value
= strdup(value
);
816 if (hp
->value
== NULL
)
817 return nerr_raise (NERR_NOMEM
, "Unable to duplicate value %s for %s",
822 hp
->alloc_value
= wf
;
823 hp
->value
= (char *)value
;
826 if (lnk
) hp
->link
= 1;
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
);
838 err
= _set_value (hdf
->top
, new_name
, value
, dupl
, wf
, lnk
, attr
, set_node
);
840 return nerr_pass(err
);
842 /* At this point, we're done if there is not more HDF name space to
846 /* Otherwise, we need to find the next part of the namespace */
849 x
= (s
!= NULL
) ? s
- n
: strlen(n
);
852 return nerr_raise(NERR_ASSERT
, "Unable to set Empty component %s", name
);
856 if (set_node
!= NULL
) *set_node
= hp
;
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
,
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
)
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
)
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
)
905 k
= vsprintf_alloc(fmt
, ap
);
908 return nerr_raise(NERR_NOMEM
, "Unable to allocate memory for format string");
913 err
= nerr_raise(NERR_ASSERT
, "No equals found: %s", k
);
918 err
= hdf_set_value(hdf
, k
, v
);
920 return nerr_pass(err
);
923 NEOERR
* hdf_set_valuef (HDF
*hdf
, const char *fmt
, ...)
929 err
= hdf_set_valuevf(hdf
, fmt
, ap
);
931 return nerr_pass(err
);
934 NEOERR
* hdf_get_node (HDF
*hdf
, const char *name
, HDF
**ret
)
936 _walk_hdf(hdf
, name
, ret
);
939 return nerr_pass(_set_value (hdf
, name
, NULL
, 0, 1, 0, NULL
, ret
));
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
947 NEOERR
*hdf_sort_obj (HDF
*h
, int (*compareFunc
)(const void *, const void *))
949 NEOERR
*err
= STATUS_OK
;
954 if (h
== NULL
) return STATUS_OK
;
956 if (c
== NULL
) return STATUS_OK
;
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
);
965 err
= uListSort(level
, compareFunc
);
967 uListGet(level
, 0, (void *)&c
);
969 for (x
= 1; x
< uListLength(level
); x
++)
971 uListGet(level
, x
, (void *)&p
);
978 uListDestroy(&level
, 0);
979 return nerr_pass(err
);
982 NEOERR
* hdf_remove_tree (HDF
*hdf
, const char *name
)
985 HDF
*lp
= NULL
, *ln
= NULL
; /* last parent, last node */
987 const char *s
= name
;
988 const char *n
= name
;
990 if (hdf
== NULL
) return STATUS_OK
;
1002 s
= strchr (n
, '.');
1003 x
= (s
== NULL
) ? strlen(n
) : s
- n
;
1009 if (hp
->name
&& (x
== hp
->name_len
) && !strncmp(hp
->name
, n
, x
))
1023 if (s
== NULL
) break;
1029 s
= strchr (n
, '.');
1030 x
= (s
== NULL
) ? strlen(n
) : s
- n
;
1033 if (lp
->hash
!= NULL
)
1035 ne_hash_remove(lp
->hash
, hp
);
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
;
1048 lp
->child
= hp
->next
;
1056 static NEOERR
* _copy_attr (HDF_ATTR
**dest
, HDF_ATTR
*src
)
1058 HDF_ATTR
*copy
, *last
= NULL
;
1063 copy
= (HDF_ATTR
*)malloc(sizeof(HDF_ATTR
));
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
);
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");
1090 static NEOERR
* _copy_nodes (HDF
*dest
, HDF
*src
)
1092 NEOERR
*err
= STATUS_OK
;
1094 HDF_ATTR
*attr_copy
;
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
);
1103 _dealloc_hdf_attr(&attr_copy
);
1104 return nerr_pass(err
);
1108 err
= _copy_nodes (dt
, st
);
1109 if (err
) return nerr_pass(err
);
1116 NEOERR
* hdf_copy (HDF
*dest
, const char *name
, HDF
*src
)
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
,
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
)
1145 nlen
= 2 + neo_rand(len
-5);
1152 ml
[x
++] = ('A' + neo_rand(26));
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
;
1167 vfprintf(fp
, fmt
, ap
);
1172 static NEOERR
*_string_dump_cb (void *rock
, const char *fmt
, ...)
1175 NEOSTRING
*str
= (NEOSTRING
*)rock
;
1179 err
= string_appendvf(str
, fmt
, 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
)
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);
1205 if (hdf
!= NULL
) hdf
= hdf
->child
;
1212 if (hdf
->link
) op
= ':';
1213 if (prefix
&& (dtype
== DUMP_TYPE_DOTTED
))
1215 err
= dump_cbf(rock
, "%s.%s", prefix
, hdf
->name
);
1219 err
= dump_cbf(rock
, "%s%s", whsp
, hdf
->name
);
1221 if (err
) return nerr_pass (err
);
1224 HDF_ATTR
*attr
= hdf
->attr
;
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
);
1235 v
= repr_string_alloc(attr
->value
);
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
);
1242 if (err
) return nerr_pass(err
);
1245 err
= dump_cbf(rock
, ", ");
1246 if (err
) return nerr_pass(err
);
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
);
1265 err
= dump_cbf(rock
, " << %s%s%s", ml
+1, hdf
->value
, ml
+1);
1269 err
= dump_cbf(rock
, " %c %s\n", op
, hdf
->value
);
1271 if (err
) return nerr_pass (err
);
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
);
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
);
1294 err
= hdf_dump_cb (hdf
, hdf
->name
, dtype
, lvl
+1, rock
, dump_cbf
);
1297 if (err
) return nerr_pass (err
);
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
)
1324 fp
= fopen(path
, "w");
1326 return nerr_raise_errno (NERR_IO
, "Unable to open %s for writing", path
);
1328 err
= hdf_dump_format (hdf
, 0, fp
);
1335 return nerr_pass(err
);
1338 NEOERR
*hdf_write_file_atomic (HDF
*hdf
, const char *path
)
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");
1349 return nerr_raise_errno (NERR_IO
, "Unable to open %s for writing", tpath
);
1351 err
= hdf_dump_format (hdf
, 0, fp
);
1358 return nerr_pass(err
);
1360 if (rename(tpath
, path
) == -1)
1363 return nerr_raise_errno (NERR_IO
, "Unable to rename file %s to %s",
1370 NEOERR
*hdf_write_string (HDF
*hdf
, char **s
)
1379 err
= hdf_dump_str (hdf
, NULL
, 2, &str
);
1382 string_clear (&str
);
1383 return nerr_pass(err
);
1385 if (str
.buf
== NULL
)
1388 if (*s
== NULL
) return nerr_raise(NERR_NOMEM
, "Unable to allocate empty string");
1399 #define SKIPWS(s) while (*s && isspace(*s)) s++;
1401 static int _copy_line (const char **s
, char *buf
, size_t buf_len
)
1404 const char *st
= *s
;
1406 while (*st
&& x
< buf_len
-1)
1409 if (*st
++ == '\n') break;
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
)
1423 const char *st
= *s
;
1426 nl
= strchr(st
, '\n');
1430 err
= string_appendn(line
, st
, x
);
1431 if (err
) return nerr_pass(err
);
1437 err
= string_appendn(line
, st
, x
);
1438 if (err
) return nerr_pass(err
);
1445 char *_strndup(const char *s
, int len
) {
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
++)
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
;
1469 HDF_ATTR
*ha
, *hal
= NULL
;
1474 while (*s
&& *s
!= ']')
1480 while (*s
&& isalnum(*s
)) s
++;
1482 if (*s
== '\0' || k_l
== 0)
1484 _dealloc_hdf_attr(attr
);
1485 return nerr_raise(NERR_PARSE
, "Misformed attribute specification: %s", *str
);
1495 while (*s
&& *s
!= '"')
1499 if (isdigit(*(s
+1)))
1503 if (isdigit(*(s
+1)))
1506 c
= (c
* 8) + (*s
- '0');
1507 if (isdigit(*(s
+1)))
1510 c
= (c
* 8) + (*s
- '0');
1517 if (*s
== 'n') c
= '\n';
1518 else if (*s
== 't') c
= '\t';
1519 else if (*s
== 'r') c
= '\r';
1522 err
= string_append_char(&buf
, c
);
1526 err
= string_append_char(&buf
, *s
);
1531 _dealloc_hdf_attr(attr
);
1532 return nerr_pass(err
);
1538 _dealloc_hdf_attr(attr
);
1540 return nerr_raise(NERR_PARSE
, "Misformed attribute specification: %s", *str
);
1549 while (*s
&& *s
!= ' ' && *s
!= ',' && *s
!= ']') s
++;
1552 _dealloc_hdf_attr(attr
);
1553 return nerr_raise(NERR_PARSE
, "Misformed attribute specification: %s", *str
);
1562 ha
= (HDF_ATTR
*) calloc (1, sizeof(HDF_ATTR
));
1565 _dealloc_hdf_attr(attr
);
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
);
1572 ha
->value
= _strndup(v
, v_l
);
1574 ha
->value
= strdup("");
1575 if (ha
->key
== NULL
|| ha
->value
== NULL
)
1577 _dealloc_hdf_attr(attr
);
1579 return nerr_raise(NERR_NOMEM
, "Unable to load attributes: %s", s
);
1581 if (hal
!= NULL
) hal
->next
= ha
;
1593 _dealloc_hdf_attr(attr
);
1594 return nerr_raise(NERR_PARSE
, "Misformed attribute specification: %s", *str
);
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
) {
1612 HDF_ATTR
*attr
= NULL
;
1614 while (**str
!= '\0')
1616 /* Reset string length, but don't free the reserved buffer */
1618 err
= _copy_line_advance(str
, line
);
1619 if (err
) return nerr_pass(err
);
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",
1633 else if (include_handle
< INCLUDE_MAX_DEPTH
)
1637 name
= neos_strip(s
);
1639 if (name
[0] == '"' && name
[l
-1] == '"')
1644 char fullpath
[PATH_MAX
];
1645 if (name
[0] != '/') {
1646 memset(fullpath
, 0, PATH_MAX
);
1648 char *p
= strrchr(path
, '/');
1651 memset(pwd
, 0, PATH_MAX
);
1652 getcwd(pwd
, PATH_MAX
);
1653 snprintf(fullpath
, PATH_MAX
, "%s/%s", pwd
, name
);
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
);
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
);
1668 return nerr_raise (NERR_MAX_RECURSION
,
1669 "[%d]: Too many recursion levels.",
1674 else if (s
[0] == '#')
1678 else if (s
[0] == '}') /* up */
1683 err
= nerr_raise(NERR_PARSE
,
1684 "[%s:%d] Trailing garbage on line following }: %s", path
, *lineno
,
1692 /* Valid hdf name is [0-9a-zA-Z_.*\]+ */
1693 int splice
= *s
== '@';
1696 while (*s
&& (isalnum(*s
) || *s
== '_' || *s
== '.' || *s
== '*' || *s
== '\\')) s
++;
1700 static int counter
= 0;
1703 for (p
= name
; p
< s
&& i
< 200; p
++) {
1707 i
+= snprintf(num
+ i
, 256 - i
, "%d", counter
++);
1713 if (s
[0] == '[') /* attributes */
1716 name
= neos_strip(name
);
1718 err
= parse_attr(&s
, &attr
);
1721 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1726 name
= neos_strip(name
);
1727 HDF
*h
= hdf_get_obj(hdf
->top
, name
);
1729 HDF
*c
= hdf_obj_child(h
);
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 */
1743 name
= neos_strip(name
);
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 */
1755 name
= neos_strip(name
);
1757 value
= neos_strip(s
);
1758 HDF
*h
= hdf_get_obj(hdf
->top
, value
);
1761 err
= nerr_raise(NERR_PARSE
,
1762 "[%s:%d] Failed to copy a node that is not loaded "
1763 "yet: %s", path
, *lineno
, value
);
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 */
1775 name
= neos_strip(name
);
1777 value
= neos_strip(s
);
1779 FILE *f
= popen(value
, "r");
1782 err
= nerr_raise(NERR_PARSE
,
1783 "[%s:%d] Failed to exec specified command: %s",
1784 path
, *lineno
, line
->buf
);
1787 char *content
= _read_file(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
);
1796 if (err
!= STATUS_OK
)
1798 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1801 else if (s
[0] == ':') /* link */
1804 name
= neos_strip(name
);
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 */
1816 name
= neos_strip(name
);
1817 lower
= hdf_get_obj (hdf
, name
);
1820 err
= _set_value (hdf
, name
, NULL
, 1, 1, 0, attr
, &lower
);
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 */
1845 name
= neos_strip(name
);
1847 value
= neos_strip(s
);
1851 err
= nerr_raise(NERR_PARSE
,
1852 "[%s:%d] No multi-assignment terminator given: %s", path
, *lineno
,
1856 m
= (char *) malloc (mmax
* sizeof(char));
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)
1866 if (!strncmp(value
, m
+msize
, l
) && isspace(m
[msize
+l
]))
1871 msize
+= strlen(m
+msize
);
1872 if (msize
+ l
+ 10 > mmax
)
1876 new_ptr
= realloc (m
, mmax
* sizeof(char));
1877 if (new_ptr
== NULL
)
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
)
1891 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1897 err
= nerr_raise(NERR_PARSE
, "[%s:%d] Unable to parse line %s", path
,
1898 *lineno
, line
->buf
);
1903 if (expect_end_brace
) {
1904 err
= nerr_raise(NERR_PARSE
, "[%s:%d] Missing matching }", path
, *lineno
);
1910 NEOERR
* hdf_read_string (HDF
*hdf
, const char *str
)
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
)
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
)
1940 for (paths
= hdf_get_child (hdf
, "hdf.loadpaths");
1942 paths
= hdf_obj_next (paths
))
1944 snprintf (full
, full_len
, "%s/%s", hdf_obj_value(paths
), path
);
1946 if (stat (full
, &s
) == -1)
1948 if (errno
!= ENOENT
)
1949 return nerr_raise_errno (NERR_SYSTEM
, "Stat of %s failed", full
);
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
,
1973 char fpath
[PATH_BUF_SIZE
];
1975 const char *ptr
= NULL
;
1976 HDF
*top
= hdf
->top
;
1982 return nerr_raise(NERR_ASSERT
, "Can't read NULL file");
1986 err
= top
->fileload(top
->fileload_ctx
, hdf
, path
, &ibuf
);
1992 err
= hdf_search_path (hdf
, path
, fpath
, PATH_BUF_SIZE
);
1993 if (err
!= STATUS_OK
) return nerr_pass(err
);
1997 err
= ne_load_file (path
, &ibuf
);
1999 if (err
) return nerr_pass(err
);
2002 err
= _hdf_read_string(hdf
, &ptr
, &line
, path
, &lineno
, include_handle
, 0);
2004 string_clear(&line
);
2005 return nerr_pass(err
);
2008 NEOERR
* hdf_read_file (HDF
*hdf
, const char *path
)
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
;