static inline void
ucl_set_err (struct ucl_chunk *chunk, int code, const char *str, UT_string **err)
{
- ucl_create_err (err, "error on line %d at column %d: '%s', character: '%c'",
- chunk->line, chunk->column, str, *chunk->pos);
+ if (isgraph (*chunk->pos)) {
+ ucl_create_err (err, "error on line %d at column %d: '%s', character: '%c'",
+ chunk->line, chunk->column, str, *chunk->pos);
+ }
+ else {
+ ucl_create_err (err, "error on line %d at column %d: '%s', character: '0x%02x'",
+ chunk->line, chunk->column, str, (int)*chunk->pos);
+ }
}
/**
*end_of_object = true;
return true;
}
+ else if (*p == '.') {
+ ucl_chunk_skipc (chunk, p);
+ parser->prev_state = parser->state;
+ parser->state = UCL_STATE_MACRO_NAME;
+ return true;
+ }
else {
/* Invalid identifier */
ucl_set_err (chunk, UCL_ESYNTAX, "key must begin with a letter", &parser->err);
bool next_key = false, end_of_object = false;
if (parser->top_obj == NULL) {
- obj = ucl_add_parser_stack (NULL, parser, false, 0);
+ if (*chunk->pos == '[') {
+ obj = ucl_add_parser_stack (NULL, parser, true, 0);
+ }
+ else {
+ obj = ucl_add_parser_stack (NULL, parser, false, 0);
+ }
parser->top_obj = obj;
+ parser->cur_obj = obj;
parser->state = UCL_STATE_INIT;
}
* if we got [ or { correspondingly or can just treat new data as
* a key of newly created object
*/
- obj = parser->top_obj;
+ obj = parser->cur_obj;
if (!ucl_skip_comments (parser)) {
parser->prev_state = parser->state;
parser->state = UCL_STATE_ERROR;
p = chunk->pos;
if (*p == '[') {
parser->state = UCL_STATE_VALUE;
- obj->type = UCL_ARRAY;
- ucl_hash_destroy (obj->value.ov, NULL);
- obj->value.av = NULL;
ucl_chunk_skipc (chunk, p);
}
else {
parser->state = UCL_STATE_KEY;
- obj->type = UCL_OBJECT;
if (*p == '{') {
ucl_chunk_skipc (chunk, p);
}
return false;
}
macro_len = ucl_expand_variable (parser, ¯o_escaped, macro_start, macro_len);
- parser->state = UCL_STATE_KEY;
+ parser->state = parser->prev_state;
if (macro_escaped == NULL) {
if (!macro->handler (macro_start, macro_len, macro->ud)) {
return false;
new->flags = flags;
+ /* Initial assumption about filevars */
+ ucl_parser_set_filevars (new, NULL, false);
+
return new;
}
ucl_parser_register_variable (struct ucl_parser *parser, const char *var,
const char *value)
{
- struct ucl_variable *new;
+ struct ucl_variable *new = NULL, *cur;
+
+ if (var == NULL) {
+ return;
+ }
- new = UCL_ALLOC (sizeof (struct ucl_variable));
- memset (new, 0, sizeof (struct ucl_variable));
- new->var = strdup (var);
- new->var_len = strlen (var);
- new->value = strdup (value);
- new->value_len = strlen (value);
+ /* Find whether a variable already exists */
+ LL_FOREACH (parser->variables, cur) {
+ if (strcmp (cur->var, var) == 0) {
+ new = cur;
+ break;
+ }
+ }
+
+ if (value == NULL) {
+
+ if (new != NULL) {
+ /* Remove variable */
+ LL_DELETE (parser->variables, new);
+ free (new->var);
+ free (new->value);
+ UCL_FREE (sizeof (struct ucl_variable), new);
+ }
+ else {
+ /* Do nothing */
+ return;
+ }
+ }
+ else {
+ if (new == NULL) {
+ new = UCL_ALLOC (sizeof (struct ucl_variable));
+ memset (new, 0, sizeof (struct ucl_variable));
+ new->var = strdup (var);
+ new->var_len = strlen (var);
+ new->value = strdup (value);
+ new->value_len = strlen (value);
- LL_PREPEND (parser->variables, new);
+ LL_PREPEND (parser->variables, new);
+ }
+ else {
+ free (new->value);
+ new->value = strdup (value);
+ new->value_len = strlen (value);
+ }
+ }
}
bool
#include "ucl_internal.h"
#include "ucl_chartable.h"
+#include <libgen.h> /* For dirname */
+
#ifdef HAVE_OPENSSL
#include <openssl/err.h>
#include <openssl/sha.h>
int fd;
struct stat st;
- if (stat (filename, &st) == -1) {
+ if (stat (filename, &st) == -1 || !S_ISREG (st.st_mode)) {
ucl_create_err (err, "cannot stat file %s: %s",
filename, strerror (errno));
return false;
size_t buflen = 0;
struct ucl_chunk *chunk;
char urlbuf[PATH_MAX];
+ int prev_state;
snprintf (urlbuf, sizeof (urlbuf), "%.*s", (int)len, data);
#endif
}
+ prev_state = parser->state;
+ parser->state = UCL_STATE_INIT;
+
res = ucl_parser_add_chunk (parser, buf, buflen);
if (res == true) {
/* Remove chunk from the stack */
UCL_FREE (sizeof (struct ucl_chunk), chunk);
}
}
+
+ parser->state = prev_state;
free (buf);
return res;
unsigned char *buf = NULL;
size_t buflen;
char filebuf[PATH_MAX], realbuf[PATH_MAX];
+ int prev_state;
snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data);
if (realpath (filebuf, realbuf) == NULL) {
#endif
}
+ ucl_parser_set_filevars (parser, realbuf, false);
+
+ prev_state = parser->state;
+ parser->state = UCL_STATE_INIT;
+
res = ucl_parser_add_chunk (parser, buf, buflen);
if (res == true) {
/* Remove chunk from the stack */
UCL_FREE (sizeof (struct ucl_chunk), chunk);
}
}
+
+ parser->state = prev_state;
+
if (buflen > 0) {
munmap (buf, buflen);
}
return ucl_include_url (data, len, parser, true);
}
+bool
+ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand)
+{
+ char realbuf[PATH_MAX], *curdir;
+
+ if (filename != NULL) {
+ if (need_expand) {
+ if (realpath (filename, realbuf) == NULL) {
+ return false;
+ }
+ }
+ else {
+ ucl_strlcpy (realbuf, filename, sizeof (realbuf));
+ }
+
+ /* Define variables */
+ ucl_parser_register_variable (parser, "FILENAME", realbuf);
+ curdir = dirname (realbuf);
+ ucl_parser_register_variable (parser, "CURDIR", curdir);
+ }
+ else {
+ /* Set everything from the current dir */
+ curdir = getcwd (realbuf, sizeof (realbuf));
+ ucl_parser_register_variable (parser, "FILENAME", "undef");
+ ucl_parser_register_variable (parser, "CURDIR", curdir);
+ }
+
+ return true;
+}
+
bool
ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
{
unsigned char *buf;
size_t len;
bool ret;
+ char realbuf[PATH_MAX];
+
+ if (realpath (filename, realbuf) == NULL) {
+ ucl_create_err (&parser->err, "cannot open file %s: %s",
+ filename,
+ strerror (errno));
+ return false;
+ }
- if (!ucl_fetch_file (filename, &buf, &len, &parser->err)) {
+ if (!ucl_fetch_file (realbuf, &buf, &len, &parser->err)) {
return false;
}
+ ucl_parser_set_filevars (parser, realbuf, false);
ret = ucl_parser_add_chunk (parser, buf, len);
if (len > 0) {