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 static int _walk_hdf (HDF
*hdf
, const char *name
, HDF
**node
)
244 if (hdf
== NULL
) return -1;
245 if (name
== NULL
|| name
[0] == '\0')
253 r
= _walk_hdf (hdf
->top
, hdf
->value
, &hp
);
273 x
= (s
== NULL
) ? strlen(n
) : s
- n
;
277 if (parent
&& parent
->hash
)
279 hash_key
.name
= (char *)n
;
280 hash_key
.name_len
= x
;
281 hp
= ne_hash_lookup(parent
->hash
, &hash_key
);
287 if (hp
->name
&& (x
== hp
->name_len
) && !strncmp(hp
->name
, n
, x
))
301 if (s
== NULL
) break;
305 r
= _walk_hdf (hp
->top
, hp
->value
, &hp
);
319 x
= (s
== NULL
) ? strlen(n
) : s
- n
;
323 return _walk_hdf (hp
->top
, hp
->value
, node
);
330 HDF
* hdf_get_obj (HDF
*hdf
, const char *name
)
334 _walk_hdf(hdf
, name
, &obj
);
338 HDF
* hdf_get_child (HDF
*hdf
, const char *name
)
341 _walk_hdf(hdf
, name
, &obj
);
342 if (obj
!= NULL
) return obj
->child
;
346 void hdf_set_visited (HDF
*hdf
, int visited
) {
347 if (hdf
) hdf
->visited
= visited
;
350 int hdf_is_visited (HDF
*hdf
) {
351 return hdf
? hdf
->visited
: 0;
354 HDF
* hdf_obj_child (HDF
*hdf
)
357 if (hdf
== NULL
) return NULL
;
360 if (_walk_hdf(hdf
->top
, hdf
->value
, &obj
))
367 HDF
* hdf_obj_next (HDF
*hdf
)
369 if (hdf
== NULL
) return NULL
;
373 char* hdf_obj_name (HDF
*hdf
)
375 if (hdf
== NULL
) return NULL
;
379 char* hdf_obj_value (HDF
*hdf
)
383 if (hdf
== NULL
) return NULL
;
384 while (hdf
->link
&& count
< 100)
386 if (_walk_hdf (hdf
->top
, hdf
->value
, &hdf
))
393 void _merge_attr (HDF_ATTR
*dest
, HDF_ATTR
*src
)
408 if (!strcmp(da
->key
, sa
->key
))
410 if (da
->value
) free(da
->value
);
411 da
->value
= sa
->value
;
423 if (src
== sa
) src
= sa
->next
;
424 ld
->next
->next
= NULL
;
433 _dealloc_hdf_attr(&src
);
436 NEOERR
* _hdf_hash_level(HDF
*hdf
)
441 err
= ne_hash_init(&(hdf
->hash
), hash_hdf_hash
, hash_hdf_comp
);
442 if (err
) return nerr_pass(err
);
447 err
= ne_hash_insert(hdf
->hash
, child
, child
);
448 if (err
) return nerr_pass(err
);
454 static NEOERR
* _set_value (HDF
*hdf
, const char *name
, const char *value
,
455 int dupl
, int wf
, int lnk
, HDF_ATTR
*attr
,
462 const char *s
= name
;
463 const char *n
= name
;
466 if (set_node
!= NULL
) *set_node
= NULL
;
469 return nerr_raise(NERR_ASSERT
, "Unable to set %s on NULL hdf", name
);
472 /* HACK: allow setting of this node by passing an empty name */
473 if (name
== NULL
|| name
[0] == '\0')
475 /* handle setting attr first */
476 if (hdf
->attr
== NULL
)
482 _merge_attr(hdf
->attr
, attr
);
485 if (lnk
) hdf
->link
= 1;
487 /* if we're setting ourselves to ourselves... */
488 if (hdf
->value
== value
)
490 if (set_node
!= NULL
) *set_node
= hdf
;
493 if (hdf
->alloc_value
)
500 hdf
->alloc_value
= 0;
505 hdf
->alloc_value
= 1;
506 hdf
->value
= strdup(value
);
507 if (hdf
->value
== NULL
)
508 return nerr_raise (NERR_NOMEM
, "Unable to duplicate value %s for %s",
513 hdf
->alloc_value
= wf
;
514 hdf
->value
= (char *)value
;
516 if (set_node
!= NULL
) *set_node
= hdf
;
522 x
= (s
!= NULL
) ? s
- n
: strlen(n
);
525 return nerr_raise(NERR_ASSERT
, "Unable to set Empty component %s", name
);
530 char *new_name
= (char *) malloc(strlen(hdf
->value
) + 1 + strlen(name
) + 1);
531 if (new_name
== NULL
)
533 return nerr_raise(NERR_NOMEM
, "Unable to allocate memory");
535 strcpy(new_name
, hdf
->value
);
536 strcat(new_name
, ".");
537 strcat(new_name
, name
);
538 err
= _set_value (hdf
->top
, new_name
, value
, dupl
, wf
, lnk
, attr
, set_node
);
540 return nerr_pass(err
);
549 /* examine cache to see if we have a match */
554 if ((hs
== NULL
&& hp
== hn
->child
) || (hs
&& hs
->next
== hp
))
556 if (hp
&& hp
->name
&& (x
== hp
->name_len
) && !strncmp (hp
->name
, n
, x
))
565 /* Look for a matching node at this level */
566 if (hn
->hash
!= NULL
)
568 hash_key
.name
= (char *)n
;
569 hash_key
.name_len
= x
;
570 hp
= ne_hash_lookup(hn
->hash
, &hash_key
);
577 if (hp
->name
&& (x
== hp
->name_len
) && !strncmp(hp
->name
, n
, x
))
587 /* save in cache any value we found */
597 /* If there was no matching node at this level, we need to
598 * allocate an intersitial node (or the actual node if we're
599 * at the last part of the HDF name) */
603 err
= _alloc_hdf (&hp
, n
, x
, NULL
, 0, 0, hdf
->top
);
607 err
= _alloc_hdf (&hp
, n
, x
, value
, dupl
, wf
, hdf
->top
);
608 if (lnk
) hp
->link
= 1;
612 if (err
!= STATUS_OK
)
613 return nerr_pass (err
);
614 if (hn
->child
== NULL
)
620 /* This is the point at which we convert to a hash table
621 * at this level, if we're over the count */
622 if (count
> FORCE_HASH_AT
&& hn
->hash
== NULL
)
624 err
= _hdf_hash_level(hn
);
625 if (err
) return nerr_pass(err
);
627 else if (hn
->hash
!= NULL
)
629 err
= ne_hash_insert(hn
->hash
, hp
, hp
);
630 if (err
) return nerr_pass(err
);
635 /* If there is a matching node and we're at the end of the HDF
636 * name, then we update the value of the node */
637 /* handle setting attr first */
638 if (hp
->attr
== NULL
)
644 _merge_attr(hp
->attr
, attr
);
646 if (hp
->value
!= value
)
661 hp
->value
= strdup(value
);
662 if (hp
->value
== NULL
)
663 return nerr_raise (NERR_NOMEM
, "Unable to duplicate value %s for %s",
668 hp
->alloc_value
= wf
;
669 hp
->value
= (char *)value
;
672 if (lnk
) hp
->link
= 1;
677 char *new_name
= (char *) malloc(strlen(hp
->value
) + strlen(s
) + 1);
678 if (new_name
== NULL
)
680 return nerr_raise(NERR_NOMEM
, "Unable to allocate memory");
682 strcpy(new_name
, hp
->value
);
684 err
= _set_value (hdf
->top
, new_name
, value
, dupl
, wf
, lnk
, attr
, set_node
);
686 return nerr_pass(err
);
688 /* At this point, we're done if there is not more HDF name space to
692 /* Otherwise, we need to find the next part of the namespace */
695 x
= (s
!= NULL
) ? s
- n
: strlen(n
);
698 return nerr_raise(NERR_ASSERT
, "Unable to set Empty component %s", name
);
702 if (set_node
!= NULL
) *set_node
= hp
;
706 NEOERR
* hdf_set_value (HDF
*hdf
, const char *name
, const char *value
)
708 return nerr_pass(_set_value (hdf
, name
, value
, 1, 1, 0, NULL
, NULL
));
711 NEOERR
* hdf_get_node (HDF
*hdf
, const char *name
, HDF
**ret
)
713 _walk_hdf(hdf
, name
, ret
);
716 return nerr_pass(_set_value (hdf
, name
, NULL
, 0, 1, 0, NULL
, ret
));
721 NEOERR
* hdf_remove_tree (HDF
*hdf
, const char *name
)
724 HDF
*lp
= NULL
, *ln
= NULL
; /* last parent, last node */
726 const char *s
= name
;
727 const char *n
= name
;
729 if (hdf
== NULL
) return STATUS_OK
;
742 x
= (s
== NULL
) ? strlen(n
) : s
- n
;
748 if (hp
->name
&& (x
== hp
->name_len
) && !strncmp(hp
->name
, n
, x
))
762 if (s
== NULL
) break;
769 x
= (s
== NULL
) ? strlen(n
) : s
- n
;
772 if (lp
->hash
!= NULL
)
774 ne_hash_remove(lp
->hash
, hp
);
779 /* check to see if we are the last parent's last_child, if so
780 * repoint so hash table inserts will go to the right place */
781 if (hp
== lp
->last_child
)
787 lp
->child
= hp
->next
;
795 static NEOERR
* _copy_attr (HDF_ATTR
**dest
, HDF_ATTR
*src
)
797 HDF_ATTR
*copy
, *last
= NULL
;
802 copy
= (HDF_ATTR
*)malloc(sizeof(HDF_ATTR
));
805 _dealloc_hdf_attr(dest
);
806 return nerr_raise(NERR_NOMEM
, "Unable to allocate copy of HDF_ATTR");
808 copy
->key
= strdup(src
->key
);
809 copy
->value
= strdup(src
->value
);
811 if ((copy
->key
== NULL
) || (copy
->value
== NULL
))
813 _dealloc_hdf_attr(dest
);
814 return nerr_raise(NERR_NOMEM
, "Unable to allocate copy of HDF_ATTR");
829 static NEOERR
* _copy_nodes (HDF
*dest
, HDF
*src
)
831 NEOERR
*err
= STATUS_OK
;
838 err
= _copy_attr(&attr_copy
, st
->attr
);
839 if (err
) return nerr_pass(err
);
840 err
= _set_value(dest
, st
->name
, st
->value
, 1, 1, st
->link
, attr_copy
, &dt
);
842 _dealloc_hdf_attr(&attr_copy
);
843 return nerr_pass(err
);
847 err
= _copy_nodes (dt
, st
);
848 if (err
) return nerr_pass(err
);
855 NEOERR
* hdf_copy (HDF
*dest
, const char *name
, HDF
*src
)
861 if (_walk_hdf(dest
, name
, &node
) == -1)
863 err
= _copy_attr(&attr_copy
, src
->attr
);
864 if (err
) return nerr_pass(err
);
865 err
= _set_value (dest
, name
, src
->value
, 1, 1, src
->link
, attr_copy
,
868 _dealloc_hdf_attr(&attr_copy
);
869 return nerr_pass(err
);
872 return nerr_pass (_copy_nodes (node
, src
));
875 /* BUG: currently, this only prints something if there is a value...
876 * but we now allow attributes on nodes with no value... */
878 static void gen_ml_break(char *ml
, size_t len
)
884 nlen
= 2 + neo_rand(len
-5);
891 ml
[x
++] = ('A' + neo_rand(26));
898 typedef NEOERR
*(*DUMPF_CB
)(void *rock
, const char *fmt
, ...);
900 static NEOERR
*_fp_dump_cb (void *rock
, const char *fmt
, ...)
902 FILE *fp
= (FILE *)rock
;
906 vfprintf(fp
, fmt
, ap
);
911 static NEOERR
*_string_dump_cb (void *rock
, const char *fmt
, ...)
914 NEOSTRING
*str
= (NEOSTRING
*)rock
;
918 err
= string_appendvf(str
, fmt
, ap
);
920 return nerr_pass(err
);
923 #define DUMP_TYPE_DOTTED 0
924 #define DUMP_TYPE_COMPACT 1
925 #define DUMP_TYPE_PRETTY 2
927 static NEOERR
* hdf_dump_cb(HDF
*hdf
, const char *prefix
, int dtype
, int lvl
,
928 void *rock
, DUMPF_CB dump_cbf
)
932 char ml
[10] = "\nEOM\n";
933 int ml_len
= strlen(ml
);
936 if (dtype
== DUMP_TYPE_PRETTY
)
938 memset(whsp
, ' ', 256);
944 if (hdf
!= NULL
) hdf
= hdf
->child
;
951 if (hdf
->link
) op
= ':';
952 if (prefix
&& (dtype
== DUMP_TYPE_DOTTED
))
954 err
= dump_cbf(rock
, "%s.%s", prefix
, hdf
->name
);
958 err
= dump_cbf(rock
, "%s%s", whsp
, hdf
->name
);
960 if (err
) return nerr_pass (err
);
963 HDF_ATTR
*attr
= hdf
->attr
;
966 err
= dump_cbf(rock
, " [");
967 if (err
) return nerr_pass(err
);
971 if (attr
->value
== NULL
|| !strcmp(attr
->value
, "1"))
972 err
= dump_cbf(rock
, "%s", attr
->key
);
975 v
= repr_string_alloc(attr
->value
);
978 return nerr_raise(NERR_NOMEM
, "Unable to repr attr %s value %s", attr
->key
, attr
->value
);
979 err
= dump_cbf(rock
, "%s=%s", attr
->key
, v
);
982 if (err
) return nerr_pass(err
);
985 err
= dump_cbf(rock
, ", ");
986 if (err
) return nerr_pass(err
);
990 err
= dump_cbf(rock
, "] ");
991 if (err
) return nerr_pass(err
);
993 if (strchr (hdf
->value
, '\n'))
995 int vlen
= strlen(hdf
->value
);
997 while (strstr(hdf
->value
, ml
) || ((vlen
> ml_len
) && !strncmp(hdf
->value
+ vlen
- ml_len
+ 1, ml
, strlen(ml
) - 1)))
999 gen_ml_break(ml
, sizeof(ml
));
1000 ml_len
= strlen(ml
);
1002 if (hdf
->value
[strlen(hdf
->value
)-1] != '\n')
1003 err
= dump_cbf(rock
, " << %s%s%s", ml
+1, hdf
->value
, ml
);
1005 err
= dump_cbf(rock
, " << %s%s%s", ml
+1, hdf
->value
, ml
+1);
1009 err
= dump_cbf(rock
, " %c %s\n", op
, hdf
->value
);
1011 if (err
) return nerr_pass (err
);
1015 if (prefix
&& (dtype
== DUMP_TYPE_DOTTED
))
1017 p
= (char *) malloc (strlen(hdf
->name
) + strlen(prefix
) + 2);
1018 sprintf (p
, "%s.%s", prefix
, hdf
->name
);
1019 err
= hdf_dump_cb (hdf
, p
, dtype
, lvl
+1, rock
, dump_cbf
);
1024 if (hdf
->name
&& (dtype
!= DUMP_TYPE_DOTTED
))
1026 err
= dump_cbf(rock
, "%s%s {\n", whsp
, hdf
->name
);
1027 if (err
) return nerr_pass (err
);
1028 err
= hdf_dump_cb (hdf
, hdf
->name
, dtype
, lvl
+1, rock
, dump_cbf
);
1029 if (err
) return nerr_pass (err
);
1030 err
= dump_cbf(rock
, "%s}\n", whsp
);
1034 err
= hdf_dump_cb (hdf
, hdf
->name
, dtype
, lvl
+1, rock
, dump_cbf
);
1037 if (err
) return nerr_pass (err
);
1044 NEOERR
* hdf_dump_str (HDF
*hdf
, const char *prefix
, int dtype
, NEOSTRING
*str
)
1046 return nerr_pass(hdf_dump_cb(hdf
, prefix
, dtype
, 0, str
, _string_dump_cb
));
1049 NEOERR
* hdf_dump_format (HDF
*hdf
, int lvl
, FILE *fp
)
1051 return nerr_pass(hdf_dump_cb(hdf
, "", DUMP_TYPE_PRETTY
, 0, fp
, _fp_dump_cb
));
1054 NEOERR
*hdf_write_file (HDF
*hdf
, const char *path
)
1059 fp
= fopen(path
, "w");
1061 return nerr_raise_errno (NERR_IO
, "Unable to open %s for writing", path
);
1063 err
= hdf_dump_format (hdf
, 0, fp
);
1070 return nerr_pass(err
);
1073 NEOERR
*hdf_write_string (HDF
*hdf
, char **s
)
1082 err
= hdf_dump_str (hdf
, NULL
, 2, &str
);
1085 string_clear (&str
);
1086 return nerr_pass(err
);
1088 if (str
.buf
== NULL
)
1091 if (*s
== NULL
) return nerr_raise(NERR_NOMEM
, "Unable to allocate empty string");
1102 #define SKIPWS(s) while (*s && isspace(*s)) s++;
1104 static int _copy_line (const char **s
, char *buf
, size_t buf_len
)
1107 const char *st
= *s
;
1109 while (*st
&& x
< buf_len
-1)
1112 if (*st
++ == '\n') break;
1120 /* Copy the characters in the file (up to the next newline) into line
1121 * and advance s to the next line */
1122 static NEOERR
*_copy_line_advance(const char **s
, NEOSTRING
*line
)
1126 const char *st
= *s
;
1129 nl
= strchr(st
, '\n');
1133 err
= string_appendn(line
, st
, x
);
1134 if (err
) return nerr_pass(err
);
1140 err
= string_appendn(line
, st
, x
);
1141 if (err
) return nerr_pass(err
);
1148 char *_strndup(const char *s
, int len
) {
1151 if (s
== NULL
) return NULL
;
1152 dupl
= (char *) malloc(len
+1);
1153 if (dupl
== NULL
) return NULL
;
1154 for (x
= 0; x
< len
&& s
[x
]; x
++)
1163 /* attributes are of the form [key1, key2, key3=value, key4="repr"] */
1164 static NEOERR
* parse_attr(char **str
, HDF_ATTR
**attr
)
1166 NEOERR
*err
= STATUS_OK
;
1172 HDF_ATTR
*ha
, *hal
= NULL
;
1177 while (*s
&& *s
!= ']')
1183 while (*s
&& isalnum(*s
)) s
++;
1185 if (*s
== '\0' || k_l
== 0)
1187 _dealloc_hdf_attr(attr
);
1188 return nerr_raise(NERR_PARSE
, "Malformed attribute specification: %s", *str
);
1198 while (*s
&& *s
!= '"')
1202 if (isdigit(*(s
+1)))
1206 if (isdigit(*(s
+1)))
1209 c
= (c
* 8) + (*s
- '0');
1210 if (isdigit(*(s
+1)))
1213 c
= (c
* 8) + (*s
- '0');
1220 if (*s
== 'n') c
= '\n';
1221 else if (*s
== 't') c
= '\t';
1222 else if (*s
== 'r') c
= '\r';
1225 err
= string_append_char(&buf
, c
);
1229 err
= string_append_char(&buf
, *s
);
1234 _dealloc_hdf_attr(attr
);
1235 return nerr_pass(err
);
1241 _dealloc_hdf_attr(attr
);
1243 return nerr_raise(NERR_PARSE
, "Malformed attribute specification: %s", *str
);
1252 while (*s
&& *s
!= ' ' && *s
!= ',' && *s
!= ']') s
++;
1255 _dealloc_hdf_attr(attr
);
1256 return nerr_raise(NERR_PARSE
, "Malformed attribute specification: %s", *str
);
1265 ha
= (HDF_ATTR
*) calloc (1, sizeof(HDF_ATTR
));
1268 _dealloc_hdf_attr(attr
);
1270 return nerr_raise(NERR_NOMEM
, "Unable to load attributes: %s", s
);
1272 if (*attr
== NULL
) *attr
= ha
;
1273 ha
->key
= _strndup(k
, k_l
);
1275 ha
->value
= _strndup(v
, v_l
);
1277 ha
->value
= strdup("");
1278 if (ha
->key
== NULL
|| ha
->value
== NULL
)
1280 _dealloc_hdf_attr(attr
);
1282 return nerr_raise(NERR_NOMEM
, "Unable to load attributes: %s", s
);
1284 if (hal
!= NULL
) hal
->next
= ha
;
1296 _dealloc_hdf_attr(attr
);
1297 return nerr_raise(NERR_PARSE
, "Malformed attribute specification: %s", *str
);
1303 #define INCLUDE_ERROR -1
1304 #define INCLUDE_IGNORE -2
1305 #define INCLUDE_FILE 0
1306 #define INCLUDE_MAX_DEPTH 50
1308 static NEOERR
* _hdf_read_string (HDF
*hdf
, const char **str
, NEOSTRING
*line
,
1309 const char *path
, int *lineno
,
1310 int include_handle
, int expect_end_brace
) {
1315 HDF_ATTR
*attr
= NULL
;
1317 while (**str
!= '\0')
1319 /* Reset string length, but don't free the reserved buffer */
1321 err
= _copy_line_advance(str
, line
);
1322 if (err
) return nerr_pass(err
);
1327 if ((!strncmp(s
, "#include ", 9) || !strncmp(s
, "-include ", 9)) && include_handle
!= INCLUDE_IGNORE
)
1329 int required
= !strncmp(s
, "#include ", 9);
1330 if (include_handle
== INCLUDE_ERROR
)
1332 return nerr_raise (NERR_PARSE
,
1333 "[%d]: #include not supported in string parse",
1336 else if (include_handle
< INCLUDE_MAX_DEPTH
)
1340 name
= neos_strip(s
);
1342 if (name
[0] == '"' && name
[l
-1] == '"')
1347 char fullpath
[PATH_MAX
];
1348 if (name
[0] != '/') {
1349 memset(fullpath
, 0, PATH_MAX
);
1351 char *p
= strrchr(path
, '/');
1354 memset(pwd
, 0, PATH_MAX
);
1355 getcwd(pwd
, PATH_MAX
);
1356 snprintf(fullpath
, PATH_MAX
, "%s/%s", pwd
, name
);
1358 int dir_len
= p
- path
+ 1;
1359 snprintf(fullpath
, PATH_MAX
, "%s", path
);
1360 snprintf(fullpath
+ dir_len
, PATH_MAX
- dir_len
, "%s", name
);
1364 err
= hdf_read_file_internal(hdf
, name
, include_handle
+ 1);
1365 if (err
!= STATUS_OK
&& required
)
1367 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1371 return nerr_raise (NERR_MAX_RECURSION
,
1372 "[%d]: Too many recursion levels.",
1377 else if (s
[0] == '#')
1381 else if (s
[0] == '}') /* up */
1386 err
= nerr_raise(NERR_PARSE
,
1387 "[%s:%d] Trailing garbage on line following }: %s", path
, *lineno
,
1395 /* Valid hdf name is [0-9a-zA-Z_.*\]+ */
1396 int splice
= *s
== '@';
1399 while (*s
&& (isalnum(*s
) || *s
== '_' || *s
== '.' || *s
== '*' || *s
== '\\')) s
++;
1403 static int counter
= 0;
1406 for (p
= name
; p
< s
&& i
< 200; p
++) {
1410 i
+= snprintf(num
+ i
, 256 - i
, "%d", counter
++);
1416 if (s
[0] == '[') /* attributes */
1419 name
= neos_strip(name
);
1421 err
= parse_attr(&s
, &attr
);
1424 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1429 name
= neos_strip(name
);
1430 HDF
*h
= hdf_get_obj(hdf
->top
, name
);
1432 HDF
*c
= hdf_obj_child(h
);
1434 err
= hdf_copy (hdf
, hdf_obj_name(c
), c
);
1435 if (err
!= STATUS_OK
) break;
1436 c
= hdf_obj_next(c
);
1439 if (err
!= STATUS_OK
)
1441 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1443 } else if (s
[0] == '=') /* assignment */
1446 name
= neos_strip(name
);
1448 value
= neos_strip(s
);
1449 err
= _set_value (hdf
, name
, value
, 1, 1, 0, attr
, NULL
);
1450 if (err
!= STATUS_OK
)
1452 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1455 else if (s
[0] == ':' && s
[1] == '=') /* copy */
1458 name
= neos_strip(name
);
1460 value
= neos_strip(s
);
1461 HDF
*h
= hdf_get_obj(hdf
->top
, value
);
1464 err
= nerr_raise(NERR_PARSE
,
1465 "[%s:%d] Failed to copy a node that is not loaded "
1466 "yet: %s", path
, *lineno
, value
);
1469 err
= hdf_copy(hdf
, name
, h
);
1470 if (err
!= STATUS_OK
)
1472 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1475 else if (s
[0] == '!' && s
[1] == '=') /* exec */
1478 name
= neos_strip(name
);
1480 value
= neos_strip(s
);
1483 FILE *f
= _popen(value
, "r");
1485 FILE *f
= popen(value
, "r");
1489 err
= nerr_raise(NERR_PARSE
,
1490 "[%s:%d] Failed to exec specified command: %s",
1491 path
, *lineno
, line
->buf
);
1494 char *content
= _read_file(f
);
1496 int len
= strlen(content
);
1497 if (len
> 0 && content
[len
- 1] == '\n') {
1498 content
[len
- 1] = '\0'; // remove \n artifact
1500 err
= _set_value (hdf
, name
, content
, 1, 1, 0, attr
, NULL
);
1503 if (err
!= STATUS_OK
)
1505 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1508 else if (s
[0] == ':') /* link */
1511 name
= neos_strip(name
);
1513 value
= neos_strip(s
);
1514 err
= _set_value (hdf
, name
, value
, 1, 1, 1, attr
, NULL
);
1515 if (err
!= STATUS_OK
)
1517 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1520 else if (s
[0] == '{') /* deeper */
1523 name
= neos_strip(name
);
1524 lower
= hdf_get_obj (hdf
, name
);
1527 err
= _set_value (hdf
, name
, NULL
, 1, 1, 0, attr
, &lower
);
1531 err
= _set_value (lower
, NULL
, lower
->value
, 1, 1, 0, attr
, NULL
);
1533 if (err
!= STATUS_OK
)
1535 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1537 err
= _hdf_read_string (lower
, str
, line
, path
, lineno
, include_handle
,
1539 if (err
!= STATUS_OK
)
1541 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1544 else if (s
[0] == '<' && s
[1] == '<') /* multi-line assignment */
1552 name
= neos_strip(name
);
1554 value
= neos_strip(s
);
1558 err
= nerr_raise(NERR_PARSE
,
1559 "[%s:%d] No multi-assignment terminator given: %s", path
, *lineno
,
1563 m
= (char *) malloc (mmax
* sizeof(char));
1566 return nerr_raise(NERR_NOMEM
,
1567 "[%s:%d] Unable to allocate memory for multi-line assignment to %s",
1568 path
, *lineno
, name
);
1570 while (_copy_line (str
, m
+msize
, mmax
-msize
) != 0)
1573 if (!strncmp(value
, m
+msize
, l
) && isspace(m
[msize
+l
]))
1578 msize
+= strlen(m
+msize
);
1579 if (msize
+ l
+ 10 > mmax
)
1583 new_ptr
= realloc (m
, mmax
* sizeof(char));
1584 if (new_ptr
== NULL
)
1587 return nerr_raise(NERR_NOMEM
,
1588 "[%s:%d] Unable to allocate memory for multi-line assignment to %s: size=%d",
1589 path
, *lineno
, name
, mmax
);
1591 m
= (char *) new_ptr
;
1594 err
= _set_value (hdf
, name
, m
, 0, 1, 0, attr
, NULL
);
1595 if (err
!= STATUS_OK
)
1598 return nerr_pass_ctx(err
, "In file %s:%d", path
, *lineno
);
1604 err
= nerr_raise(NERR_PARSE
, "[%s:%d] Unable to parse line %s", path
,
1605 *lineno
, line
->buf
);
1610 if (expect_end_brace
) {
1611 err
= nerr_raise(NERR_PARSE
, "[%s:%d] Missing matching }", path
, *lineno
);
1617 NEOERR
* hdf_read_string (HDF
*hdf
, const char *str
)
1623 err
= _hdf_read_string(hdf
, &str
, &line
, "<string>", &lineno
, INCLUDE_ERROR
,
1625 string_clear(&line
);
1626 return nerr_pass(err
);
1629 /* The search path is part of the HDF by convention */
1630 NEOERR
* hdf_search_path (HDF
*hdf
, const char *path
, char *full
, int full_len
)
1635 for (paths
= hdf_get_child (hdf
, "hdf.loadpaths");
1637 paths
= hdf_obj_next (paths
))
1639 snprintf (full
, full_len
, "%s/%s", hdf_obj_value(paths
), path
);
1641 if (stat (full
, &s
) == -1)
1643 if (errno
!= ENOENT
)
1644 return nerr_raise_errno (NERR_SYSTEM
, "Stat of %s failed", full
);
1652 strncpy (full
, path
, full_len
);
1653 if (stat (full
, &s
) == -1)
1655 if (errno
!= ENOENT
)
1656 return nerr_raise_errno (NERR_SYSTEM
, "Stat of %s failed", full
);
1658 else return STATUS_OK
;
1660 return nerr_raise (NERR_NOT_FOUND
, "Path %s not found", path
);
1663 static NEOERR
* hdf_read_file_internal (HDF
*hdf
, const char *path
,
1668 char fpath
[PATH_BUF_SIZE
];
1670 const char *ptr
= NULL
;
1676 return nerr_raise(NERR_ASSERT
, "Can't read NULL file");
1679 err
= hdf_search_path (hdf
, path
, fpath
, PATH_BUF_SIZE
);
1680 if (err
!= STATUS_OK
) return nerr_pass(err
);
1684 err
= ne_load_file (path
, &ibuf
);
1685 if (err
) return nerr_pass(err
);
1688 err
= _hdf_read_string(hdf
, &ptr
, &line
, path
, &lineno
, include_handle
, 0);
1690 string_clear(&line
);
1691 return nerr_pass(err
);
1694 NEOERR
* hdf_read_file (HDF
*hdf
, const char *path
)
1697 err
= hdf_read_file_internal (hdf
, path
, INCLUDE_FILE
);
1698 return nerr_pass(err
);