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"
27 #define PATH_MAX MAX_PATH
37 #include "neo_files.h"
40 static NEOERR
* hdf_read_file_internal (HDF
*hdf
, const char *path
,
44 static char *_read_file(FILE *f
) {
46 char *ret
= malloc(size
+ 1);
52 while ((nread
= fread(buf
, 1, len
, f
))) {
59 newret
= realloc(ret
, size
+ 1);
60 buf
= buf
- ret
+ newret
;
68 /* Ok, in order to use the hash, we have to support n-len strings
69 * instead of null terminated strings (since in set_value and walk_hdf
70 * we are merely using part of the HDF name for lookup, and that might
71 * be a const, and we don't want the overhead of allocating/copying
74 * Since HASH doesn't maintain any data placed in it, merely pointers to
75 * it, we use the HDF node itself as the key, and have specific
76 * comp/hash functions which just use the name/name_len as the key.
79 static int hash_hdf_comp(const void *a
, const void *b
)
84 return (ha
->name_len
== hb
->name_len
) && !strncmp(ha
->name
, hb
->name
, ha
->name_len
);
87 static UINT32
hash_hdf_hash(const void *a
)
90 return ne_crc((UINT8
*)(ha
->name
), ha
->name_len
);
93 static NEOERR
*_alloc_hdf (HDF
**hdf
, const char *name
, size_t nlen
,
94 const char *value
, int dupl
, int wf
, HDF
*top
)
96 *hdf
= calloc (1, sizeof (HDF
));
99 return nerr_raise (NERR_NOMEM
, "Unable to allocate memory for hdf element");
106 (*hdf
)->name_len
= nlen
;
107 (*hdf
)->name
= (char *) malloc (nlen
+ 1);
108 if ((*hdf
)->name
== NULL
)
112 return nerr_raise (NERR_NOMEM
,
113 "Unable to allocate memory for hdf element: %s", name
);
115 strncpy((*hdf
)->name
, name
, nlen
);
116 (*hdf
)->name
[nlen
] = '\0';
122 (*hdf
)->alloc_value
= 1;
123 (*hdf
)->value
= strdup(value
);
124 if ((*hdf
)->value
== NULL
)
129 return nerr_raise (NERR_NOMEM
,
130 "Unable to allocate memory for hdf element %s", name
);
135 (*hdf
)->alloc_value
= wf
;
136 /* We're overriding the const of value here for the set_buf case
137 * where we overrode the char * to const char * earlier, since
138 * alloc_value actually keeps track of the const-ness for us */
139 (*hdf
)->value
= (char *)value
;
145 static void _dealloc_hdf_attr(HDF_ATTR
**attr
)
149 while ((*attr
) != NULL
)
151 next
= (*attr
)->next
;
152 if ((*attr
)->key
) free((*attr
)->key
);
153 if ((*attr
)->value
) free((*attr
)->value
);
160 static void _dealloc_hdf (HDF
**hdf
)
165 if (myhdf
== NULL
) return;
166 if (myhdf
->child
!= NULL
)
167 _dealloc_hdf(&(myhdf
->child
));
169 /* This was easier recursively, but dangerous on long lists, so we
170 * walk it ourselves */
174 myhdf
->next
= next
->next
;
179 if (myhdf
->name
!= NULL
)
184 if (myhdf
->value
!= NULL
)
186 if (myhdf
->alloc_value
)
190 if (myhdf
->attr
!= NULL
)
192 _dealloc_hdf_attr(&(myhdf
->attr
));
194 if (myhdf
->hash
!= NULL
)
196 ne_hash_destroy(&myhdf
->hash
);
202 NEOERR
* hdf_init (HDF
**hdf
)
210 if (err
!= STATUS_OK
)
211 return nerr_pass (err
);
213 err
= _alloc_hdf (&my_hdf
, NULL
, 0, NULL
, 0, 0, NULL
);
214 if (err
!= STATUS_OK
)
215 return nerr_pass (err
);
217 my_hdf
->top
= my_hdf
;
224 void hdf_destroy (HDF
**hdf
)
226 if (*hdf
== NULL
) return;
227 if ((*hdf
)->top
== (*hdf
))
233 #define WALK_MAX_DEPTH 1000
235 static int _walk_hdf (HDF
*hdf
, const char *name
, HDF
**node
,
236 NEOERR
** err
, int recursion
)
247 if (hdf
== NULL
) return -1;
248 if (name
== NULL
|| name
[0] == '\0')
256 if (recursion
>= WALK_MAX_DEPTH
) {
257 *err
= nerr_raise (NERR_MAX_RECURSION
,
258 "Recursion limit reached in _walk_hdf"
262 r
= _walk_hdf (hdf
->top
, hdf
->value
, &hp
, err
, recursion
+ 1);
282 x
= (s
== NULL
) ? strlen(n
) : s
- n
;
286 if (parent
&& parent
->hash
)
288 hash_key
.name
= (char *)n
;
289 hash_key
.name_len
= x
;
290 hp
= ne_hash_lookup(parent
->hash
, &hash_key
);
296 if (hp
->name
&& (x
== hp
->name_len
) && !strncmp(hp
->name
, n
, x
))
310 if (s
== NULL
) break;
314 if (recursion
>= WALK_MAX_DEPTH
) {
315 *err
= nerr_raise (NERR_MAX_RECURSION
,
316 "Recursion limit reached in _walk_hdf"
320 r
= _walk_hdf (hp
->top
, hp
->value
, &hp
, err
, recursion
+ 1);
334 x
= (s
== NULL
) ? strlen(n
) : s
- n
;
338 if (recursion
>= WALK_MAX_DEPTH
) {
339 *err
= nerr_raise (NERR_MAX_RECURSION
,
340 "Recursion limit reached in _walk_hdf"
344 return _walk_hdf (hp
->top
, hp
->value
, node
, err
, recursion
+ 1);
351 HDF
* hdf_get_obj (HDF
*hdf
, const char *name
, NEOERR
** err
)
355 _walk_hdf(hdf
, name
, &obj
, err
, 0);
359 HDF
* hdf_get_child (HDF
*hdf
, const char *name
, NEOERR
** err
)
362 _walk_hdf(hdf
, name
, &obj
, err
, 0);
363 if (obj
!= NULL
) return obj
->child
;
367 void hdf_set_visited (HDF
*hdf
, int visited
) {
368 if (hdf
) hdf
->visited
= visited
;
371 int hdf_is_visited (HDF
*hdf
) {
372 return hdf
? hdf
->visited
: 0;
375 HDF
* hdf_obj_child (HDF
*hdf
, NEOERR
** err
)
378 if (hdf
== NULL
) return NULL
;
381 if (_walk_hdf(hdf
->top
, hdf
->value
, &obj
, err
, 0))
388 HDF
* hdf_obj_next (HDF
*hdf
)
390 if (hdf
== NULL
) return NULL
;
394 char* hdf_obj_name (HDF
*hdf
)
396 if (hdf
== NULL
) return NULL
;
400 char* hdf_obj_value (HDF
*hdf
, NEOERR
** err
)
404 if (hdf
== NULL
) return NULL
;
405 while (hdf
->link
&& count
< 100)
407 if (_walk_hdf (hdf
->top
, hdf
->value
, &hdf
, err
, 0))
414 void _merge_attr (HDF_ATTR
*dest
, HDF_ATTR
*src
)
429 if (!strcmp(da
->key
, sa
->key
))
431 if (da
->value
) free(da
->value
);
432 da
->value
= sa
->value
;
444 if (src
== sa
) src
= sa
->next
;
445 ld
->next
->next
= NULL
;
454 _dealloc_hdf_attr(&src
);
457 NEOERR
* _hdf_hash_level(HDF
*hdf
)
462 err
= ne_hash_init(&(hdf
->hash
), hash_hdf_hash
, hash_hdf_comp
);
463 if (err
) return nerr_pass(err
);
468 err
= ne_hash_insert(hdf
->hash
, child
, child
);
469 if (err
) return nerr_pass(err
);
475 static NEOERR
* _set_value (HDF
*hdf
, const char *name
, const char *value
,
476 int dupl
, int wf
, int lnk
, HDF_ATTR
*attr
,
483 const char *s
= name
;
484 const char *n
= name
;
487 if (set_node
!= NULL
) *set_node
= NULL
;
490 return nerr_raise(NERR_ASSERT
, "Unable to set %s on NULL hdf", name
);
493 /* HACK: allow setting of this node by passing an empty name */
494 if (name
== NULL
|| name
[0] == '\0')
496 /* handle setting attr first */
497 if (hdf
->attr
== NULL
)
503 _merge_attr(hdf
->attr
, attr
);
506 if (lnk
) hdf
->link
= 1;
508 /* if we're setting ourselves to ourselves... */
509 if (hdf
->value
== value
)
511 if (set_node
!= NULL
) *set_node
= hdf
;
514 if (hdf
->alloc_value
)
521 hdf
->alloc_value
= 0;
526 hdf
->alloc_value
= 1;
527 hdf
->value
= strdup(value
);
528 if (hdf
->value
== NULL
)
529 return nerr_raise (NERR_NOMEM
, "Unable to duplicate value %s for %s",
534 hdf
->alloc_value
= wf
;
535 hdf
->value
= (char *)value
;
537 if (set_node
!= NULL
) *set_node
= hdf
;
543 x
= (s
!= NULL
) ? s
- n
: strlen(n
);
546 return nerr_raise(NERR_ASSERT
, "Unable to set Empty component %s", name
);
551 char *new_name
= (char *) malloc(strlen(hdf
->value
) + 1 + strlen(name
) + 1);
552 if (new_name
== NULL
)
554 return nerr_raise(NERR_NOMEM
, "Unable to allocate memory");
556 strcpy(new_name
, hdf
->value
);
557 strcat(new_name
, ".");
558 strcat(new_name
, name
);
559 err
= _set_value (hdf
->top
, new_name
, value
, dupl
, wf
, lnk
, attr
, set_node
);
561 return nerr_pass(err
);
570 /* examine cache to see if we have a match */
575 if ((hs
== NULL
&& hp
== hn
->child
) || (hs
&& hs
->next
== hp
))
577 if (hp
&& hp
->name
&& (x
== hp
->name_len
) && !strncmp (hp
->name
, n
, x
))
586 /* Look for a matching node at this level */
587 if (hn
->hash
!= NULL
)
589 hash_key
.name
= (char *)n
;
590 hash_key
.name_len
= x
;
591 hp
= ne_hash_lookup(hn
->hash
, &hash_key
);
598 if (hp
->name
&& (x
== hp
->name_len
) && !strncmp(hp
->name
, n
, x
))
608 /* save in cache any value we found */
618 /* If there was no matching node at this level, we need to
619 * allocate an intersitial node (or the actual node if we're
620 * at the last part of the HDF name) */
624 err
= _alloc_hdf (&hp
, n
, x
, NULL
, 0, 0, hdf
->top
);
628 err
= _alloc_hdf (&hp
, n
, x
, value
, dupl
, wf
, hdf
->top
);
629 if (lnk
) hp
->link
= 1;
633 if (err
!= STATUS_OK
)
634 return nerr_pass (err
);
635 if (hn
->child
== NULL
)
641 /* This is the point at which we convert to a hash table
642 * at this level, if we're over the count */
643 if (count
> FORCE_HASH_AT
&& hn
->hash
== NULL
)
645 err
= _hdf_hash_level(hn
);
646 if (err
) return nerr_pass(err
);
648 else if (hn
->hash
!= NULL
)
650 err
= ne_hash_insert(hn
->hash
, hp
, hp
);
651 if (err
) return nerr_pass(err
);
656 /* If there is a matching node and we're at the end of the HDF
657 * name, then we update the value of the node */
658 /* handle setting attr first */
659 if (hp
->attr
== NULL
)
665 _merge_attr(hp
->attr
, attr
);
667 if (hp
->value
!= value
)
682 hp
->value
= strdup(value
);
683 if (hp
->value
== NULL
)
684 return nerr_raise (NERR_NOMEM
, "Unable to duplicate value %s for %s",
689 hp
->alloc_value
= wf
;
690 hp
->value
= (char *)value
;
693 if (lnk
) hp
->link
= 1;
698 char *new_name
= (char *) malloc(strlen(hp
->value
) + strlen(s
) + 1);
699 if (new_name
== NULL
)
701 return nerr_raise(NERR_NOMEM
, "Unable to allocate memory");
703 strcpy(new_name
, hp
->value
);
705 err
= _set_value (hdf
->top
, new_name
, value
, dupl
, wf
, lnk
, attr
, set_node
);
707 return nerr_pass(err
);
709 /* At this point, we're done if there is not more HDF name space to
713 /* Otherwise, we need to find the next part of the namespace */
716 x
= (s
!= NULL
) ? s
- n
: strlen(n
);
719 return nerr_raise(NERR_ASSERT
, "Unable to set Empty component %s", name
);
723 if (set_node
!= NULL
) *set_node
= hp
;
727 NEOERR
* hdf_set_value (HDF
*hdf
, const char *name
, const char *value
)
729 return nerr_pass(_set_value (hdf
, name
, value
, 1, 1, 0, NULL
, NULL
));
732 NEOERR
* hdf_get_node (HDF
*hdf
, const char *name
, HDF
**ret
)
734 NEOERR
* err
= STATUS_OK
;
735 _walk_hdf(hdf
, name
, ret
, &err
, 0);
738 if (err
!= STATUS_OK
) return err
;
739 return nerr_pass(_set_value (hdf
, name
, NULL
, 0, 1, 0, NULL
, ret
));
744 NEOERR
* hdf_remove_tree (HDF
*hdf
, const char *name
)
747 HDF
*lp
= NULL
, *ln
= NULL
; /* last parent, last node */
749 const char *s
= name
;
750 const char *n
= name
;
752 if (hdf
== NULL
) return STATUS_OK
;
765 x
= (s
== NULL
) ? strlen(n
) : s
- n
;
771 if (hp
->name
&& (x
== hp
->name_len
) && !strncmp(hp
->name
, n
, x
))
785 if (s
== NULL
) break;
792 x
= (s
== NULL
) ? strlen(n
) : s
- n
;
795 if (lp
->hash
!= NULL
)
797 ne_hash_remove(lp
->hash
, hp
);
802 /* check to see if we are the last parent's last_child, if so
803 * repoint so hash table inserts will go to the right place */
804 if (hp
== lp
->last_child
)
810 lp
->child
= hp
->next
;
818 static NEOERR
* _copy_attr (HDF_ATTR
**dest
, HDF_ATTR
*src
)
820 HDF_ATTR
*copy
, *last
= NULL
;
825 copy
= (HDF_ATTR
*)malloc(sizeof(HDF_ATTR
));
828 _dealloc_hdf_attr(dest
);
829 return nerr_raise(NERR_NOMEM
, "Unable to allocate copy of HDF_ATTR");
831 copy
->key
= strdup(src
->key
);
832 copy
->value
= strdup(src
->value
);
834 if ((copy
->key
== NULL
) || (copy
->value
== NULL
))
836 _dealloc_hdf_attr(dest
);
837 return nerr_raise(NERR_NOMEM
, "Unable to allocate copy of HDF_ATTR");
852 static NEOERR
* _copy_nodes (HDF
*dest
, HDF
*src
)
854 NEOERR
*err
= STATUS_OK
;
861 err
= _copy_attr(&attr_copy
, st
->attr
);
862 if (err
) return nerr_pass(err
);
863 err
= _set_value(dest
, st
->name
, st
->value
, 1, 1, st
->link
, attr_copy
, &dt
);
865 _dealloc_hdf_attr(&attr_copy
);
866 return nerr_pass(err
);
870 err
= _copy_nodes (dt
, st
);
871 if (err
) return nerr_pass(err
);
878 NEOERR
* hdf_copy (HDF
*dest
, const char *name
, HDF
*src
)
885 if (_walk_hdf(dest
, name
, &node
, &err
, 0) == -1)
888 err
= _copy_attr(&attr_copy
, src
->attr
);
889 if (err
) return nerr_pass(err
);
890 err
= _set_value (dest
, name
, src
->value
, 1, 1, src
->link
, attr_copy
,
893 _dealloc_hdf_attr(&attr_copy
);
894 return nerr_pass(err
);
897 return nerr_pass (_copy_nodes (node
, src
));
900 /* BUG: currently, this only prints something if there is a value...
901 * but we now allow attributes on nodes with no value... */
903 static void gen_ml_break(char *ml
, size_t len
)
909 nlen
= 2 + neo_rand(len
-5);
916 ml
[x
++] = ('A' + neo_rand(26));
923 typedef NEOERR
*(*DUMPF_CB
)(void *rock
, const char *fmt
, ...);
925 static NEOERR
*_fp_dump_cb (void *rock
, const char *fmt
, ...)
927 FILE *fp
= (FILE *)rock
;
931 vfprintf(fp
, fmt
, ap
);
936 static NEOERR
*_string_dump_cb (void *rock
, const char *fmt
, ...)
939 NEOSTRING
*str
= (NEOSTRING
*)rock
;
943 err
= string_appendvf(str
, fmt
, ap
);
945 return nerr_pass(err
);
948 #define DUMP_TYPE_DOTTED 0
949 #define DUMP_TYPE_COMPACT 1
950 #define DUMP_TYPE_PRETTY 2
952 static NEOERR
* hdf_dump_cb(HDF
*hdf
, const char *prefix
, int dtype
, int lvl
,
953 void *rock
, DUMPF_CB dump_cbf
)
957 char ml
[10] = "\nEOM\n";
958 int ml_len
= strlen(ml
);
961 if (dtype
== DUMP_TYPE_PRETTY
)
963 memset(whsp
, ' ', 256);
969 if (hdf
!= NULL
) hdf
= hdf
->child
;
976 if (hdf
->link
) op
= ':';
977 if (prefix
&& (dtype
== DUMP_TYPE_DOTTED
))
979 err
= dump_cbf(rock
, "%s.%s", prefix
, hdf
->name
);
983 err
= dump_cbf(rock
, "%s%s", whsp
, hdf
->name
);
985 if (err
) return nerr_pass (err
);
988 HDF_ATTR
*attr
= hdf
->attr
;
991 err
= dump_cbf(rock
, " [");
992 if (err
) return nerr_pass(err
);
996 if (attr
->value
== NULL
|| !strcmp(attr
->value
, "1"))
997 err
= dump_cbf(rock
, "%s", attr
->key
);
1000 v
= repr_string_alloc(attr
->value
);
1003 return nerr_raise(NERR_NOMEM
, "Unable to repr attr %s value %s", attr
->key
, attr
->value
);
1004 err
= dump_cbf(rock
, "%s=%s", attr
->key
, v
);
1007 if (err
) return nerr_pass(err
);
1010 err
= dump_cbf(rock
, ", ");
1011 if (err
) return nerr_pass(err
);
1015 err
= dump_cbf(rock
, "] ");
1016 if (err
) return nerr_pass(err
);
1018 if (strchr (hdf
->value
, '\n'))
1020 int vlen
= strlen(hdf
->value
);
1022 while (strstr(hdf
->value
, ml
) || ((vlen
> ml_len
) && !strncmp(hdf
->value
+ vlen
- ml_len
+ 1, ml
, strlen(ml
) - 1)))
1024 gen_ml_break(ml
, sizeof(ml
));
1025 ml_len
= strlen(ml
);
1027 if (hdf
->value
[strlen(hdf
->value
)-1] != '\n')
1028 err
= dump_cbf(rock
, " << %s%s%s", ml
+1, hdf
->value
, ml
);
1030 err
= dump_cbf(rock
, " << %s%s%s", ml
+1, hdf
->value
, ml
+1);
1034 err
= dump_cbf(rock
, " %c %s\n", op
, hdf
->value
);
1036 if (err
) return nerr_pass (err
);
1040 if (prefix
&& (dtype
== DUMP_TYPE_DOTTED
))
1042 size_t p_len
= strlen(hdf
->name
) + strlen(prefix
) + 2;
1043 p
= (char *) malloc (p_len
);
1044 snprintf (p
, p_len
, "%s.%s", prefix
, hdf
->name
);
1046 err
= hdf_dump_cb (hdf
, p
, dtype
, lvl
+1, rock
, dump_cbf
);
1051 if (hdf
->name
&& (dtype
!= DUMP_TYPE_DOTTED
))
1053 err
= dump_cbf(rock
, "%s%s {\n", whsp
, hdf
->name
);
1054 if (err
) return nerr_pass (err
);
1055 err
= hdf_dump_cb (hdf
, hdf
->name
, dtype
, lvl
+1, rock
, dump_cbf
);
1056 if (err
) return nerr_pass (err
);
1057 err
= dump_cbf(rock
, "%s}\n", whsp
);
1061 err
= hdf_dump_cb (hdf
, hdf
->name
, dtype
, lvl
+1, rock
, dump_cbf
);
1064 if (err
) return nerr_pass (err
);
1071 NEOERR
* hdf_dump_str (HDF
*hdf
, const char *prefix
, int dtype
, NEOSTRING
*str
)
1073 return nerr_pass(hdf_dump_cb(hdf
, prefix
, dtype
, 0, str
, _string_dump_cb
));
1076 NEOERR
* hdf_dump_format (HDF
*hdf
, int lvl
, FILE *fp
)
1078 return nerr_pass(hdf_dump_cb(hdf
, "", DUMP_TYPE_PRETTY
, 0, fp
, _fp_dump_cb
));
1081 NEOERR
*hdf_write_file (HDF
*hdf
, const char *path
)
1086 fp
= fopen(path
, "w");
1088 return nerr_raise_errno (NERR_IO
, "Unable to open %s for writing", path
);
1090 err
= hdf_dump_format (hdf
, 0, fp
);
1097 return nerr_pass(err
);
1100 NEOERR
*hdf_write_string (HDF
*hdf
, char **s
)
1109 err
= hdf_dump_str (hdf
, NULL
, 2, &str
);
1112 string_clear (&str
);
1113 return nerr_pass(err
);
1115 if (str
.buf
== NULL
)
1118 if (*s
== NULL
) return nerr_raise(NERR_NOMEM
, "Unable to allocate empty string");
1129 #define SKIPWS(s) while (*s && isspace(*s)) s++;
1131 static int _copy_line (const char **s
, char *buf
, size_t buf_len
)
1134 const char *st
= *s
;
1136 while (*st
&& x
< buf_len
-1)
1139 if (*st
++ == '\n') break;
1147 /* Copy the characters in the file (up to the next newline) into line
1148 * and advance s to the next line */
1149 static NEOERR
*_copy_line_advance(const char **s
, NEOSTRING
*line
)
1153 const char *st
= *s
;
1156 nl
= strchr(st
, '\n');
1160 err
= string_appendn(line
, st
, x
);
1161 if (err
) return nerr_pass(err
);
1167 err
= string_appendn(line
, st
, x
);
1168 if (err
) return nerr_pass(err
);
1175 char *_strndup(const char *s
, int len
) {
1178 if (s
== NULL
) return NULL
;
1179 dupl
= (char *) malloc(len
+1);
1180 if (dupl
== NULL
) return NULL
;
1181 for (x
= 0; x
< len
&& s
[x
]; x
++)
1190 /* attributes are of the form [key1, key2, key3=value, key4="repr"] */
1191 static NEOERR
* parse_attr(char **str
, HDF_ATTR
**attr
)
1193 NEOERR
*err
= STATUS_OK
;
1199 HDF_ATTR
*ha
, *hal
= NULL
;
1204 while (*s
&& *s
!= ']')
1210 while (*s
&& isalnum(*s
)) s
++;
1212 if (*s
== '\0' || k_l
== 0)
1214 _dealloc_hdf_attr(attr
);
1215 return nerr_raise(NERR_PARSE
, "Malformed attribute specification: %s", *str
);
1225 while (*s
&& *s
!= '"')
1229 if (isdigit(*(s
+1)))
1233 if (isdigit(*(s
+1)))
1236 c
= (c
* 8) + (*s
- '0');
1237 if (isdigit(*(s
+1)))
1240 c
= (c
* 8) + (*s
- '0');
1247 if (*s
== 'n') c
= '\n';
1248 else if (*s
== 't') c
= '\t';
1249 else if (*s
== 'r') c
= '\r';
1252 err
= string_append_char(&buf
, c
);
1256 err
= string_append_char(&buf
, *s
);
1261 _dealloc_hdf_attr(attr
);
1262 return nerr_pass(err
);
1268 _dealloc_hdf_attr(attr
);
1270 return nerr_raise(NERR_PARSE
, "Malformed attribute specification: %s", *str
);
1279 while (*s
&& *s
!= ' ' && *s
!= ',' && *s
!= ']') s
++;
1282 _dealloc_hdf_attr(attr
);
1283 return nerr_raise(NERR_PARSE
, "Malformed attribute specification: %s", *str
);
1292 ha
= (HDF_ATTR
*) calloc (1, sizeof(HDF_ATTR
));
1295 _dealloc_hdf_attr(attr
);
1297 return nerr_raise(NERR_NOMEM
, "Unable to load attributes: %s", s
);
1299 if (*attr
== NULL
) *attr
= ha
;
1300 ha
->key
= _strndup(k
, k_l
);
1302 ha
->value
= _strndup(v
, v_l
);
1304 ha
->value
= strdup("");
1305 if (ha
->key
== NULL
|| ha
->value
== NULL
)
1307 _dealloc_hdf_attr(attr
);
1309 return nerr_raise(NERR_NOMEM
, "Unable to load attributes: %s", s
);
1311 if (hal
!= NULL
) hal
->next
= ha
;
1323 _dealloc_hdf_attr(attr
);
1324 return nerr_raise(NERR_PARSE
, "Malformed attribute specification: %s", *str
);
1330 #define INCLUDE_ERROR -1
1331 #define INCLUDE_IGNORE -2
1332 #define INCLUDE_FILE 0
1333 #define INCLUDE_MAX_DEPTH 50
1335 static NEOERR
* _hdf_read_string (HDF
*hdf
, const char **str
, NEOSTRING
*line
,
1336 const char *path
, int *lineno
,
1337 int include_handle
, int expect_end_brace
) {
1342 HDF_ATTR
*attr
= NULL
;
1344 while (**str
!= '\0')
1346 /* Reset string length, but don't free the reserved buffer */
1348 err
= _copy_line_advance(str
, line
);
1349 if (err
) return nerr_pass(err
);
1354 if ((!strncmp(s
, "#include ", 9) || !strncmp(s
, "-include ", 9)) && include_handle
!= INCLUDE_IGNORE
)
1356 int required
= !strncmp(s
, "#include ", 9);
1357 if (include_handle
== INCLUDE_ERROR
)
1359 return nerr_raise (NERR_PARSE
,
1360 "[%d]: #include not supported in string parse",
1363 else if (include_handle
< INCLUDE_MAX_DEPTH
)
1367 name
= neos_strip(s
);
1369 if (name
[0] == '"' && name
[l
-1] == '"')
1374 char fullpath
[PATH_MAX
];
1375 if (name
[0] != '/') {
1376 memset(fullpath
, 0, PATH_MAX
);
1378 char *p
= strrchr(path
, '/');
1381 memset(pwd
, 0, PATH_MAX
);
1382 getcwd(pwd
, PATH_MAX
);
1383 snprintf(fullpath
, PATH_MAX
, "%s/%s", pwd
, name
);
1385 int dir_len
= p
- path
+ 1;
1386 snprintf(fullpath
, PATH_MAX
, "%s", path
);
1387 snprintf(fullpath
+ dir_len
, PATH_MAX
- dir_len
, "%s", name
);
1391 err
= hdf_read_file_internal(hdf
, name
, include_handle
+ 1);
1392 if (err
!= STATUS_OK
&& required
)
1394 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1398 return nerr_raise (NERR_MAX_RECURSION
,
1399 "[%d]: Too many recursion levels.",
1404 else if (s
[0] == '#')
1408 else if (s
[0] == '}') /* up */
1413 err
= nerr_raise(NERR_PARSE
,
1414 "[%s:%d] Trailing garbage on line following }: %s", path
, *lineno
,
1422 /* Valid hdf name is [0-9a-zA-Z_.*\]+ */
1423 int splice
= *s
== '@';
1426 while (*s
&& (isalnum(*s
) || *s
== '_' || *s
== '.' || *s
== '*' || *s
== '\\')) s
++;
1430 static int counter
= 0;
1433 for (p
= name
; p
< s
&& i
< 200; p
++) {
1437 i
+= snprintf(num
+ i
, 256 - i
, "%d", counter
++);
1443 if (s
[0] == '[') /* attributes */
1446 name
= neos_strip(name
);
1448 err
= parse_attr(&s
, &attr
);
1451 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1456 name
= neos_strip(name
);
1457 HDF
*h
= hdf_get_obj(hdf
->top
, name
, &err
);
1458 if (err
!= STATUS_OK
) {
1459 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1462 HDF
*c
= hdf_obj_child(h
, &err
);
1463 if (err
!= STATUS_OK
) {
1464 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1467 err
= hdf_copy (hdf
, hdf_obj_name(c
), c
);
1468 if (err
!= STATUS_OK
) break;
1469 c
= hdf_obj_next(c
);
1472 if (err
!= STATUS_OK
)
1474 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1476 } else if (s
[0] == '=') /* assignment */
1479 name
= neos_strip(name
);
1481 value
= neos_strip(s
);
1482 err
= _set_value (hdf
, name
, value
, 1, 1, 0, attr
, NULL
);
1483 if (err
!= STATUS_OK
)
1485 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1488 else if (s
[0] == ':' && s
[1] == '=') /* copy */
1491 name
= neos_strip(name
);
1493 value
= neos_strip(s
);
1494 HDF
*h
= hdf_get_obj(hdf
->top
, value
, &err
);
1495 if (err
!= STATUS_OK
) {
1496 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1500 err
= nerr_raise(NERR_PARSE
,
1501 "[%s:%d] Failed to copy a node that is not loaded "
1502 "yet: %s", path
, *lineno
, value
);
1505 err
= hdf_copy(hdf
, name
, h
);
1506 if (err
!= STATUS_OK
)
1508 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1511 else if (s
[0] == '!' && s
[1] == '=') /* exec */
1514 name
= neos_strip(name
);
1516 value
= neos_strip(s
);
1519 FILE *f
= _popen(value
, "r");
1521 FILE *f
= popen(value
, "r");
1525 err
= nerr_raise(NERR_PARSE
,
1526 "[%s:%d] Failed to exec specified command: %s",
1527 path
, *lineno
, line
->buf
);
1530 char *content
= _read_file(f
);
1532 int len
= strlen(content
);
1533 if (len
> 0 && content
[len
- 1] == '\n') {
1534 content
[len
- 1] = '\0'; // remove \n artifact
1536 err
= _set_value (hdf
, name
, content
, 1, 1, 0, attr
, NULL
);
1539 if (err
!= STATUS_OK
)
1541 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1544 else if (s
[0] == ':') /* link */
1547 name
= neos_strip(name
);
1549 value
= neos_strip(s
);
1550 err
= _set_value (hdf
, name
, value
, 1, 1, 1, attr
, NULL
);
1551 if (err
!= STATUS_OK
)
1553 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1556 else if (s
[0] == '{') /* deeper */
1559 name
= neos_strip(name
);
1560 lower
= hdf_get_obj (hdf
, name
, &err
);
1563 err
= _set_value (hdf
, name
, NULL
, 1, 1, 0, attr
, &lower
);
1567 err
= _set_value (lower
, NULL
, lower
->value
, 1, 1, 0, attr
, NULL
);
1569 if (err
!= STATUS_OK
)
1571 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1573 err
= _hdf_read_string (lower
, str
, line
, path
, lineno
, include_handle
,
1575 if (err
!= STATUS_OK
)
1577 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1580 else if (s
[0] == '<' && s
[1] == '<') /* multi-line assignment */
1588 name
= neos_strip(name
);
1590 value
= neos_strip(s
);
1594 err
= nerr_raise(NERR_PARSE
,
1595 "[%s:%d] No multi-assignment terminator given: %s", path
, *lineno
,
1599 m
= (char *) malloc (mmax
* sizeof(char));
1602 return nerr_raise(NERR_NOMEM
,
1603 "[%s:%d] Unable to allocate memory for multi-line assignment to %s",
1604 path
, *lineno
, name
);
1606 while (_copy_line (str
, m
+msize
, mmax
-msize
) != 0)
1609 if (!strncmp(value
, m
+msize
, l
) && isspace(m
[msize
+l
]))
1614 msize
+= strlen(m
+msize
);
1615 if (msize
+ l
+ 10 > mmax
)
1619 new_ptr
= realloc (m
, mmax
* sizeof(char));
1620 if (new_ptr
== NULL
)
1623 return nerr_raise(NERR_NOMEM
,
1624 "[%s:%d] Unable to allocate memory for multi-line assignment to %s: size=%d",
1625 path
, *lineno
, name
, mmax
);
1627 m
= (char *) new_ptr
;
1630 err
= _set_value (hdf
, name
, m
, 0, 1, 0, attr
, NULL
);
1631 if (err
!= STATUS_OK
)
1634 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1640 err
= nerr_raise(NERR_PARSE
, "[%s:%d] Unable to parse line %s", path
,
1641 *lineno
, line
->buf
);
1646 if (expect_end_brace
) {
1647 err
= nerr_raise(NERR_PARSE
, "[%s:%d] Missing matching }", path
, *lineno
);
1653 NEOERR
* hdf_read_string (HDF
*hdf
, const char *str
)
1659 err
= _hdf_read_string(hdf
, &str
, &line
, "<string>", &lineno
, INCLUDE_ERROR
,
1661 string_clear(&line
);
1662 return nerr_pass(err
);
1665 /* The search path is part of the HDF by convention */
1666 NEOERR
* hdf_search_path (HDF
*hdf
, const char *path
, char *full
, int full_len
)
1670 NEOERR
* err
= STATUS_OK
;
1672 paths
= hdf_get_child (hdf
, "hdf.loadpaths", &err
);
1673 if (err
!= STATUS_OK
) return err
;
1675 for (; paths
; paths
= hdf_obj_next (paths
))
1677 char* value
= hdf_obj_value(paths
, &err
);
1678 if (err
!= STATUS_OK
) return err
;
1679 snprintf (full
, full_len
, "%s/%s", value
, path
);
1681 if (stat (full
, &s
) == -1)
1683 if (errno
!= ENOENT
)
1684 return nerr_raise_errno (NERR_SYSTEM
, "Stat of %s failed", full
);
1692 strncpy (full
, path
, full_len
);
1693 full
[full_len
> 0 ? full_len
-1 : full_len
] = '\0';
1695 if (stat (full
, &s
) == -1)
1697 if (errno
!= ENOENT
)
1698 return nerr_raise_errno (NERR_SYSTEM
, "Stat of %s failed", full
);
1700 else return STATUS_OK
;
1702 return nerr_raise (NERR_NOT_FOUND
, "Path %s not found", path
);
1705 static NEOERR
* hdf_read_file_internal (HDF
*hdf
, const char *path
,
1710 char fpath
[PATH_BUF_SIZE
];
1712 const char *ptr
= NULL
;
1718 return nerr_raise(NERR_ASSERT
, "Can't read NULL file");
1721 err
= hdf_search_path (hdf
, path
, fpath
, PATH_BUF_SIZE
);
1722 if (err
!= STATUS_OK
) return nerr_pass(err
);
1726 err
= ne_load_file (path
, &ibuf
);
1727 if (err
) return nerr_pass(err
);
1730 err
= _hdf_read_string(hdf
, &ptr
, &line
, path
, &lineno
, include_handle
, 0);
1732 string_clear(&line
);
1733 return nerr_pass(err
);
1736 NEOERR
* hdf_read_file (HDF
*hdf
, const char *path
)
1739 err
= hdf_read_file_internal (hdf
, path
, INCLUDE_FILE
);
1740 return nerr_pass(err
);