17908SN/A/* Copyright (c) 2013, Vsevolod Stakhov
27908SN/A * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
37908SN/A * All rights reserved.
47908SN/A *
57908SN/A * Redistribution and use in source and binary forms, with or without
67908SN/A * modification, are permitted provided that the following conditions are met:
77908SN/A *       * Redistributions of source code must retain the above copyright
87908SN/A *         notice, this list of conditions and the following disclaimer.
97908SN/A *       * Redistributions in binary form must reproduce the above copyright
107908SN/A *         notice, this list of conditions and the following disclaimer in the
117908SN/A *         documentation and/or other materials provided with the distribution.
127908SN/A *
137908SN/A * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
147908SN/A * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
157908SN/A * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
167908SN/A * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
177908SN/A * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
187908SN/A * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
197908SN/A * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
207908SN/A * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
217908SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
227908SN/A * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
237908SN/A */
247908SN/A
257908SN/A#include "ucl.h"
267908SN/A#include "ucl_internal.h"
277908SN/A#include "ucl_chartable.h"
287908SN/A#include "kvec.h"
297908SN/A#include <limits.h>
307908SN/A#include <stdarg.h>
317908SN/A#include <stdio.h> /* for snprintf */
327908SN/A
337908SN/A#ifndef _WIN32
347908SN/A#include <glob.h>
357908SN/A#include <sys/param.h>
367908SN/A#else
377908SN/A#ifndef NBBY
387908SN/A#define NBBY 8
397908SN/A#endif
407908SN/A#endif
417908SN/A
427908SN/A#ifdef HAVE_LIBGEN_H
437908SN/A#ifndef _WIN32
447908SN/A#  include <libgen.h> /* For dirname */
457908SN/A#endif
467908SN/A#endif
477908SN/A
487908SN/Atypedef kvec_t(ucl_object_t *) ucl_array_t;
497908SN/A
507908SN/A#define UCL_ARRAY_GET(ar, obj) ucl_array_t *ar = \
517908SN/A	(ucl_array_t *)((obj) != NULL ? (obj)->value.av : NULL)
527908SN/A
537908SN/A#ifdef HAVE_OPENSSL
547908SN/A#include <openssl/err.h>
557908SN/A#include <openssl/sha.h>
567908SN/A#include <openssl/rsa.h>
577908SN/A#include <openssl/ssl.h>
587908SN/A#include <openssl/evp.h>
597908SN/A#endif
607908SN/A
617908SN/A#ifdef CURL_FOUND
627908SN/A/* Seems to be broken */
637908SN/A#define CURL_DISABLE_TYPECHECK 1
647908SN/A#include <curl/curl.h>
657908SN/A#endif
667908SN/A#ifdef HAVE_FETCH_H
677908SN/A#include <fetch.h>
687908SN/A#endif
697908SN/A
707908SN/A#if defined(_MSC_VER)
717908SN/A#include <windows.h>
727908SN/A#include <io.h>
737908SN/A#include <direct.h>
747908SN/A
757908SN/A#ifndef PROT_READ
767908SN/A#define PROT_READ       1
777908SN/A#endif
787908SN/A#ifndef PROT_WRITE
797908SN/A#define PROT_WRITE      2
807908SN/A#endif
817908SN/A#ifndef PROT_READWRITE
827908SN/A#define PROT_READWRITE  3
837908SN/A#endif
847908SN/A#ifndef MAP_SHARED
857908SN/A#define MAP_SHARED      1
867908SN/A#endif
877908SN/A#ifndef MAP_PRIVATE
887908SN/A#define MAP_PRIVATE     2
897908SN/A#endif
907908SN/A#ifndef MAP_FAILED
917908SN/A#define MAP_FAILED      ((void *) -1)
927908SN/A#endif
937908SN/A
947908SN/A#define getcwd _getcwd
957908SN/A#define open _open
967908SN/A#define close _close
977908SN/A
987908SN/Astatic void *ucl_mmap(char *addr, size_t length, int prot, int access, int fd, off_t offset)
997908SN/A{
1007908SN/A	void *map = NULL;
1017908SN/A	HANDLE handle = INVALID_HANDLE_VALUE;
1027908SN/A
1037908SN/A	switch (prot) {
1047908SN/A	default:
1057908SN/A	case PROT_READ:
1067908SN/A		{
1077908SN/A			handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READONLY, 0, length, 0);
1087908SN/A			if (!handle) break;
1097908SN/A			map = (void *) MapViewOfFile(handle, FILE_MAP_READ, 0, 0, length);
1107908SN/A			CloseHandle(handle);
1117908SN/A			break;
1127908SN/A		}
1137908SN/A	case PROT_WRITE:
1147908SN/A		{
1157908SN/A			handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READWRITE, 0, length, 0);
1167908SN/A			if (!handle) break;
1177908SN/A			map = (void *) MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, length);
1187908SN/A			CloseHandle(handle);
1197908SN/A			break;
1207908SN/A		}
1217908SN/A	case PROT_READWRITE:
1227908SN/A		{
1237908SN/A			handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READWRITE, 0, length, 0);
1247908SN/A			if (!handle) break;
1257908SN/A			map = (void *) MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, length);
1267908SN/A			CloseHandle(handle);
127			break;
128		}
129	}
130	if (map == (void *) NULL) {
131		return (void *) MAP_FAILED;
132	}
133	return (void *) ((char *) map + offset);
134}
135
136static int ucl_munmap(void *map,size_t length)
137{
138	if (!UnmapViewOfFile(map)) {
139		return(-1);
140	}
141	return(0);
142}
143
144static char* ucl_realpath(const char *path, char *resolved_path)
145{
146	char *p;
147	char tmp[MAX_PATH + 1];
148	strncpy(tmp, path, sizeof(tmp)-1);
149	p = tmp;
150	while(*p) {
151		if (*p == '/') *p = '\\';
152		p++;
153	}
154	return _fullpath(resolved_path, tmp, MAX_PATH);
155}
156
157
158char *dirname(char *path)
159{
160	static char path_buffer[_MAX_PATH];
161	char drive[_MAX_DRIVE];
162	char dir[_MAX_DIR];
163	char fname[_MAX_FNAME];
164	char ext[_MAX_EXT];
165
166	_splitpath (path, drive, dir, fname, ext);
167	_makepath(path_buffer, drive, dir, NULL, NULL);
168
169	return path_buffer;
170}
171
172char *basename(char *path)
173{
174	static char path_buffer[_MAX_PATH];
175	char drive[_MAX_DRIVE];
176	char dir[_MAX_DIR];
177	char fname[_MAX_FNAME];
178	char ext[_MAX_EXT];
179
180	_splitpath(path, drive, dir, fname, ext);
181	_makepath(path_buffer, NULL, NULL, fname, ext);
182
183	return path_buffer;
184}
185#else
186#define ucl_mmap mmap
187#define ucl_munmap munmap
188#define ucl_realpath realpath
189#endif
190
191typedef void (*ucl_object_dtor) (ucl_object_t *obj);
192static void ucl_object_free_internal (ucl_object_t *obj, bool allow_rec,
193		ucl_object_dtor dtor);
194static void ucl_object_dtor_unref (ucl_object_t *obj);
195
196static void
197ucl_object_dtor_free (ucl_object_t *obj)
198{
199	if (obj->trash_stack[UCL_TRASH_KEY] != NULL) {
200		UCL_FREE (obj->hh.keylen, obj->trash_stack[UCL_TRASH_KEY]);
201	}
202	if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) {
203		UCL_FREE (obj->len, obj->trash_stack[UCL_TRASH_VALUE]);
204	}
205	/* Do not free ephemeral objects */
206	if ((obj->flags & UCL_OBJECT_EPHEMERAL) == 0) {
207		if (obj->type != UCL_USERDATA) {
208			UCL_FREE (sizeof (ucl_object_t), obj);
209		}
210		else {
211			struct ucl_object_userdata *ud = (struct ucl_object_userdata *)obj;
212			if (ud->dtor) {
213				ud->dtor (obj->value.ud);
214			}
215			UCL_FREE (sizeof (*ud), obj);
216		}
217	}
218}
219
220/*
221 * This is a helper function that performs exactly the same as
222 * `ucl_object_unref` but it doesn't iterate over elements allowing
223 * to use it for individual elements of arrays and multiple values
224 */
225static void
226ucl_object_dtor_unref_single (ucl_object_t *obj)
227{
228	if (obj != NULL) {
229#ifdef HAVE_ATOMIC_BUILTINS
230		unsigned int rc = __sync_sub_and_fetch (&obj->ref, 1);
231		if (rc == 0) {
232#else
233		if (--obj->ref == 0) {
234#endif
235			ucl_object_free_internal (obj, false, ucl_object_dtor_unref);
236		}
237	}
238}
239
240static void
241ucl_object_dtor_unref (ucl_object_t *obj)
242{
243	if (obj->ref == 0) {
244		ucl_object_dtor_free (obj);
245	}
246	else {
247		/* This may cause dtor unref being called one more time */
248		ucl_object_dtor_unref_single (obj);
249	}
250}
251
252static void
253ucl_object_free_internal (ucl_object_t *obj, bool allow_rec, ucl_object_dtor dtor)
254{
255	ucl_object_t *tmp, *sub;
256
257	while (obj != NULL) {
258		if (obj->type == UCL_ARRAY) {
259			UCL_ARRAY_GET (vec, obj);
260			unsigned int i;
261
262			if (vec != NULL) {
263				for (i = 0; i < vec->n; i ++) {
264					sub = kv_A (*vec, i);
265					if (sub != NULL) {
266						tmp = sub;
267						while (sub) {
268							tmp = sub->next;
269							dtor (sub);
270							sub = tmp;
271						}
272					}
273				}
274				kv_destroy (*vec);
275				UCL_FREE (sizeof (*vec), vec);
276			}
277			obj->value.av = NULL;
278		}
279		else if (obj->type == UCL_OBJECT) {
280			if (obj->value.ov != NULL) {
281				ucl_hash_destroy (obj->value.ov, (ucl_hash_free_func)dtor);
282			}
283			obj->value.ov = NULL;
284		}
285		tmp = obj->next;
286		dtor (obj);
287		obj = tmp;
288
289		if (!allow_rec) {
290			break;
291		}
292	}
293}
294
295void
296ucl_object_free (ucl_object_t *obj)
297{
298	ucl_object_free_internal (obj, true, ucl_object_dtor_free);
299}
300
301size_t
302ucl_unescape_json_string (char *str, size_t len)
303{
304	char *t = str, *h = str;
305	int i, uval;
306
307	if (len <= 1) {
308		return len;
309	}
310	/* t is target (tortoise), h is source (hare) */
311
312	while (len) {
313		if (*h == '\\') {
314			h ++;
315
316			if (len == 1) {
317				/*
318				 * If \ is last, then do not try to go further
319				 * Issue: #74
320				 */
321				len --;
322				*t++ = '\\';
323				continue;
324			}
325
326			switch (*h) {
327			case 'n':
328				*t++ = '\n';
329				break;
330			case 'r':
331				*t++ = '\r';
332				break;
333			case 'b':
334				*t++ = '\b';
335				break;
336			case 't':
337				*t++ = '\t';
338				break;
339			case 'f':
340				*t++ = '\f';
341				break;
342			case '\\':
343				*t++ = '\\';
344				break;
345			case '"':
346				*t++ = '"';
347				break;
348			case 'u':
349				/* Unicode escape */
350				uval = 0;
351				h ++; /* u character */
352				len --;
353
354				if (len > 3) {
355					for (i = 0; i < 4; i++) {
356						uval <<= 4;
357						if (isdigit (h[i])) {
358							uval += h[i] - '0';
359						}
360						else if (h[i] >= 'a' && h[i] <= 'f') {
361							uval += h[i] - 'a' + 10;
362						}
363						else if (h[i] >= 'A' && h[i] <= 'F') {
364							uval += h[i] - 'A' + 10;
365						}
366						else {
367							break;
368						}
369					}
370
371					/* Encode */
372					if(uval < 0x80) {
373						t[0] = (char)uval;
374						t ++;
375					}
376					else if(uval < 0x800) {
377						t[0] = 0xC0 + ((uval & 0x7C0) >> 6);
378						t[1] = 0x80 + ((uval & 0x03F));
379						t += 2;
380					}
381					else if(uval < 0x10000) {
382						t[0] = 0xE0 + ((uval & 0xF000) >> 12);
383						t[1] = 0x80 + ((uval & 0x0FC0) >> 6);
384						t[2] = 0x80 + ((uval & 0x003F));
385						t += 3;
386					}
387#if 0
388					/* It's not actually supported now */
389					else if(uval <= 0x10FFFF) {
390						t[0] = 0xF0 + ((uval & 0x1C0000) >> 18);
391						t[1] = 0x80 + ((uval & 0x03F000) >> 12);
392						t[2] = 0x80 + ((uval & 0x000FC0) >> 6);
393						t[3] = 0x80 + ((uval & 0x00003F));
394						t += 4;
395					}
396#endif
397					else {
398						*t++ = '?';
399					}
400
401					/* Consume 4 characters of source */
402					h += 4;
403					len -= 4;
404
405					if (len > 0) {
406						len --; /* for '\' character */
407					}
408					continue;
409				}
410				else {
411					*t++ = 'u';
412				}
413				break;
414			default:
415				*t++ = *h;
416				break;
417			}
418			h ++;
419			len --;
420		}
421		else {
422			*t++ = *h++;
423		}
424
425		if (len > 0) {
426			len --;
427		}
428	}
429	*t = '\0';
430
431	return (t - str);
432}
433
434size_t
435ucl_unescape_squoted_string (char *str, size_t len)
436{
437	char *t = str, *h = str;
438
439	if (len <= 1) {
440		return len;
441	}
442
443	/* t is target (tortoise), h is source (hare) */
444
445	while (len) {
446		if (*h == '\\') {
447			h ++;
448
449			if (len == 1) {
450				/*
451				 * If \ is last, then do not try to go further
452				 * Issue: #74
453				 */
454				len --;
455				*t++ = '\\';
456				continue;
457			}
458
459			switch (*h) {
460			case '\'':
461				*t++ = '\'';
462				break;
463			case '\n':
464				/* Ignore \<newline> style stuff */
465				break;
466			case '\r':
467				/* Ignore \r and the following \n if needed */
468				if (len > 1 && h[1] == '\n') {
469					h ++;
470					len --;
471				}
472				break;
473			default:
474				/* Ignore \ */
475				*t++ = '\\';
476				*t++ = *h;
477				break;
478			}
479
480			h ++;
481			len --;
482		}
483		else {
484			*t++ = *h++;
485		}
486
487		if (len > 0) {
488			len --;
489		}
490	}
491
492	*t = '\0';
493
494	return (t - str);
495}
496
497char *
498ucl_copy_key_trash (const ucl_object_t *obj)
499{
500	ucl_object_t *deconst;
501
502	if (obj == NULL) {
503		return NULL;
504	}
505	if (obj->trash_stack[UCL_TRASH_KEY] == NULL && obj->key != NULL) {
506		deconst = __DECONST (ucl_object_t *, obj);
507		deconst->trash_stack[UCL_TRASH_KEY] = malloc (obj->keylen + 1);
508		if (deconst->trash_stack[UCL_TRASH_KEY] != NULL) {
509			memcpy (deconst->trash_stack[UCL_TRASH_KEY], obj->key, obj->keylen);
510			deconst->trash_stack[UCL_TRASH_KEY][obj->keylen] = '\0';
511		}
512		deconst->key = obj->trash_stack[UCL_TRASH_KEY];
513		deconst->flags |= UCL_OBJECT_ALLOCATED_KEY;
514	}
515
516	return obj->trash_stack[UCL_TRASH_KEY];
517}
518
519void
520ucl_chunk_free (struct ucl_chunk *chunk)
521{
522	if (chunk) {
523		struct ucl_parser_special_handler_chain *chain, *tmp;
524
525		LL_FOREACH_SAFE (chunk->special_handlers, chain, tmp) {
526			if (chain->special_handler->free_function) {
527				chain->special_handler->free_function (
528						chain->begin,
529						chain->len,
530						chain->special_handler->user_data);
531			} else {
532				UCL_FREE (chain->len, chain->begin);
533			}
534
535			UCL_FREE (sizeof (*chain), chain);
536		}
537
538		chunk->special_handlers = NULL;
539
540		if (chunk->fname) {
541			free (chunk->fname);
542		}
543
544		UCL_FREE (sizeof (*chunk), chunk);
545	}
546}
547
548char *
549ucl_copy_value_trash (const ucl_object_t *obj)
550{
551	ucl_object_t *deconst;
552
553	if (obj == NULL) {
554		return NULL;
555	}
556	if (obj->trash_stack[UCL_TRASH_VALUE] == NULL) {
557		deconst = __DECONST (ucl_object_t *, obj);
558		if (obj->type == UCL_STRING) {
559
560			/* Special case for strings */
561			if (obj->flags & UCL_OBJECT_BINARY) {
562				deconst->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len);
563				if (deconst->trash_stack[UCL_TRASH_VALUE] != NULL) {
564					memcpy (deconst->trash_stack[UCL_TRASH_VALUE],
565							obj->value.sv,
566							obj->len);
567					deconst->value.sv = obj->trash_stack[UCL_TRASH_VALUE];
568				}
569			}
570			else {
571				deconst->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len + 1);
572				if (deconst->trash_stack[UCL_TRASH_VALUE] != NULL) {
573					memcpy (deconst->trash_stack[UCL_TRASH_VALUE],
574							obj->value.sv,
575							obj->len);
576					deconst->trash_stack[UCL_TRASH_VALUE][obj->len] = '\0';
577					deconst->value.sv = obj->trash_stack[UCL_TRASH_VALUE];
578				}
579			}
580		}
581		else {
582			/* Just emit value in json notation */
583			deconst->trash_stack[UCL_TRASH_VALUE] = ucl_object_emit_single_json (obj);
584			deconst->len = strlen (obj->trash_stack[UCL_TRASH_VALUE]);
585		}
586		deconst->flags |= UCL_OBJECT_ALLOCATED_VALUE;
587	}
588
589	return obj->trash_stack[UCL_TRASH_VALUE];
590}
591
592ucl_object_t*
593ucl_parser_get_object (struct ucl_parser *parser)
594{
595	if (parser->state != UCL_STATE_ERROR && parser->top_obj != NULL) {
596		return ucl_object_ref (parser->top_obj);
597	}
598
599	return NULL;
600}
601
602void
603ucl_parser_free (struct ucl_parser *parser)
604{
605	struct ucl_stack *stack, *stmp;
606	struct ucl_macro *macro, *mtmp;
607	struct ucl_chunk *chunk, *ctmp;
608	struct ucl_pubkey *key, *ktmp;
609	struct ucl_variable *var, *vtmp;
610	ucl_object_t *tr, *trtmp;
611
612	if (parser == NULL) {
613		return;
614	}
615
616	if (parser->top_obj != NULL) {
617		ucl_object_unref (parser->top_obj);
618	}
619
620	if (parser->includepaths != NULL) {
621		ucl_object_unref (parser->includepaths);
622	}
623
624	LL_FOREACH_SAFE (parser->stack, stack, stmp) {
625		free (stack);
626	}
627	HASH_ITER (hh, parser->macroes, macro, mtmp) {
628		free (macro->name);
629		HASH_DEL (parser->macroes, macro);
630		UCL_FREE (sizeof (struct ucl_macro), macro);
631	}
632	LL_FOREACH_SAFE (parser->chunks, chunk, ctmp) {
633		ucl_chunk_free (chunk);
634	}
635	LL_FOREACH_SAFE (parser->keys, key, ktmp) {
636		UCL_FREE (sizeof (struct ucl_pubkey), key);
637	}
638	LL_FOREACH_SAFE (parser->variables, var, vtmp) {
639		free (var->value);
640		free (var->var);
641		UCL_FREE (sizeof (struct ucl_variable), var);
642	}
643	LL_FOREACH_SAFE (parser->trash_objs, tr, trtmp) {
644		ucl_object_free_internal (tr, false, ucl_object_dtor_free);
645	}
646
647	if (parser->err != NULL) {
648		utstring_free (parser->err);
649	}
650
651	if (parser->cur_file) {
652		free (parser->cur_file);
653	}
654
655	if (parser->comments) {
656		ucl_object_unref (parser->comments);
657	}
658
659	UCL_FREE (sizeof (struct ucl_parser), parser);
660}
661
662const char *
663ucl_parser_get_error(struct ucl_parser *parser)
664{
665	if (parser == NULL) {
666		return NULL;
667	}
668
669	if (parser->err == NULL) {
670		return NULL;
671	}
672
673	return utstring_body (parser->err);
674}
675
676int
677ucl_parser_get_error_code(struct ucl_parser *parser)
678{
679	if (parser == NULL) {
680		return 0;
681	}
682
683	return parser->err_code;
684}
685
686unsigned
687ucl_parser_get_column(struct ucl_parser *parser)
688{
689	if (parser == NULL || parser->chunks == NULL) {
690		return 0;
691	}
692
693	return parser->chunks->column;
694}
695
696unsigned
697ucl_parser_get_linenum(struct ucl_parser *parser)
698{
699	if (parser == NULL || parser->chunks == NULL) {
700		return 0;
701	}
702
703	return parser->chunks->line;
704}
705
706void
707ucl_parser_clear_error(struct ucl_parser *parser)
708{
709	if (parser != NULL && parser->err != NULL) {
710		utstring_free(parser->err);
711		parser->err = NULL;
712		parser->err_code = 0;
713	}
714}
715
716bool
717ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len)
718{
719#ifndef HAVE_OPENSSL
720	ucl_create_err (&parser->err, "cannot check signatures without openssl");
721	return false;
722#else
723# if (OPENSSL_VERSION_NUMBER < 0x10000000L)
724	ucl_create_err (&parser->err, "cannot check signatures, openssl version is unsupported");
725	return EXIT_FAILURE;
726# else
727	struct ucl_pubkey *nkey;
728	BIO *mem;
729
730	mem = BIO_new_mem_buf ((void *)key, len);
731	nkey = UCL_ALLOC (sizeof (struct ucl_pubkey));
732	if (nkey == NULL) {
733		ucl_create_err (&parser->err, "cannot allocate memory for key");
734		return false;
735	}
736	nkey->key = PEM_read_bio_PUBKEY (mem, &nkey->key, NULL, NULL);
737	BIO_free (mem);
738	if (nkey->key == NULL) {
739		UCL_FREE (sizeof (struct ucl_pubkey), nkey);
740		ucl_create_err (&parser->err, "%s",
741				ERR_error_string (ERR_get_error (), NULL));
742		return false;
743	}
744	LL_PREPEND (parser->keys, nkey);
745# endif
746#endif
747	return true;
748}
749
750void ucl_parser_add_special_handler (struct ucl_parser *parser,
751		struct ucl_parser_special_handler *handler)
752{
753	LL_APPEND (parser->special_handlers, handler);
754}
755
756#ifdef CURL_FOUND
757struct ucl_curl_cbdata {
758	unsigned char *buf;
759	size_t buflen;
760};
761
762static size_t
763ucl_curl_write_callback (void* contents, size_t size, size_t nmemb, void* ud)
764{
765	struct ucl_curl_cbdata *cbdata = ud;
766	size_t realsize = size * nmemb;
767
768	cbdata->buf = realloc (cbdata->buf, cbdata->buflen + realsize + 1);
769	if (cbdata->buf == NULL) {
770		return 0;
771	}
772
773	memcpy (&(cbdata->buf[cbdata->buflen]), contents, realsize);
774	cbdata->buflen += realsize;
775	cbdata->buf[cbdata->buflen] = 0;
776
777	return realsize;
778}
779#endif
780
781/**
782 * Fetch a url and save results to the memory buffer
783 * @param url url to fetch
784 * @param len length of url
785 * @param buf target buffer
786 * @param buflen target length
787 * @return
788 */
789bool
790ucl_fetch_url (const unsigned char *url, unsigned char **buf, size_t *buflen,
791		UT_string **err, bool must_exist)
792{
793
794#ifdef HAVE_FETCH_H
795	struct url *fetch_url;
796	struct url_stat us;
797	FILE *in;
798
799	fetch_url = fetchParseURL (url);
800	if (fetch_url == NULL) {
801		ucl_create_err (err, "invalid URL %s: %s",
802				url, strerror (errno));
803		return false;
804	}
805	if ((in = fetchXGet (fetch_url, &us, "")) == NULL) {
806		if (!must_exist) {
807			ucl_create_err (err, "cannot fetch URL %s: %s",
808				url, strerror (errno));
809		}
810		fetchFreeURL (fetch_url);
811		return false;
812	}
813
814	*buflen = us.size;
815	*buf = malloc (*buflen);
816	if (*buf == NULL) {
817		ucl_create_err (err, "cannot allocate buffer for URL %s: %s",
818				url, strerror (errno));
819		fclose (in);
820		fetchFreeURL (fetch_url);
821		return false;
822	}
823
824	if (fread (*buf, *buflen, 1, in) != 1) {
825		ucl_create_err (err, "cannot read URL %s: %s",
826				url, strerror (errno));
827		fclose (in);
828		fetchFreeURL (fetch_url);
829		return false;
830	}
831
832	fetchFreeURL (fetch_url);
833	return true;
834#elif defined(CURL_FOUND)
835	CURL *curl;
836	int r;
837	struct ucl_curl_cbdata cbdata;
838
839	curl = curl_easy_init ();
840	if (curl == NULL) {
841		ucl_create_err (err, "CURL interface is broken");
842		return false;
843	}
844	if ((r = curl_easy_setopt (curl, CURLOPT_URL, url)) != CURLE_OK) {
845		ucl_create_err (err, "invalid URL %s: %s",
846				url, curl_easy_strerror (r));
847		curl_easy_cleanup (curl);
848		return false;
849	}
850	curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, ucl_curl_write_callback);
851	cbdata.buf = NULL;
852	cbdata.buflen = 0;
853	curl_easy_setopt (curl, CURLOPT_WRITEDATA, &cbdata);
854
855	if ((r = curl_easy_perform (curl)) != CURLE_OK) {
856		if (!must_exist) {
857			ucl_create_err (err, "error fetching URL %s: %s",
858				url, curl_easy_strerror (r));
859		}
860		curl_easy_cleanup (curl);
861		if (cbdata.buf) {
862			free (cbdata.buf);
863		}
864		return false;
865	}
866	*buf = cbdata.buf;
867	*buflen = cbdata.buflen;
868
869	curl_easy_cleanup (curl);
870
871	return true;
872#else
873	ucl_create_err (err, "URL support is disabled");
874	return false;
875#endif
876}
877
878/**
879 * Fetch a file and save results to the memory buffer
880 * @param filename filename to fetch
881 * @param len length of filename
882 * @param buf target buffer
883 * @param buflen target length
884 * @return
885 */
886bool
887ucl_fetch_file (const unsigned char *filename, unsigned char **buf, size_t *buflen,
888		UT_string **err, bool must_exist)
889{
890	int fd;
891	struct stat st;
892
893	if (stat (filename, &st) == -1) {
894		if (must_exist || errno == EPERM) {
895			ucl_create_err (err, "cannot stat file %s: %s",
896					filename, strerror (errno));
897		}
898		return false;
899	}
900	if (!S_ISREG (st.st_mode)) {
901		if (must_exist) {
902			ucl_create_err (err, "file %s is not a regular file", filename);
903		}
904
905		return false;
906	}
907	if (st.st_size == 0) {
908		/* Do not map empty files */
909		*buf = NULL;
910		*buflen = 0;
911	}
912	else {
913		if ((fd = open (filename, O_RDONLY)) == -1) {
914			ucl_create_err (err, "cannot open file %s: %s",
915					filename, strerror (errno));
916			return false;
917		}
918		if ((*buf = ucl_mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
919			close (fd);
920			ucl_create_err (err, "cannot mmap file %s: %s",
921					filename, strerror (errno));
922			*buf = NULL;
923
924			return false;
925		}
926		*buflen = st.st_size;
927		close (fd);
928	}
929
930	return true;
931}
932
933
934#if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
935static inline bool
936ucl_sig_check (const unsigned char *data, size_t datalen,
937		const unsigned char *sig, size_t siglen, struct ucl_parser *parser)
938{
939	struct ucl_pubkey *key;
940	char dig[EVP_MAX_MD_SIZE];
941	unsigned int diglen;
942	EVP_PKEY_CTX *key_ctx;
943	EVP_MD_CTX *sign_ctx = NULL;
944
945	sign_ctx = EVP_MD_CTX_create ();
946
947	LL_FOREACH (parser->keys, key) {
948		key_ctx = EVP_PKEY_CTX_new (key->key, NULL);
949		if (key_ctx != NULL) {
950			if (EVP_PKEY_verify_init (key_ctx) <= 0) {
951				EVP_PKEY_CTX_free (key_ctx);
952				continue;
953			}
954			if (EVP_PKEY_CTX_set_rsa_padding (key_ctx, RSA_PKCS1_PADDING) <= 0) {
955				EVP_PKEY_CTX_free (key_ctx);
956				continue;
957			}
958			if (EVP_PKEY_CTX_set_signature_md (key_ctx, EVP_sha256 ()) <= 0) {
959				EVP_PKEY_CTX_free (key_ctx);
960				continue;
961			}
962			EVP_DigestInit (sign_ctx, EVP_sha256 ());
963			EVP_DigestUpdate (sign_ctx, data, datalen);
964			EVP_DigestFinal (sign_ctx, dig, &diglen);
965
966			if (EVP_PKEY_verify (key_ctx, sig, siglen, dig, diglen) == 1) {
967				EVP_MD_CTX_destroy (sign_ctx);
968				EVP_PKEY_CTX_free (key_ctx);
969				return true;
970			}
971
972			EVP_PKEY_CTX_free (key_ctx);
973		}
974	}
975
976	EVP_MD_CTX_destroy (sign_ctx);
977
978	return false;
979}
980#endif
981
982struct ucl_include_params {
983	bool check_signature;
984	bool must_exist;
985	bool use_glob;
986	bool use_prefix;
987	bool soft_fail;
988	bool allow_glob;
989	unsigned priority;
990	enum ucl_duplicate_strategy strat;
991	enum ucl_parse_type parse_type;
992	const char *prefix;
993	const char *target;
994};
995
996/**
997 * Include an url to configuration
998 * @param data
999 * @param len
1000 * @param parser
1001 * @param err
1002 * @return
1003 */
1004static bool
1005ucl_include_url (const unsigned char *data, size_t len,
1006		struct ucl_parser *parser,
1007		struct ucl_include_params *params)
1008{
1009
1010	bool res;
1011	unsigned char *buf = NULL;
1012	size_t buflen = 0;
1013	struct ucl_chunk *chunk;
1014	char urlbuf[PATH_MAX];
1015	int prev_state;
1016
1017	snprintf (urlbuf, sizeof (urlbuf), "%.*s", (int)len, data);
1018
1019	if (!ucl_fetch_url (urlbuf, &buf, &buflen, &parser->err, params->must_exist)) {
1020		return !params->must_exist;
1021	}
1022
1023	if (params->check_signature) {
1024#if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
1025		unsigned char *sigbuf = NULL;
1026		size_t siglen = 0;
1027		/* We need to check signature first */
1028		snprintf (urlbuf, sizeof (urlbuf), "%.*s.sig", (int)len, data);
1029		if (!ucl_fetch_url (urlbuf, &sigbuf, &siglen, &parser->err, true)) {
1030			return false;
1031		}
1032		if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
1033			ucl_create_err (&parser->err, "cannot verify url %s: %s",
1034							urlbuf,
1035							ERR_error_string (ERR_get_error (), NULL));
1036			if (siglen > 0) {
1037				ucl_munmap (sigbuf, siglen);
1038			}
1039			return false;
1040		}
1041		if (siglen > 0) {
1042			ucl_munmap (sigbuf, siglen);
1043		}
1044#endif
1045	}
1046
1047	prev_state = parser->state;
1048	parser->state = UCL_STATE_INIT;
1049
1050	res = ucl_parser_add_chunk_full (parser, buf, buflen, params->priority,
1051			params->strat, params->parse_type);
1052	if (res == true) {
1053		/* Remove chunk from the stack */
1054		chunk = parser->chunks;
1055		if (chunk != NULL) {
1056			parser->chunks = chunk->next;
1057			ucl_chunk_free (chunk);
1058		}
1059	}
1060
1061	parser->state = prev_state;
1062	free (buf);
1063
1064	return res;
1065}
1066
1067/**
1068 * Include a single file to the parser
1069 * @param data
1070 * @param len
1071 * @param parser
1072 * @param check_signature
1073 * @param must_exist
1074 * @param allow_glob
1075 * @param priority
1076 * @return
1077 */
1078static bool
1079ucl_include_file_single (const unsigned char *data, size_t len,
1080		struct ucl_parser *parser, struct ucl_include_params *params)
1081{
1082	bool res;
1083	struct ucl_chunk *chunk;
1084	unsigned char *buf = NULL;
1085	char *old_curfile, *ext;
1086	size_t buflen = 0;
1087	char filebuf[PATH_MAX], realbuf[PATH_MAX];
1088	int prev_state;
1089	struct ucl_variable *cur_var, *tmp_var, *old_curdir = NULL,
1090			*old_filename = NULL;
1091	ucl_object_t *nest_obj = NULL, *old_obj = NULL, *new_obj = NULL;
1092	ucl_hash_t *container = NULL;
1093	struct ucl_stack *st = NULL;
1094
1095	snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data);
1096	if (ucl_realpath (filebuf, realbuf) == NULL) {
1097		if (params->soft_fail) {
1098			return false;
1099		}
1100		if (!params->must_exist && errno != EPERM) {
1101			return true;
1102		}
1103
1104		ucl_create_err (&parser->err, "cannot open file %s: %s",
1105									filebuf,
1106									strerror (errno));
1107		return false;
1108	}
1109
1110	if (parser->cur_file && strcmp (realbuf, parser->cur_file) == 0) {
1111		/* We are likely including the file itself */
1112		if (params->soft_fail) {
1113			return false;
1114		}
1115
1116		ucl_create_err (&parser->err, "trying to include the file %s from itself",
1117				realbuf);
1118		return false;
1119	}
1120
1121	if (!ucl_fetch_file (realbuf, &buf, &buflen, &parser->err, params->must_exist)) {
1122		if (params->soft_fail) {
1123			return false;
1124		}
1125
1126		if (params->must_exist || parser->err != NULL) {
1127			/* The case of fatal errors */
1128			return false;
1129		}
1130
1131		return true;
1132	}
1133
1134	if (params->check_signature) {
1135#if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
1136		unsigned char *sigbuf = NULL;
1137		size_t siglen = 0;
1138		/* We need to check signature first */
1139		snprintf (filebuf, sizeof (filebuf), "%s.sig", realbuf);
1140		if (!ucl_fetch_file (filebuf, &sigbuf, &siglen, &parser->err, true)) {
1141			return false;
1142		}
1143		if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
1144			ucl_create_err (&parser->err, "cannot verify file %s: %s",
1145							filebuf,
1146							ERR_error_string (ERR_get_error (), NULL));
1147			if (sigbuf) {
1148				ucl_munmap (sigbuf, siglen);
1149			}
1150			return false;
1151		}
1152		if (sigbuf) {
1153			ucl_munmap (sigbuf, siglen);
1154		}
1155#endif
1156	}
1157
1158	old_curfile = parser->cur_file;
1159	parser->cur_file = NULL;
1160
1161	/* Store old file vars */
1162	DL_FOREACH_SAFE (parser->variables, cur_var, tmp_var) {
1163		if (strcmp (cur_var->var, "CURDIR") == 0) {
1164			old_curdir = cur_var;
1165			DL_DELETE (parser->variables, cur_var);
1166		}
1167		else if (strcmp (cur_var->var, "FILENAME") == 0) {
1168			old_filename = cur_var;
1169			DL_DELETE (parser->variables, cur_var);
1170		}
1171	}
1172
1173	ucl_parser_set_filevars (parser, realbuf, false);
1174
1175	prev_state = parser->state;
1176	parser->state = UCL_STATE_INIT;
1177
1178	if (params->use_prefix && params->prefix == NULL) {
1179		/* Auto generate a key name based on the included filename */
1180		params->prefix = basename (realbuf);
1181		ext = strrchr (params->prefix, '.');
1182		if (ext != NULL && (strcmp (ext, ".conf") == 0 || strcmp (ext, ".ucl") == 0)) {
1183			/* Strip off .conf or .ucl */
1184			*ext = '\0';
1185		}
1186	}
1187	if (params->prefix != NULL) {
1188		/* This is a prefixed include */
1189		container = parser->stack->obj->value.ov;
1190
1191		old_obj = __DECONST (ucl_object_t *, ucl_hash_search (container,
1192				params->prefix, strlen (params->prefix)));
1193
1194		if (strcasecmp (params->target, "array") == 0) {
1195			if (old_obj == NULL) {
1196				/* Create an array with key: prefix */
1197				old_obj = ucl_object_new_full (UCL_ARRAY, params->priority);
1198				old_obj->key = params->prefix;
1199				old_obj->keylen = strlen (params->prefix);
1200				ucl_copy_key_trash (old_obj);
1201				old_obj->prev = old_obj;
1202				old_obj->next = NULL;
1203
1204				container = ucl_hash_insert_object (container, old_obj,
1205						parser->flags & UCL_PARSER_KEY_LOWERCASE);
1206				parser->stack->obj->len++;
1207
1208				nest_obj = ucl_object_new_full (UCL_OBJECT, params->priority);
1209				nest_obj->prev = nest_obj;
1210				nest_obj->next = NULL;
1211
1212				ucl_array_append (old_obj, nest_obj);
1213			}
1214			else {
1215				if (ucl_object_type (old_obj) == UCL_ARRAY) {
1216					/* Append to the existing array */
1217					nest_obj = ucl_object_new_full (UCL_OBJECT,
1218							params->priority);
1219					if (nest_obj == NULL) {
1220						ucl_create_err (&parser->err,
1221								"cannot allocate memory for an object");
1222						if (buf) {
1223							ucl_munmap (buf, buflen);
1224						}
1225
1226						return false;
1227					}
1228					nest_obj->prev = nest_obj;
1229					nest_obj->next = NULL;
1230
1231					ucl_array_append (old_obj, nest_obj);
1232				}
1233				else {
1234					/* Convert the object to an array */
1235					new_obj = ucl_object_typed_new (UCL_ARRAY);
1236					if (new_obj == NULL) {
1237						ucl_create_err (&parser->err,
1238								"cannot allocate memory for an object");
1239						if (buf) {
1240							ucl_munmap (buf, buflen);
1241						}
1242
1243						return false;
1244					}
1245					new_obj->key = old_obj->key;
1246					new_obj->keylen = old_obj->keylen;
1247					new_obj->flags |= UCL_OBJECT_MULTIVALUE;
1248					new_obj->prev = new_obj;
1249					new_obj->next = NULL;
1250
1251					nest_obj = ucl_object_new_full (UCL_OBJECT,
1252							params->priority);
1253					if (nest_obj == NULL) {
1254						ucl_create_err (&parser->err,
1255								"cannot allocate memory for an object");
1256						if (buf) {
1257							ucl_munmap (buf, buflen);
1258						}
1259
1260						return false;
1261					}
1262					nest_obj->prev = nest_obj;
1263					nest_obj->next = NULL;
1264
1265					ucl_array_append (new_obj, old_obj);
1266					ucl_array_append (new_obj, nest_obj);
1267					ucl_hash_replace (container, old_obj, new_obj);
1268				}
1269			}
1270		}
1271		else {
1272			/* Case of object */
1273			if (old_obj == NULL) {
1274				/* Create an object with key: prefix */
1275				nest_obj = ucl_object_new_full (UCL_OBJECT, params->priority);
1276
1277				if (nest_obj == NULL) {
1278					ucl_create_err (&parser->err, "cannot allocate memory for an object");
1279					if (buf) {
1280						ucl_munmap (buf, buflen);
1281					}
1282
1283					return false;
1284				}
1285
1286				nest_obj->key = params->prefix;
1287				nest_obj->keylen = strlen (params->prefix);
1288				ucl_copy_key_trash(nest_obj);
1289				nest_obj->prev = nest_obj;
1290				nest_obj->next = NULL;
1291
1292				container = ucl_hash_insert_object (container, nest_obj,
1293						parser->flags & UCL_PARSER_KEY_LOWERCASE);
1294				parser->stack->obj->len ++;
1295			}
1296			else {
1297				if (ucl_object_type (old_obj) == UCL_OBJECT) {
1298					/* Append to existing Object*/
1299					nest_obj = old_obj;
1300				}
1301				else {
1302					/* The key is not an object */
1303					ucl_create_err (&parser->err,
1304							"Conflicting type for key: %s, asked %s, has %s",
1305							params->prefix, params->target,
1306							ucl_object_type_to_string (ucl_object_type (old_obj)));
1307					if (buf) {
1308						ucl_munmap (buf, buflen);
1309					}
1310
1311					return false;
1312				}
1313			}
1314		}
1315
1316
1317		/* Put all of the content of the include inside that object */
1318		parser->stack->obj->value.ov = container;
1319
1320		st = UCL_ALLOC (sizeof (struct ucl_stack));
1321		if (st == NULL) {
1322			ucl_create_err (&parser->err, "cannot allocate memory for an object");
1323			ucl_object_unref (nest_obj);
1324
1325			if (buf) {
1326				ucl_munmap (buf, buflen);
1327			}
1328
1329			return false;
1330		}
1331		st->obj = nest_obj;
1332		st->e.params.level = parser->stack->e.params.level;
1333		st->e.params.flags = parser->stack->e.params.flags;
1334		st->e.params.line = parser->stack->e.params.line;
1335		st->chunk = parser->chunks;
1336		LL_PREPEND (parser->stack, st);
1337		parser->cur_obj = nest_obj;
1338	}
1339
1340	res = ucl_parser_add_chunk_full (parser, buf, buflen, params->priority,
1341			params->strat, params->parse_type);
1342
1343	if (res) {
1344		/* Stop nesting the include, take 1 level off the stack */
1345		if (params->prefix != NULL && nest_obj != NULL) {
1346			parser->stack = st->next;
1347			UCL_FREE (sizeof (struct ucl_stack), st);
1348		}
1349
1350		/* Remove chunk from the stack */
1351		chunk = parser->chunks;
1352		if (chunk != NULL) {
1353			parser->chunks = chunk->next;
1354			ucl_chunk_free (chunk);
1355			parser->recursion--;
1356		}
1357
1358		/* Restore old file vars */
1359		if (parser->cur_file) {
1360			free (parser->cur_file);
1361		}
1362
1363		parser->cur_file = old_curfile;
1364		DL_FOREACH_SAFE (parser->variables, cur_var, tmp_var) {
1365			if (strcmp (cur_var->var, "CURDIR") == 0 && old_curdir) {
1366				DL_DELETE (parser->variables, cur_var);
1367				free (cur_var->var);
1368				free (cur_var->value);
1369				UCL_FREE (sizeof (struct ucl_variable), cur_var);
1370			} else if (strcmp (cur_var->var, "FILENAME") == 0 && old_filename) {
1371				DL_DELETE (parser->variables, cur_var);
1372				free (cur_var->var);
1373				free (cur_var->value);
1374				UCL_FREE (sizeof (struct ucl_variable), cur_var);
1375			}
1376		}
1377		if (old_filename) {
1378			DL_APPEND (parser->variables, old_filename);
1379		}
1380		if (old_curdir) {
1381			DL_APPEND (parser->variables, old_curdir);
1382		}
1383
1384		parser->state = prev_state;
1385	}
1386
1387	if (buflen > 0) {
1388		ucl_munmap (buf, buflen);
1389	}
1390
1391	return res;
1392}
1393
1394/**
1395 * Include a file to configuration
1396 * @param data
1397 * @param len
1398 * @param parser
1399 * @param err
1400 * @return
1401 */
1402static bool
1403ucl_include_file (const unsigned char *data, size_t len,
1404				  struct ucl_parser *parser,
1405				  struct ucl_include_params *params,
1406				  const ucl_object_t *args)
1407{
1408	const unsigned char *p = data, *end = data + len;
1409	bool need_glob = false;
1410	int cnt = 0;
1411	char glob_pattern[PATH_MAX];
1412	size_t i;
1413
1414#ifndef _WIN32
1415	if (!params->allow_glob) {
1416		return ucl_include_file_single (data, len, parser, params);
1417	}
1418	else {
1419		/* Check for special symbols in a filename */
1420		while (p != end) {
1421			if (*p == '*' || *p == '?') {
1422				need_glob = true;
1423				break;
1424			}
1425			p ++;
1426		}
1427		if (need_glob) {
1428			glob_t globbuf;
1429			memset (&globbuf, 0, sizeof (globbuf));
1430			ucl_strlcpy (glob_pattern, (const char *)data,
1431				(len + 1 < sizeof (glob_pattern) ? len + 1 : sizeof (glob_pattern)));
1432			if (glob (glob_pattern, 0, NULL, &globbuf) != 0) {
1433				return (!params->must_exist || false);
1434			}
1435			for (i = 0; i < globbuf.gl_pathc; i ++) {
1436
1437				if (parser->include_trace_func) {
1438					const ucl_object_t *parent = NULL;
1439
1440					if (parser->stack) {
1441						parent = parser->stack->obj;
1442					}
1443
1444					parser->include_trace_func (parser, parent, NULL,
1445							globbuf.gl_pathv[i],
1446							strlen (globbuf.gl_pathv[i]),
1447							parser->include_trace_ud);
1448				}
1449
1450				if (!ucl_include_file_single ((unsigned char *)globbuf.gl_pathv[i],
1451						strlen (globbuf.gl_pathv[i]), parser, params)) {
1452					if (params->soft_fail) {
1453						continue;
1454					}
1455					globfree (&globbuf);
1456					return false;
1457				}
1458				cnt ++;
1459			}
1460			globfree (&globbuf);
1461
1462			if (cnt == 0 && params->must_exist) {
1463				ucl_create_err (&parser->err, "cannot match any files for pattern %s",
1464					glob_pattern);
1465				return false;
1466			}
1467		}
1468		else {
1469			return ucl_include_file_single (data, len, parser, params);
1470		}
1471	}
1472#else
1473	/* Win32 compilers do not support globbing. Therefore, for Win32,
1474	   treat allow_glob/need_glob as a NOOP and just return */
1475	return ucl_include_file_single (data, len, parser, params);
1476#endif
1477
1478	return true;
1479}
1480
1481/**
1482 * Common function to handle .*include* macros
1483 * @param data
1484 * @param len
1485 * @param args
1486 * @param parser
1487 * @param default_try
1488 * @param default_sign
1489 * @return
1490 */
1491static bool
1492ucl_include_common (const unsigned char *data, size_t len,
1493		const ucl_object_t *args, struct ucl_parser *parser,
1494		bool default_try,
1495		bool default_sign)
1496{
1497	bool allow_url = false, search = false;
1498	const char *duplicate;
1499	const ucl_object_t *param;
1500	ucl_object_iter_t it = NULL, ip = NULL;
1501	char ipath[PATH_MAX];
1502	struct ucl_include_params params;
1503
1504	/* Default values */
1505	params.soft_fail = default_try;
1506	params.allow_glob = false;
1507	params.check_signature = default_sign;
1508	params.use_prefix = false;
1509	params.target = "object";
1510	params.prefix = NULL;
1511	params.priority = 0;
1512	params.parse_type = UCL_PARSE_UCL;
1513	params.strat = UCL_DUPLICATE_APPEND;
1514	params.must_exist = !default_try;
1515
1516	if (parser->include_trace_func) {
1517		const ucl_object_t *parent = NULL;
1518
1519		if (parser->stack) {
1520			parent = parser->stack->obj;
1521		}
1522
1523		parser->include_trace_func (parser, parent, args,
1524				data, len, parser->include_trace_ud);
1525	}
1526
1527	/* Process arguments */
1528	if (args != NULL && args->type == UCL_OBJECT) {
1529		while ((param = ucl_object_iterate (args, &it, true)) != NULL) {
1530			if (param->type == UCL_BOOLEAN) {
1531				if (strncmp (param->key, "try", param->keylen) == 0) {
1532					params.must_exist = !ucl_object_toboolean (param);
1533				}
1534				else if (strncmp (param->key, "sign", param->keylen) == 0) {
1535					params.check_signature = ucl_object_toboolean (param);
1536				}
1537				else if (strncmp (param->key, "glob", param->keylen) == 0) {
1538					params.allow_glob = ucl_object_toboolean (param);
1539				}
1540				else if (strncmp (param->key, "url", param->keylen) == 0) {
1541					allow_url = ucl_object_toboolean (param);
1542				}
1543				else if (strncmp (param->key, "prefix", param->keylen) == 0) {
1544					params.use_prefix = ucl_object_toboolean (param);
1545				}
1546			}
1547			else if (param->type == UCL_STRING) {
1548				if (strncmp (param->key, "key", param->keylen) == 0) {
1549					params.prefix = ucl_object_tostring (param);
1550				}
1551				else if (strncmp (param->key, "target", param->keylen) == 0) {
1552					params.target = ucl_object_tostring (param);
1553				}
1554				else if (strncmp (param->key, "duplicate", param->keylen) == 0) {
1555					duplicate = ucl_object_tostring (param);
1556
1557					if (strcmp (duplicate, "append") == 0) {
1558						params.strat = UCL_DUPLICATE_APPEND;
1559					}
1560					else if (strcmp (duplicate, "merge") == 0) {
1561						params.strat = UCL_DUPLICATE_MERGE;
1562					}
1563					else if (strcmp (duplicate, "rewrite") == 0) {
1564						params.strat = UCL_DUPLICATE_REWRITE;
1565					}
1566					else if (strcmp (duplicate, "error") == 0) {
1567						params.strat = UCL_DUPLICATE_ERROR;
1568					}
1569				}
1570			}
1571			else if (param->type == UCL_ARRAY) {
1572				if (strncmp (param->key, "path", param->keylen) == 0) {
1573					ucl_set_include_path (parser, __DECONST(ucl_object_t *, param));
1574				}
1575			}
1576			else if (param->type == UCL_INT) {
1577				if (strncmp (param->key, "priority", param->keylen) == 0) {
1578					params.priority = ucl_object_toint (param);
1579					if (params.priority > UCL_PRIORITY_MAX) {
1580						ucl_create_err (&parser->err, "Invalid priority value in macro: %d",
1581							params.priority);
1582						return false;
1583					}
1584				}
1585			}
1586		}
1587	}
1588
1589	if (parser->includepaths == NULL) {
1590		if (allow_url && ucl_strnstr (data, "://", len) != NULL) {
1591			/* Globbing is not used for URL's */
1592			return ucl_include_url (data, len, parser, &params);
1593		}
1594		else if (data != NULL) {
1595			/* Try to load a file */
1596			return ucl_include_file (data, len, parser, &params, args);
1597		}
1598	}
1599	else {
1600		if (allow_url && ucl_strnstr (data, "://", len) != NULL) {
1601			/* Globbing is not used for URL's */
1602			return ucl_include_url (data, len, parser, &params);
1603		}
1604
1605		ip = ucl_object_iterate_new (parser->includepaths);
1606		while ((param = ucl_object_iterate_safe (ip, true)) != NULL) {
1607			if (ucl_object_type(param) == UCL_STRING) {
1608				snprintf (ipath, sizeof (ipath), "%s/%.*s", ucl_object_tostring(param),
1609						(int)len, data);
1610				if ((search = ucl_include_file (ipath, strlen (ipath),
1611						parser, &params, args))) {
1612					if (!params.allow_glob) {
1613						break;
1614					}
1615				}
1616			}
1617		}
1618		ucl_object_iterate_free (ip);
1619		if (search == true) {
1620			return true;
1621		}
1622		else {
1623			ucl_create_err (&parser->err,
1624					"cannot find file: %.*s in search path",
1625					(int)len, data);
1626			return false;
1627		}
1628	}
1629
1630	return false;
1631}
1632
1633/**
1634 * Handle include macro
1635 * @param data include data
1636 * @param len length of data
1637 * @param args UCL object representing arguments to the macro
1638 * @param ud user data
1639 * @return
1640 */
1641bool
1642ucl_include_handler (const unsigned char *data, size_t len,
1643		const ucl_object_t *args, void* ud)
1644{
1645	struct ucl_parser *parser = ud;
1646
1647	return ucl_include_common (data, len, args, parser, false, false);
1648}
1649
1650/**
1651 * Handle includes macro
1652 * @param data include data
1653 * @param len length of data
1654 * @param args UCL object representing arguments to the macro
1655 * @param ud user data
1656 * @return
1657 */
1658bool
1659ucl_includes_handler (const unsigned char *data, size_t len,
1660		const ucl_object_t *args, void* ud)
1661{
1662	struct ucl_parser *parser = ud;
1663
1664	return ucl_include_common (data, len, args, parser, false, true);
1665}
1666
1667/**
1668 * Handle tryinclude macro
1669 * @param data include data
1670 * @param len length of data
1671 * @param args UCL object representing arguments to the macro
1672 * @param ud user data
1673 * @return
1674 */
1675bool
1676ucl_try_include_handler (const unsigned char *data, size_t len,
1677		const ucl_object_t *args, void* ud)
1678{
1679	struct ucl_parser *parser = ud;
1680
1681	return ucl_include_common (data, len, args, parser, true, false);
1682}
1683
1684/**
1685 * Handle priority macro
1686 * @param data include data
1687 * @param len length of data
1688 * @param args UCL object representing arguments to the macro
1689 * @param ud user data
1690 * @return
1691 */
1692bool
1693ucl_priority_handler (const unsigned char *data, size_t len,
1694		const ucl_object_t *args, void* ud)
1695{
1696	struct ucl_parser *parser = ud;
1697	unsigned priority = 255;
1698	const ucl_object_t *param;
1699	bool found = false;
1700	char *value = NULL, *leftover = NULL;
1701	ucl_object_iter_t it = NULL;
1702
1703	if (parser == NULL) {
1704		return false;
1705	}
1706
1707	/* Process arguments */
1708	if (args != NULL && args->type == UCL_OBJECT) {
1709		while ((param = ucl_object_iterate (args, &it, true)) != NULL) {
1710			if (param->type == UCL_INT) {
1711				if (strncmp (param->key, "priority", param->keylen) == 0) {
1712					priority = ucl_object_toint (param);
1713					found = true;
1714				}
1715			}
1716		}
1717	}
1718
1719	if (len > 0) {
1720		value = malloc(len + 1);
1721		ucl_strlcpy(value, (const char *)data, len + 1);
1722		errno = 0;
1723		priority = strtoul(value, &leftover, 10);
1724		if (errno != 0 || *leftover != '\0' || priority > UCL_PRIORITY_MAX) {
1725			ucl_create_err (&parser->err, "Invalid priority value in macro: %s",
1726				value);
1727			free(value);
1728			return false;
1729		}
1730		free(value);
1731		found = true;
1732	}
1733
1734	if (found == true) {
1735		parser->chunks->priority = priority;
1736		return true;
1737	}
1738
1739	ucl_create_err (&parser->err, "Unable to parse priority macro");
1740	return false;
1741}
1742
1743/**
1744 * Handle load macro
1745 * @param data include data
1746 * @param len length of data
1747 * @param args UCL object representing arguments to the macro
1748 * @param ud user data
1749 * @return
1750 */
1751bool
1752ucl_load_handler (const unsigned char *data, size_t len,
1753		const ucl_object_t *args, void* ud)
1754{
1755	struct ucl_parser *parser = ud;
1756	const ucl_object_t *param;
1757	ucl_object_t *obj, *old_obj;
1758	ucl_object_iter_t it = NULL;
1759	bool try_load, multiline, test;
1760	const char *target, *prefix;
1761	char *load_file, *tmp;
1762	unsigned char *buf;
1763	size_t buflen;
1764	unsigned priority;
1765	int64_t iv;
1766	ucl_object_t *container = NULL;
1767	enum ucl_string_flags flags;
1768
1769	/* Default values */
1770	try_load = false;
1771	multiline = false;
1772	test = false;
1773	target = "string";
1774	prefix = NULL;
1775	load_file = NULL;
1776	buf = NULL;
1777	buflen = 0;
1778	priority = 0;
1779	obj = NULL;
1780	old_obj = NULL;
1781	flags = 0;
1782
1783	if (parser == NULL) {
1784		return false;
1785	}
1786
1787	/* Process arguments */
1788	if (args != NULL && args->type == UCL_OBJECT) {
1789		while ((param = ucl_object_iterate (args, &it, true)) != NULL) {
1790			if (param->type == UCL_BOOLEAN) {
1791				if (strncmp (param->key, "try", param->keylen) == 0) {
1792					try_load = ucl_object_toboolean (param);
1793				}
1794				else if (strncmp (param->key, "multiline", param->keylen) == 0) {
1795					multiline = ucl_object_toboolean (param);
1796				}
1797				else if (strncmp (param->key, "escape", param->keylen) == 0) {
1798					test = ucl_object_toboolean (param);
1799					if (test) {
1800						flags |= UCL_STRING_ESCAPE;
1801					}
1802				}
1803				else if (strncmp (param->key, "trim", param->keylen) == 0) {
1804					test = ucl_object_toboolean (param);
1805					if (test) {
1806						flags |= UCL_STRING_TRIM;
1807					}
1808				}
1809			}
1810			else if (param->type == UCL_STRING) {
1811				if (strncmp (param->key, "key", param->keylen) == 0) {
1812					prefix = ucl_object_tostring (param);
1813				}
1814				else if (strncmp (param->key, "target", param->keylen) == 0) {
1815					target = ucl_object_tostring (param);
1816				}
1817			}
1818			else if (param->type == UCL_INT) {
1819				if (strncmp (param->key, "priority", param->keylen) == 0) {
1820					priority = ucl_object_toint (param);
1821				}
1822			}
1823		}
1824	}
1825
1826	if (prefix == NULL || strlen (prefix) == 0) {
1827		ucl_create_err (&parser->err, "No Key specified in load macro");
1828		return false;
1829	}
1830
1831	if (len > 0) {
1832		load_file = malloc (len + 1);
1833		if (!load_file) {
1834			ucl_create_err (&parser->err, "cannot allocate memory for suffix");
1835
1836			return false;
1837		}
1838
1839		snprintf (load_file, len + 1, "%.*s", (int)len, data);
1840
1841		if (!ucl_fetch_file (load_file, &buf, &buflen, &parser->err,
1842				!try_load)) {
1843			free (load_file);
1844
1845			return (try_load || false);
1846		}
1847
1848		free (load_file);
1849		container = parser->stack->obj;
1850		old_obj = __DECONST (ucl_object_t *, ucl_object_lookup (container,
1851				prefix));
1852
1853		if (old_obj != NULL) {
1854			ucl_create_err (&parser->err, "Key %s already exists", prefix);
1855			if (buf) {
1856				ucl_munmap (buf, buflen);
1857			}
1858
1859			return false;
1860		}
1861
1862		if (strcasecmp (target, "string") == 0) {
1863			obj = ucl_object_fromstring_common (buf, buflen, flags);
1864			ucl_copy_value_trash (obj);
1865			if (multiline) {
1866				obj->flags |= UCL_OBJECT_MULTILINE;
1867			}
1868		}
1869		else if (strcasecmp (target, "int") == 0) {
1870			tmp = malloc (buflen + 1);
1871
1872			if (tmp == NULL) {
1873				ucl_create_err (&parser->err, "Memory allocation failed");
1874				if (buf) {
1875					ucl_munmap (buf, buflen);
1876				}
1877
1878				return false;
1879			}
1880
1881			snprintf (tmp, buflen + 1, "%.*s", (int)buflen, buf);
1882			iv = strtoll (tmp, NULL, 10);
1883			obj = ucl_object_fromint (iv);
1884			free (tmp);
1885		}
1886
1887		if (buf) {
1888			ucl_munmap (buf, buflen);
1889		}
1890
1891		if (obj != NULL) {
1892			obj->key = prefix;
1893			obj->keylen = strlen (prefix);
1894			ucl_copy_key_trash (obj);
1895			obj->prev = obj;
1896			obj->next = NULL;
1897			ucl_object_set_priority (obj, priority);
1898			ucl_object_insert_key (container, obj, obj->key, obj->keylen, false);
1899		}
1900
1901		return true;
1902	}
1903
1904	ucl_create_err (&parser->err, "Unable to parse load macro");
1905	return false;
1906}
1907
1908bool
1909ucl_inherit_handler (const unsigned char *data, size_t len,
1910		const ucl_object_t *args, const ucl_object_t *ctx, void* ud)
1911{
1912	const ucl_object_t *parent, *cur;
1913	ucl_object_t *target, *copy;
1914	ucl_object_iter_t it = NULL;
1915	bool replace = false;
1916	struct ucl_parser *parser = ud;
1917
1918	parent = ucl_object_lookup_len (ctx, data, len);
1919
1920	/* Some sanity checks */
1921	if (parent == NULL || ucl_object_type (parent) != UCL_OBJECT) {
1922		ucl_create_err (&parser->err, "Unable to find inherited object %*.s",
1923				(int)len, data);
1924		return false;
1925	}
1926
1927	if (parser->stack == NULL || parser->stack->obj == NULL ||
1928			ucl_object_type (parser->stack->obj) != UCL_OBJECT) {
1929		ucl_create_err (&parser->err, "Invalid inherit context");
1930		return false;
1931	}
1932
1933	target = parser->stack->obj;
1934
1935	if (args && (cur = ucl_object_lookup (args, "replace")) != NULL) {
1936		replace = ucl_object_toboolean (cur);
1937	}
1938
1939	while ((cur = ucl_object_iterate (parent, &it, true))) {
1940		/* We do not replace existing keys */
1941		if (!replace && ucl_object_lookup_len (target, cur->key, cur->keylen)) {
1942			continue;
1943		}
1944
1945		copy = ucl_object_copy (cur);
1946
1947		if (!replace) {
1948			copy->flags |= UCL_OBJECT_INHERITED;
1949		}
1950
1951		ucl_object_insert_key (target, copy, copy->key,
1952				copy->keylen, false);
1953	}
1954
1955	return true;
1956}
1957
1958bool
1959ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand)
1960{
1961	char realbuf[PATH_MAX], *curdir;
1962
1963	if (filename != NULL) {
1964		if (need_expand) {
1965			if (ucl_realpath (filename, realbuf) == NULL) {
1966				return false;
1967			}
1968		}
1969		else {
1970			ucl_strlcpy (realbuf, filename, sizeof (realbuf));
1971		}
1972
1973		if (parser->cur_file) {
1974			free (parser->cur_file);
1975		}
1976
1977		parser->cur_file = strdup (realbuf);
1978
1979		/* Define variables */
1980		ucl_parser_register_variable (parser, "FILENAME", realbuf);
1981		curdir = dirname (realbuf);
1982		ucl_parser_register_variable (parser, "CURDIR", curdir);
1983	}
1984	else {
1985		/* Set everything from the current dir */
1986		curdir = getcwd (realbuf, sizeof (realbuf));
1987		ucl_parser_register_variable (parser, "FILENAME", "undef");
1988		ucl_parser_register_variable (parser, "CURDIR", curdir);
1989	}
1990
1991	return true;
1992}
1993
1994bool
1995ucl_parser_add_file_full (struct ucl_parser *parser, const char *filename,
1996		unsigned priority, enum ucl_duplicate_strategy strat,
1997		enum ucl_parse_type parse_type)
1998{
1999	unsigned char *buf;
2000	size_t len;
2001	bool ret;
2002	char realbuf[PATH_MAX];
2003
2004	if (ucl_realpath (filename, realbuf) == NULL) {
2005		ucl_create_err (&parser->err, "cannot open file %s: %s",
2006				filename,
2007				strerror (errno));
2008		return false;
2009	}
2010
2011	if (!ucl_fetch_file (realbuf, &buf, &len, &parser->err, true)) {
2012		return false;
2013	}
2014
2015	ucl_parser_set_filevars (parser, realbuf, false);
2016	ret = ucl_parser_add_chunk_full (parser, buf, len, priority, strat,
2017			parse_type);
2018
2019	if (len > 0) {
2020		ucl_munmap (buf, len);
2021	}
2022
2023	return ret;
2024}
2025
2026bool
2027ucl_parser_add_file_priority (struct ucl_parser *parser, const char *filename,
2028		unsigned priority)
2029{
2030	if (parser == NULL) {
2031		return false;
2032	}
2033
2034	return ucl_parser_add_file_full(parser, filename, priority,
2035			UCL_DUPLICATE_APPEND, UCL_PARSE_UCL);
2036}
2037
2038bool
2039ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
2040{
2041	if (parser == NULL) {
2042		return false;
2043	}
2044
2045	return ucl_parser_add_file_full(parser, filename,
2046			parser->default_priority, UCL_DUPLICATE_APPEND,
2047			UCL_PARSE_UCL);
2048}
2049
2050
2051bool
2052ucl_parser_add_fd_full (struct ucl_parser *parser, int fd,
2053		unsigned priority, enum ucl_duplicate_strategy strat,
2054		enum ucl_parse_type parse_type)
2055{
2056	unsigned char *buf;
2057	size_t len;
2058	bool ret;
2059	struct stat st;
2060
2061	if (fstat (fd, &st) == -1) {
2062		ucl_create_err (&parser->err, "cannot stat fd %d: %s",
2063			fd, strerror (errno));
2064		return false;
2065	}
2066	if (st.st_size == 0) {
2067		return true;
2068	}
2069	if ((buf = ucl_mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
2070		ucl_create_err (&parser->err, "cannot mmap fd %d: %s",
2071			fd, strerror (errno));
2072		return false;
2073	}
2074
2075	if (parser->cur_file) {
2076		free (parser->cur_file);
2077	}
2078	parser->cur_file = NULL;
2079	len = st.st_size;
2080	ret = ucl_parser_add_chunk_full (parser, buf, len, priority, strat,
2081			parse_type);
2082
2083	if (len > 0) {
2084		ucl_munmap (buf, len);
2085	}
2086
2087	return ret;
2088}
2089
2090bool
2091ucl_parser_add_fd_priority (struct ucl_parser *parser, int fd,
2092		unsigned priority)
2093{
2094	if (parser == NULL) {
2095		return false;
2096	}
2097
2098	return ucl_parser_add_fd_full(parser, fd, parser->default_priority,
2099			UCL_DUPLICATE_APPEND, UCL_PARSE_UCL);
2100}
2101
2102bool
2103ucl_parser_add_fd (struct ucl_parser *parser, int fd)
2104{
2105	if (parser == NULL) {
2106		return false;
2107	}
2108
2109	return ucl_parser_add_fd_priority(parser, fd, parser->default_priority);
2110}
2111
2112size_t
2113ucl_strlcpy (char *dst, const char *src, size_t siz)
2114{
2115	char *d = dst;
2116	const char *s = src;
2117	size_t n = siz;
2118
2119	/* Copy as many bytes as will fit */
2120	if (n != 0) {
2121		while (--n != 0) {
2122			if ((*d++ = *s++) == '\0') {
2123				break;
2124			}
2125		}
2126	}
2127
2128	if (n == 0 && siz != 0) {
2129		*d = '\0';
2130	}
2131
2132	return (s - src - 1);    /* count does not include NUL */
2133}
2134
2135size_t
2136ucl_strlcpy_unsafe (char *dst, const char *src, size_t siz)
2137{
2138	memcpy (dst, src, siz - 1);
2139	dst[siz - 1] = '\0';
2140
2141	return siz - 1;
2142}
2143
2144size_t
2145ucl_strlcpy_tolower (char *dst, const char *src, size_t siz)
2146{
2147	char *d = dst;
2148	const char *s = src;
2149	size_t n = siz;
2150
2151	/* Copy as many bytes as will fit */
2152	if (n != 0) {
2153		while (--n != 0) {
2154			if ((*d++ = tolower (*s++)) == '\0') {
2155				break;
2156			}
2157		}
2158	}
2159
2160	if (n == 0 && siz != 0) {
2161		*d = '\0';
2162	}
2163
2164	return (s - src);    /* count does not include NUL */
2165}
2166
2167/*
2168 * Find the first occurrence of find in s
2169 */
2170char *
2171ucl_strnstr (const char *s, const char *find, int len)
2172{
2173	char c, sc;
2174	int mlen;
2175
2176	if ((c = *find++) != 0) {
2177		mlen = strlen (find);
2178		do {
2179			do {
2180				if ((sc = *s++) == 0 || len-- == 0)
2181					return (NULL);
2182			} while (sc != c);
2183		} while (strncmp (s, find, mlen) != 0);
2184		s--;
2185	}
2186	return ((char *)s);
2187}
2188
2189/*
2190 * Find the first occurrence of find in s, ignore case.
2191 */
2192char *
2193ucl_strncasestr (const char *s, const char *find, int len)
2194{
2195	char c, sc;
2196	int mlen;
2197
2198	if ((c = *find++) != 0) {
2199		c = tolower (c);
2200		mlen = strlen (find);
2201		do {
2202			do {
2203				if ((sc = *s++) == 0 || len-- == 0)
2204					return (NULL);
2205			} while (tolower (sc) != c);
2206		} while (strncasecmp (s, find, mlen) != 0);
2207		s--;
2208	}
2209	return ((char *)s);
2210}
2211
2212ucl_object_t *
2213ucl_object_fromstring_common (const char *str, size_t len, enum ucl_string_flags flags)
2214{
2215	ucl_object_t *obj;
2216	const char *start, *end, *p, *pos;
2217	char *dst, *d;
2218	size_t escaped_len;
2219
2220	if (str == NULL) {
2221		return NULL;
2222	}
2223
2224	obj = ucl_object_new ();
2225	if (obj) {
2226		if (len == 0) {
2227			len = strlen (str);
2228		}
2229		if (flags & UCL_STRING_TRIM) {
2230			/* Skip leading spaces */
2231			for (start = str; (size_t)(start - str) < len; start ++) {
2232				if (!ucl_test_character (*start, UCL_CHARACTER_WHITESPACE_UNSAFE)) {
2233					break;
2234				}
2235			}
2236			/* Skip trailing spaces */
2237			for (end = str + len - 1; end > start; end --) {
2238				if (!ucl_test_character (*end, UCL_CHARACTER_WHITESPACE_UNSAFE)) {
2239					break;
2240				}
2241			}
2242			end ++;
2243		}
2244		else {
2245			start = str;
2246			end = str + len;
2247		}
2248
2249		obj->type = UCL_STRING;
2250		if (flags & UCL_STRING_ESCAPE) {
2251			for (p = start, escaped_len = 0; p < end; p ++, escaped_len ++) {
2252				if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE | UCL_CHARACTER_WHITESPACE_UNSAFE)) {
2253					switch (*p) {
2254					case '\v':
2255					case '\0':
2256						escaped_len += 5;
2257						break;
2258					case ' ':
2259						break;
2260					default:
2261						escaped_len ++;
2262						break;
2263					}
2264				}
2265			}
2266			dst = malloc (escaped_len + 1);
2267			if (dst != NULL) {
2268				for (p = start, d = dst; p < end; p ++, d ++) {
2269					if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE | UCL_CHARACTER_WHITESPACE_UNSAFE)) {
2270						switch (*p) {
2271						case '\n':
2272							*d++ = '\\';
2273							*d = 'n';
2274							break;
2275						case '\r':
2276							*d++ = '\\';
2277							*d = 'r';
2278							break;
2279						case '\b':
2280							*d++ = '\\';
2281							*d = 'b';
2282							break;
2283						case '\t':
2284							*d++ = '\\';
2285							*d = 't';
2286							break;
2287						case '\f':
2288							*d++ = '\\';
2289							*d = 'f';
2290							break;
2291						case '\0':
2292							*d++ = '\\';
2293							*d++ = 'u';
2294							*d++ = '0';
2295							*d++ = '0';
2296							*d++ = '0';
2297							*d   = '0';
2298							break;
2299						case '\v':
2300							*d++ = '\\';
2301							*d++ = 'u';
2302							*d++ = '0';
2303							*d++ = '0';
2304							*d++ = '0';
2305							*d   = 'B';
2306							break;
2307						case '\\':
2308							*d++ = '\\';
2309							*d = '\\';
2310							break;
2311						case ' ':
2312							*d = ' ';
2313							break;
2314						case '"':
2315							*d++ = '\\';
2316							*d = '"';
2317							break;
2318						}
2319					}
2320					else {
2321						*d = *p;
2322					}
2323				}
2324				*d = '\0';
2325				obj->value.sv = dst;
2326				obj->trash_stack[UCL_TRASH_VALUE] = dst;
2327				obj->len = escaped_len;
2328			}
2329		}
2330		else {
2331			dst = malloc (end - start + 1);
2332			if (dst != NULL) {
2333				ucl_strlcpy_unsafe (dst, start, end - start + 1);
2334				obj->value.sv = dst;
2335				obj->trash_stack[UCL_TRASH_VALUE] = dst;
2336				obj->len = end - start;
2337			}
2338		}
2339		if ((flags & UCL_STRING_PARSE) && dst != NULL) {
2340			/* Parse what we have */
2341			if (flags & UCL_STRING_PARSE_BOOLEAN) {
2342				if (!ucl_maybe_parse_boolean (obj, dst, obj->len) && (flags & UCL_STRING_PARSE_NUMBER)) {
2343					ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
2344							flags & UCL_STRING_PARSE_DOUBLE,
2345							flags & UCL_STRING_PARSE_BYTES,
2346							flags & UCL_STRING_PARSE_TIME);
2347				}
2348			}
2349			else {
2350				ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
2351						flags & UCL_STRING_PARSE_DOUBLE,
2352						flags & UCL_STRING_PARSE_BYTES,
2353						flags & UCL_STRING_PARSE_TIME);
2354			}
2355		}
2356	}
2357
2358	return obj;
2359}
2360
2361static bool
2362ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt,
2363		const char *key, size_t keylen, bool copy_key, bool merge, bool replace)
2364{
2365	ucl_object_t *found, *tmp;
2366	const ucl_object_t *cur;
2367	ucl_object_iter_t it = NULL;
2368	const char *p;
2369	int ret = true;
2370
2371	if (elt == NULL || key == NULL) {
2372		return false;
2373	}
2374
2375	if (top == NULL) {
2376		return false;
2377	}
2378
2379	if (top->type != UCL_OBJECT) {
2380		/* It is possible to convert NULL type to an object */
2381		if (top->type == UCL_NULL) {
2382			top->type = UCL_OBJECT;
2383		}
2384		else {
2385			/* Refuse converting of other object types */
2386			return false;
2387		}
2388	}
2389
2390	if (top->value.ov == NULL) {
2391		top->value.ov = ucl_hash_create (false);
2392	}
2393
2394	if (keylen == 0) {
2395		keylen = strlen (key);
2396	}
2397
2398	for (p = key; p < key + keylen; p ++) {
2399		if (ucl_test_character (*p, UCL_CHARACTER_UCL_UNSAFE)) {
2400			elt->flags |= UCL_OBJECT_NEED_KEY_ESCAPE;
2401			break;
2402		}
2403	}
2404
2405	/* workaround for some use cases */
2406	if (elt->trash_stack[UCL_TRASH_KEY] != NULL &&
2407			key != (const char *)elt->trash_stack[UCL_TRASH_KEY]) {
2408		/* Remove copied key */
2409		free (elt->trash_stack[UCL_TRASH_KEY]);
2410		elt->trash_stack[UCL_TRASH_KEY] = NULL;
2411		elt->flags &= ~UCL_OBJECT_ALLOCATED_KEY;
2412	}
2413
2414	elt->key = key;
2415	elt->keylen = keylen;
2416
2417	if (copy_key) {
2418		ucl_copy_key_trash (elt);
2419	}
2420
2421	found = __DECONST (ucl_object_t *, ucl_hash_search_obj (top->value.ov, elt));
2422
2423	if (found == NULL) {
2424		top->value.ov = ucl_hash_insert_object (top->value.ov, elt, false);
2425		top->len ++;
2426		if (replace) {
2427			ret = false;
2428		}
2429	}
2430	else {
2431		if (replace) {
2432			ucl_hash_replace (top->value.ov, found, elt);
2433			ucl_object_unref (found);
2434		}
2435		else if (merge) {
2436			if (found->type != UCL_OBJECT && elt->type == UCL_OBJECT) {
2437				/* Insert old elt to new one */
2438				ucl_object_insert_key_common (elt, found, found->key,
2439						found->keylen, copy_key, false, false);
2440				ucl_hash_delete (top->value.ov, found);
2441				top->value.ov = ucl_hash_insert_object (top->value.ov, elt, false);
2442			}
2443			else if (found->type == UCL_OBJECT && elt->type != UCL_OBJECT) {
2444				/* Insert new to old */
2445				ucl_object_insert_key_common (found, elt, elt->key,
2446						elt->keylen, copy_key, false, false);
2447			}
2448			else if (found->type == UCL_OBJECT && elt->type == UCL_OBJECT) {
2449				/* Mix two hashes */
2450				while ((cur = ucl_object_iterate (elt, &it, true)) != NULL) {
2451					tmp = ucl_object_ref (cur);
2452					ucl_object_insert_key_common (found, tmp, cur->key,
2453							cur->keylen, copy_key, true, false);
2454				}
2455				ucl_object_unref (elt);
2456			}
2457			else {
2458				/* Just make a list of scalars */
2459				DL_CONCAT (found, elt);
2460			}
2461		}
2462		else {
2463			DL_CONCAT (found, elt);
2464		}
2465	}
2466
2467	return ret;
2468}
2469
2470bool
2471ucl_object_delete_keyl (ucl_object_t *top, const char *key, size_t keylen)
2472{
2473	ucl_object_t *found;
2474
2475	if (top == NULL || key == NULL) {
2476		return false;
2477	}
2478
2479	found = __DECONST (ucl_object_t *, ucl_object_lookup_len (top, key, keylen));
2480
2481	if (found == NULL) {
2482		return false;
2483	}
2484
2485	ucl_hash_delete (top->value.ov, found);
2486	ucl_object_unref (found);
2487	top->len --;
2488
2489	return true;
2490}
2491
2492bool
2493ucl_object_delete_key (ucl_object_t *top, const char *key)
2494{
2495	return ucl_object_delete_keyl (top, key, strlen (key));
2496}
2497
2498ucl_object_t*
2499ucl_object_pop_keyl (ucl_object_t *top, const char *key, size_t keylen)
2500{
2501	const ucl_object_t *found;
2502
2503	if (top == NULL || key == NULL) {
2504		return false;
2505	}
2506	found = ucl_object_lookup_len (top, key, keylen);
2507
2508	if (found == NULL) {
2509		return NULL;
2510	}
2511	ucl_hash_delete (top->value.ov, found);
2512	top->len --;
2513
2514	return __DECONST (ucl_object_t *, found);
2515}
2516
2517ucl_object_t*
2518ucl_object_pop_key (ucl_object_t *top, const char *key)
2519{
2520	return ucl_object_pop_keyl (top, key, strlen (key));
2521}
2522
2523bool
2524ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt,
2525		const char *key, size_t keylen, bool copy_key)
2526{
2527	return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, false);
2528}
2529
2530bool
2531ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt,
2532		const char *key, size_t keylen, bool copy_key)
2533{
2534	return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, true, false);
2535}
2536
2537bool
2538ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt,
2539		const char *key, size_t keylen, bool copy_key)
2540{
2541	return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, true);
2542}
2543
2544bool
2545ucl_object_merge (ucl_object_t *top, ucl_object_t *elt, bool copy)
2546{
2547	ucl_object_t *cur = NULL, *cp = NULL, *found = NULL;
2548	ucl_object_iter_t iter = NULL;
2549
2550	if (top == NULL || elt == NULL) {
2551		return false;
2552	}
2553
2554	if (top->type == UCL_ARRAY) {
2555		if (elt->type == UCL_ARRAY) {
2556			/* Merge two arrays */
2557			return ucl_array_merge (top, elt, copy);
2558		}
2559		else {
2560			if (copy) {
2561				ucl_array_append (top, ucl_object_copy (elt));
2562
2563				return true;
2564			}
2565			else {
2566				ucl_array_append (top, ucl_object_ref (elt));
2567
2568				return true;
2569			}
2570		}
2571	}
2572	else if (top->type == UCL_OBJECT) {
2573		if (elt->type == UCL_OBJECT) {
2574			/* Mix two hashes */
2575			while ((cur = (ucl_object_t *) ucl_hash_iterate (elt->value.ov,
2576					&iter))) {
2577
2578				if (copy) {
2579					cp = ucl_object_copy (cur);
2580				} else {
2581					cp = ucl_object_ref (cur);
2582				}
2583
2584				found = __DECONST(ucl_object_t *,
2585						ucl_hash_search (top->value.ov, cp->key, cp->keylen));
2586
2587				if (found == NULL) {
2588					/* The key does not exist */
2589					top->value.ov = ucl_hash_insert_object (top->value.ov, cp,
2590							false);
2591					top->len++;
2592				}
2593				else {
2594					/* The key already exists, merge it recursively */
2595					if (found->type == UCL_OBJECT || found->type == UCL_ARRAY) {
2596						if (!ucl_object_merge (found, cp, copy)) {
2597							return false;
2598						}
2599					}
2600					else {
2601						ucl_hash_replace (top->value.ov, found, cp);
2602						ucl_object_unref (found);
2603					}
2604				}
2605			}
2606		}
2607		else {
2608			if (copy) {
2609				cp = ucl_object_copy (elt);
2610			}
2611			else {
2612				cp = ucl_object_ref (elt);
2613			}
2614
2615			found = __DECONST(ucl_object_t *,
2616					ucl_hash_search (top->value.ov, cp->key, cp->keylen));
2617
2618			if (found == NULL) {
2619				/* The key does not exist */
2620				top->value.ov = ucl_hash_insert_object (top->value.ov, cp,
2621						false);
2622				top->len++;
2623			}
2624			else {
2625				/* The key already exists, merge it recursively */
2626				if (found->type == UCL_OBJECT || found->type == UCL_ARRAY) {
2627					if (!ucl_object_merge (found, cp, copy)) {
2628						return false;
2629					}
2630				}
2631				else {
2632					ucl_hash_replace (top->value.ov, found, cp);
2633					ucl_object_unref (found);
2634				}
2635			}
2636		}
2637	}
2638	else {
2639		/* Cannot merge trivial objects */
2640		return false;
2641	}
2642
2643	return true;
2644}
2645
2646const ucl_object_t *
2647ucl_object_lookup_len (const ucl_object_t *obj, const char *key, size_t klen)
2648{
2649	const ucl_object_t *ret;
2650	ucl_object_t srch;
2651
2652	if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) {
2653		return NULL;
2654	}
2655
2656	srch.key = key;
2657	srch.keylen = klen;
2658	ret = ucl_hash_search_obj (obj->value.ov, &srch);
2659
2660	return ret;
2661}
2662
2663const ucl_object_t *
2664ucl_object_lookup (const ucl_object_t *obj, const char *key)
2665{
2666	if (key == NULL) {
2667		return NULL;
2668	}
2669
2670	return ucl_object_lookup_len (obj, key, strlen (key));
2671}
2672
2673const ucl_object_t*
2674ucl_object_lookup_any (const ucl_object_t *obj,
2675		const char *key, ...)
2676{
2677	va_list ap;
2678	const ucl_object_t *ret = NULL;
2679	const char *nk = NULL;
2680
2681	if (obj == NULL || key == NULL) {
2682		return NULL;
2683	}
2684
2685	ret = ucl_object_lookup_len (obj, key, strlen (key));
2686
2687	if (ret == NULL) {
2688		va_start (ap, key);
2689
2690		while (ret == NULL) {
2691			nk = va_arg (ap, const char *);
2692
2693			if (nk == NULL) {
2694				break;
2695			}
2696			else {
2697				ret = ucl_object_lookup_len (obj, nk, strlen (nk));
2698			}
2699		}
2700
2701		va_end (ap);
2702	}
2703
2704	return ret;
2705}
2706
2707const ucl_object_t*
2708ucl_object_iterate_with_error (const ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values,
2709    int *ep)
2710{
2711	const ucl_object_t *elt = NULL;
2712
2713	if (obj == NULL || iter == NULL) {
2714		return NULL;
2715	}
2716
2717	if (expand_values) {
2718		switch (obj->type) {
2719		case UCL_OBJECT:
2720			return (const ucl_object_t*)ucl_hash_iterate2 (obj->value.ov, iter, ep);
2721			break;
2722		case UCL_ARRAY: {
2723			unsigned int idx;
2724			UCL_ARRAY_GET (vec, obj);
2725			idx = (unsigned int)(uintptr_t)(*iter);
2726
2727			if (vec != NULL) {
2728				while (idx < kv_size (*vec)) {
2729					if ((elt = kv_A (*vec, idx)) != NULL) {
2730						idx ++;
2731						break;
2732					}
2733					idx ++;
2734				}
2735				*iter = (void *)(uintptr_t)idx;
2736			}
2737
2738			return elt;
2739			break;
2740		}
2741		default:
2742			/* Go to linear iteration */
2743			break;
2744		}
2745	}
2746	/* Treat everything as a linear list */
2747	elt = *iter;
2748	if (elt == NULL) {
2749		elt = obj;
2750	}
2751	else if (elt == obj) {
2752		return NULL;
2753	}
2754	*iter = __DECONST (void *, elt->next ? elt->next : obj);
2755	return elt;
2756
2757	/* Not reached */
2758	return NULL;
2759}
2760
2761enum ucl_safe_iter_flags {
2762	UCL_ITERATE_FLAG_UNDEFINED = 0,
2763	UCL_ITERATE_FLAG_INSIDE_ARRAY,
2764	UCL_ITERATE_FLAG_INSIDE_OBJECT,
2765	UCL_ITERATE_FLAG_IMPLICIT,
2766	UCL_ITERATE_FLAG_EXCEPTION
2767};
2768
2769static const char safe_iter_magic[4] = {'u', 'i', 't', 'e'};
2770struct ucl_object_safe_iter {
2771	char magic[4]; /* safety check */
2772	uint32_t flags;
2773	const ucl_object_t *impl_it; /* implicit object iteration */
2774	ucl_object_iter_t expl_it; /* explicit iteration */
2775};
2776
2777#define UCL_SAFE_ITER(ptr) (struct ucl_object_safe_iter *)(ptr)
2778#define UCL_SAFE_ITER_CHECK(it) do { \
2779	assert (it != NULL); \
2780	assert (memcmp (it->magic, safe_iter_magic, sizeof (it->magic)) == 0); \
2781 } while (0)
2782
2783ucl_object_iter_t
2784ucl_object_iterate_new (const ucl_object_t *obj)
2785{
2786	struct ucl_object_safe_iter *it;
2787
2788	it = UCL_ALLOC (sizeof (*it));
2789	if (it != NULL) {
2790		memcpy (it->magic, safe_iter_magic, sizeof (it->magic));
2791		it->flags = UCL_ITERATE_FLAG_UNDEFINED;
2792		it->expl_it = NULL;
2793		it->impl_it = obj;
2794	}
2795
2796	return (ucl_object_iter_t)it;
2797}
2798
2799bool
2800ucl_object_iter_chk_excpn(ucl_object_iter_t *it)
2801{
2802        struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it);
2803
2804        UCL_SAFE_ITER_CHECK (rit);
2805
2806	return (rit->flags == UCL_ITERATE_FLAG_EXCEPTION);
2807}
2808
2809ucl_object_iter_t
2810ucl_object_iterate_reset (ucl_object_iter_t it, const ucl_object_t *obj)
2811{
2812	struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it);
2813
2814	UCL_SAFE_ITER_CHECK (rit);
2815
2816	if (rit->expl_it != NULL) {
2817		if (rit->flags == UCL_ITERATE_FLAG_INSIDE_OBJECT) {
2818			UCL_FREE (sizeof (*rit->expl_it), rit->expl_it);
2819		}
2820	}
2821
2822	rit->impl_it = obj;
2823	rit->expl_it = NULL;
2824	rit->flags = UCL_ITERATE_FLAG_UNDEFINED;
2825
2826	return it;
2827}
2828
2829const ucl_object_t*
2830ucl_object_iterate_safe (ucl_object_iter_t it, bool expand_values)
2831{
2832	return ucl_object_iterate_full (it, expand_values ? UCL_ITERATE_BOTH :
2833			UCL_ITERATE_IMPLICIT);
2834}
2835
2836const ucl_object_t*
2837ucl_object_iterate_full (ucl_object_iter_t it, enum ucl_iterate_type type)
2838{
2839	struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it);
2840	const ucl_object_t *ret = NULL;
2841	int ern;
2842
2843	UCL_SAFE_ITER_CHECK (rit);
2844
2845	if (rit->impl_it == NULL) {
2846		return NULL;
2847	}
2848
2849	if (rit->impl_it->type == UCL_OBJECT) {
2850		rit->flags = UCL_ITERATE_FLAG_INSIDE_OBJECT;
2851		ret = ucl_object_iterate_with_error (rit->impl_it, &rit->expl_it, true, &ern);
2852
2853		if (ret == NULL && ern != 0) {
2854			rit->flags = UCL_ITERATE_FLAG_EXCEPTION;
2855			return NULL;
2856		}
2857
2858		if (ret == NULL && (type & UCL_ITERATE_IMPLICIT)) {
2859			/* Need to switch to another implicit object in chain */
2860			rit->impl_it = rit->impl_it->next;
2861			rit->expl_it = NULL;
2862
2863			return ucl_object_iterate_safe (it, type);
2864		}
2865	}
2866	else if (rit->impl_it->type == UCL_ARRAY) {
2867		rit->flags = UCL_ITERATE_FLAG_INSIDE_ARRAY;
2868		ret = ucl_object_iterate (rit->impl_it, &rit->expl_it, true);
2869
2870		if (ret == NULL && (type & UCL_ITERATE_IMPLICIT)) {
2871			/* Need to switch to another implicit object in chain */
2872			rit->impl_it = rit->impl_it->next;
2873			rit->expl_it = NULL;
2874
2875			return ucl_object_iterate_safe (it, type);
2876		}
2877	}
2878	else {
2879		/* Just iterate over the implicit array */
2880		rit->flags = UCL_ITERATE_FLAG_IMPLICIT;
2881		ret = rit->impl_it;
2882		rit->impl_it = rit->impl_it->next;
2883
2884		if (type & UCL_ITERATE_EXPLICIT) {
2885			/* We flatten objects if need to expand values */
2886			if (ret->type == UCL_OBJECT || ret->type == UCL_ARRAY) {
2887				return ucl_object_iterate_safe (it, type);
2888			}
2889		}
2890	}
2891
2892	return ret;
2893}
2894
2895void
2896ucl_object_iterate_free (ucl_object_iter_t it)
2897{
2898	struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it);
2899
2900	UCL_SAFE_ITER_CHECK (rit);
2901
2902	if (rit->expl_it != NULL) {
2903		if (rit->flags == UCL_ITERATE_FLAG_INSIDE_OBJECT) {
2904			UCL_FREE (sizeof (*rit->expl_it), rit->expl_it);
2905		}
2906	}
2907
2908	UCL_FREE (sizeof (*rit), it);
2909}
2910
2911const ucl_object_t *
2912ucl_object_lookup_path (const ucl_object_t *top, const char *path_in) {
2913	return ucl_object_lookup_path_char (top, path_in, '.');
2914}
2915
2916
2917const ucl_object_t *
2918ucl_object_lookup_path_char (const ucl_object_t *top, const char *path_in, const char sep) {
2919	const ucl_object_t *o = NULL, *found;
2920	const char *p, *c;
2921	char *err_str;
2922	unsigned index;
2923
2924	if (path_in == NULL || top == NULL) {
2925		return NULL;
2926	}
2927
2928	found = NULL;
2929	p = path_in;
2930
2931	/* Skip leading dots */
2932	while (*p == sep) {
2933		p ++;
2934	}
2935
2936	c = p;
2937	while (*p != '\0') {
2938		p ++;
2939		if (*p == sep || *p == '\0') {
2940			if (p > c) {
2941				switch (top->type) {
2942				case UCL_ARRAY:
2943					/* Key should be an int */
2944					index = strtoul (c, &err_str, 10);
2945					if (err_str != NULL && (*err_str != sep && *err_str != '\0')) {
2946						return NULL;
2947					}
2948					o = ucl_array_find_index (top, index);
2949					break;
2950				default:
2951					o = ucl_object_lookup_len (top, c, p - c);
2952					break;
2953				}
2954				if (o == NULL) {
2955					return NULL;
2956				}
2957				top = o;
2958			}
2959			if (*p != '\0') {
2960				c = p + 1;
2961			}
2962		}
2963	}
2964	found = o;
2965
2966	return found;
2967}
2968
2969
2970ucl_object_t *
2971ucl_object_new (void)
2972{
2973	return ucl_object_typed_new (UCL_NULL);
2974}
2975
2976ucl_object_t *
2977ucl_object_typed_new (ucl_type_t type)
2978{
2979	return ucl_object_new_full (type, 0);
2980}
2981
2982ucl_object_t *
2983ucl_object_new_full (ucl_type_t type, unsigned priority)
2984{
2985	ucl_object_t *new;
2986
2987	if (type != UCL_USERDATA) {
2988		new = UCL_ALLOC (sizeof (ucl_object_t));
2989		if (new != NULL) {
2990			memset (new, 0, sizeof (ucl_object_t));
2991			new->ref = 1;
2992			new->type = (type <= UCL_NULL ? type : UCL_NULL);
2993			new->next = NULL;
2994			new->prev = new;
2995			ucl_object_set_priority (new, priority);
2996
2997			if (type == UCL_ARRAY) {
2998				new->value.av = UCL_ALLOC (sizeof (ucl_array_t));
2999				if (new->value.av) {
3000					memset (new->value.av, 0, sizeof (ucl_array_t));
3001					UCL_ARRAY_GET (vec, new);
3002
3003					/* Preallocate some space for arrays */
3004					kv_resize_safe (ucl_object_t *, *vec, 8, enomem);
3005				}
3006			}
3007		}
3008	}
3009	else {
3010		new = ucl_object_new_userdata (NULL, NULL, NULL);
3011		ucl_object_set_priority (new, priority);
3012	}
3013enomem:
3014	return new;
3015}
3016
3017bool ucl_object_reserve (ucl_object_t *obj, size_t reserved)
3018{
3019	if (obj->type == UCL_ARRAY) {
3020		UCL_ARRAY_GET (vec, obj);
3021
3022		if (vec->m < reserved) {
3023			/* Preallocate some space for arrays */
3024			kv_resize_safe (ucl_object_t *, *vec, reserved, e0);
3025		}
3026	}
3027	else if (obj->type == UCL_OBJECT) {
3028		ucl_hash_reserve (obj->value.ov, reserved);
3029	}
3030	return true;
3031e0:
3032	return false;
3033}
3034
3035ucl_object_t*
3036ucl_object_new_userdata (ucl_userdata_dtor dtor,
3037		ucl_userdata_emitter emitter,
3038		void *ptr)
3039{
3040	struct ucl_object_userdata *new;
3041	size_t nsize = sizeof (*new);
3042
3043	new = UCL_ALLOC (nsize);
3044	if (new != NULL) {
3045		memset (new, 0, nsize);
3046		new->obj.ref = 1;
3047		new->obj.type = UCL_USERDATA;
3048		new->obj.next = NULL;
3049		new->obj.prev = (ucl_object_t *)new;
3050		new->dtor = dtor;
3051		new->emitter = emitter;
3052		new->obj.value.ud = ptr;
3053	}
3054
3055	return (ucl_object_t *)new;
3056}
3057
3058ucl_type_t
3059ucl_object_type (const ucl_object_t *obj)
3060{
3061	if (obj == NULL) {
3062		return UCL_NULL;
3063	}
3064
3065	return obj->type;
3066}
3067
3068ucl_object_t*
3069ucl_object_fromstring (const char *str)
3070{
3071	return ucl_object_fromstring_common (str, 0, UCL_STRING_ESCAPE);
3072}
3073
3074ucl_object_t *
3075ucl_object_fromlstring (const char *str, size_t len)
3076{
3077	return ucl_object_fromstring_common (str, len, UCL_STRING_ESCAPE);
3078}
3079
3080ucl_object_t *
3081ucl_object_fromint (int64_t iv)
3082{
3083	ucl_object_t *obj;
3084
3085	obj = ucl_object_new ();
3086	if (obj != NULL) {
3087		obj->type = UCL_INT;
3088		obj->value.iv = iv;
3089	}
3090
3091	return obj;
3092}
3093
3094ucl_object_t *
3095ucl_object_fromdouble (double dv)
3096{
3097	ucl_object_t *obj;
3098
3099	obj = ucl_object_new ();
3100	if (obj != NULL) {
3101		obj->type = UCL_FLOAT;
3102		obj->value.dv = dv;
3103	}
3104
3105	return obj;
3106}
3107
3108ucl_object_t*
3109ucl_object_frombool (bool bv)
3110{
3111	ucl_object_t *obj;
3112
3113	obj = ucl_object_new ();
3114	if (obj != NULL) {
3115		obj->type = UCL_BOOLEAN;
3116		obj->value.iv = bv;
3117	}
3118
3119	return obj;
3120}
3121
3122bool
3123ucl_array_append (ucl_object_t *top, ucl_object_t *elt)
3124{
3125	UCL_ARRAY_GET (vec, top);
3126
3127	if (elt == NULL || top == NULL) {
3128		return false;
3129	}
3130
3131	if (vec == NULL) {
3132		vec = UCL_ALLOC (sizeof (*vec));
3133
3134		if (vec == NULL) {
3135			return false;
3136		}
3137
3138		kv_init (*vec);
3139		top->value.av = (void *)vec;
3140	}
3141
3142	kv_push_safe (ucl_object_t *, *vec, elt, e0);
3143
3144	top->len ++;
3145
3146	return true;
3147e0:
3148	return false;
3149}
3150
3151bool
3152ucl_array_prepend (ucl_object_t *top, ucl_object_t *elt)
3153{
3154	UCL_ARRAY_GET (vec, top);
3155
3156	if (elt == NULL || top == NULL) {
3157		return false;
3158	}
3159
3160	if (vec == NULL) {
3161		vec = UCL_ALLOC (sizeof (*vec));
3162		kv_init (*vec);
3163		top->value.av = (void *)vec;
3164		kv_push_safe (ucl_object_t *, *vec, elt, e0);
3165	}
3166	else {
3167		/* Slow O(n) algorithm */
3168		kv_prepend_safe (ucl_object_t *, *vec, elt, e0);
3169	}
3170
3171	top->len ++;
3172
3173	return true;
3174e0:
3175	return false;
3176}
3177
3178bool
3179ucl_array_merge (ucl_object_t *top, ucl_object_t *elt, bool copy)
3180{
3181	unsigned i;
3182	ucl_object_t *cp = NULL;
3183	ucl_object_t **obj;
3184
3185	if (elt == NULL || top == NULL || top->type != UCL_ARRAY || elt->type != UCL_ARRAY) {
3186		return false;
3187	}
3188
3189	if (copy) {
3190		cp = ucl_object_copy (elt);
3191	}
3192	else {
3193		cp = ucl_object_ref (elt);
3194	}
3195
3196	UCL_ARRAY_GET (v1, top);
3197	UCL_ARRAY_GET (v2, cp);
3198
3199	if (v1 && v2) {
3200		kv_concat_safe (ucl_object_t *, *v1, *v2, e0);
3201
3202		for (i = v2->n; i < v1->n; i ++) {
3203			obj = &kv_A (*v1, i);
3204			if (*obj == NULL) {
3205				continue;
3206			}
3207			top->len ++;
3208		}
3209	}
3210
3211	return true;
3212e0:
3213	return false;
3214}
3215
3216ucl_object_t *
3217ucl_array_delete (ucl_object_t *top, ucl_object_t *elt)
3218{
3219	UCL_ARRAY_GET (vec, top);
3220	ucl_object_t *ret = NULL;
3221	unsigned i;
3222
3223	if (vec == NULL) {
3224		return NULL;
3225	}
3226
3227	for (i = 0; i < vec->n; i ++) {
3228		if (kv_A (*vec, i) == elt) {
3229			kv_del (ucl_object_t *, *vec, i);
3230			ret = elt;
3231			top->len --;
3232			break;
3233		}
3234	}
3235
3236	return ret;
3237}
3238
3239const ucl_object_t *
3240ucl_array_head (const ucl_object_t *top)
3241{
3242	UCL_ARRAY_GET (vec, top);
3243
3244	if (vec == NULL || top == NULL || top->type != UCL_ARRAY ||
3245			top->value.av == NULL) {
3246		return NULL;
3247	}
3248
3249	return (vec->n > 0 ? vec->a[0] : NULL);
3250}
3251
3252const ucl_object_t *
3253ucl_array_tail (const ucl_object_t *top)
3254{
3255	UCL_ARRAY_GET (vec, top);
3256
3257	if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
3258		return NULL;
3259	}
3260
3261	return (vec->n > 0 ? vec->a[vec->n - 1] : NULL);
3262}
3263
3264ucl_object_t *
3265ucl_array_pop_last (ucl_object_t *top)
3266{
3267	UCL_ARRAY_GET (vec, top);
3268	ucl_object_t **obj, *ret = NULL;
3269
3270	if (vec != NULL && vec->n > 0) {
3271		obj = &kv_A (*vec, vec->n - 1);
3272		ret = *obj;
3273		kv_del (ucl_object_t *, *vec, vec->n - 1);
3274		top->len --;
3275	}
3276
3277	return ret;
3278}
3279
3280ucl_object_t *
3281ucl_array_pop_first (ucl_object_t *top)
3282{
3283	UCL_ARRAY_GET (vec, top);
3284	ucl_object_t **obj, *ret = NULL;
3285
3286	if (vec != NULL && vec->n > 0) {
3287		obj = &kv_A (*vec, 0);
3288		ret = *obj;
3289		kv_del (ucl_object_t *, *vec, 0);
3290		top->len --;
3291	}
3292
3293	return ret;
3294}
3295
3296unsigned int
3297ucl_array_size (const ucl_object_t *top)
3298{
3299	if (top == NULL || top->type != UCL_ARRAY) {
3300		return 0;
3301	}
3302
3303	UCL_ARRAY_GET (vec, top);
3304
3305	if (vec != NULL) {
3306		return kv_size(*vec);
3307	}
3308
3309	return 0;
3310}
3311
3312const ucl_object_t *
3313ucl_array_find_index (const ucl_object_t *top, unsigned int index)
3314{
3315	UCL_ARRAY_GET (vec, top);
3316
3317	if (vec != NULL && vec->n > 0 && index < vec->n) {
3318		return kv_A (*vec, index);
3319	}
3320
3321	return NULL;
3322}
3323
3324unsigned int
3325ucl_array_index_of (ucl_object_t *top, ucl_object_t *elt)
3326{
3327	UCL_ARRAY_GET (vec, top);
3328	unsigned i;
3329
3330	if (vec == NULL) {
3331		return (unsigned int)(-1);
3332	}
3333
3334	for (i = 0; i < vec->n; i ++) {
3335		if (kv_A (*vec, i) == elt) {
3336			return i;
3337		}
3338	}
3339
3340	return (unsigned int)(-1);
3341}
3342
3343ucl_object_t *
3344ucl_array_replace_index (ucl_object_t *top, ucl_object_t *elt,
3345	unsigned int index)
3346{
3347	UCL_ARRAY_GET (vec, top);
3348	ucl_object_t *ret = NULL;
3349
3350	if (vec != NULL && vec->n > 0 && index < vec->n) {
3351		ret = kv_A (*vec, index);
3352		kv_A (*vec, index) = elt;
3353	}
3354
3355	return ret;
3356}
3357
3358ucl_object_t *
3359ucl_elt_append (ucl_object_t *head, ucl_object_t *elt)
3360{
3361
3362	if (head == NULL) {
3363		elt->next = NULL;
3364		elt->prev = elt;
3365		head = elt;
3366	}
3367	else {
3368		elt->prev = head->prev;
3369		head->prev->next = elt;
3370		head->prev = elt;
3371		elt->next = NULL;
3372	}
3373
3374	return head;
3375}
3376
3377bool
3378ucl_object_todouble_safe (const ucl_object_t *obj, double *target)
3379{
3380	if (obj == NULL || target == NULL) {
3381		return false;
3382	}
3383	switch (obj->type) {
3384	case UCL_INT:
3385		*target = obj->value.iv; /* Probably could cause overflow */
3386		break;
3387	case UCL_FLOAT:
3388	case UCL_TIME:
3389		*target = obj->value.dv;
3390		break;
3391	default:
3392		return false;
3393	}
3394
3395	return true;
3396}
3397
3398double
3399ucl_object_todouble (const ucl_object_t *obj)
3400{
3401	double result = 0.;
3402
3403	ucl_object_todouble_safe (obj, &result);
3404	return result;
3405}
3406
3407bool
3408ucl_object_toint_safe (const ucl_object_t *obj, int64_t *target)
3409{
3410	if (obj == NULL || target == NULL) {
3411		return false;
3412	}
3413	switch (obj->type) {
3414	case UCL_INT:
3415		*target = obj->value.iv;
3416		break;
3417	case UCL_FLOAT:
3418	case UCL_TIME:
3419		*target = obj->value.dv; /* Losing of decimal points */
3420		break;
3421	default:
3422		return false;
3423	}
3424
3425	return true;
3426}
3427
3428int64_t
3429ucl_object_toint (const ucl_object_t *obj)
3430{
3431	int64_t result = 0;
3432
3433	ucl_object_toint_safe (obj, &result);
3434	return result;
3435}
3436
3437bool
3438ucl_object_toboolean_safe (const ucl_object_t *obj, bool *target)
3439{
3440	if (obj == NULL || target == NULL) {
3441		return false;
3442	}
3443	switch (obj->type) {
3444	case UCL_BOOLEAN:
3445		*target = (obj->value.iv == true);
3446		break;
3447	default:
3448		return false;
3449	}
3450
3451	return true;
3452}
3453
3454bool
3455ucl_object_toboolean (const ucl_object_t *obj)
3456{
3457	bool result = false;
3458
3459	ucl_object_toboolean_safe (obj, &result);
3460	return result;
3461}
3462
3463bool
3464ucl_object_tostring_safe (const ucl_object_t *obj, const char **target)
3465{
3466	if (obj == NULL || target == NULL) {
3467		return false;
3468	}
3469
3470	switch (obj->type) {
3471	case UCL_STRING:
3472		if (!(obj->flags & UCL_OBJECT_BINARY)) {
3473			*target = ucl_copy_value_trash (obj);
3474		}
3475		break;
3476	default:
3477		return false;
3478	}
3479
3480	return true;
3481}
3482
3483const char *
3484ucl_object_tostring (const ucl_object_t *obj)
3485{
3486	const char *result = NULL;
3487
3488	ucl_object_tostring_safe (obj, &result);
3489	return result;
3490}
3491
3492const char *
3493ucl_object_tostring_forced (const ucl_object_t *obj)
3494{
3495	/* TODO: For binary strings we might encode string here */
3496	if (!(obj->flags & UCL_OBJECT_BINARY)) {
3497		return ucl_copy_value_trash (obj);
3498	}
3499
3500	return NULL;
3501}
3502
3503bool
3504ucl_object_tolstring_safe (const ucl_object_t *obj, const char **target, size_t *tlen)
3505{
3506	if (obj == NULL || target == NULL) {
3507		return false;
3508	}
3509	switch (obj->type) {
3510	case UCL_STRING:
3511		*target = obj->value.sv;
3512		if (tlen != NULL) {
3513			*tlen = obj->len;
3514		}
3515		break;
3516	default:
3517		return false;
3518	}
3519
3520	return true;
3521}
3522
3523const char *
3524ucl_object_tolstring (const ucl_object_t *obj, size_t *tlen)
3525{
3526	const char *result = NULL;
3527
3528	ucl_object_tolstring_safe (obj, &result, tlen);
3529	return result;
3530}
3531
3532const char *
3533ucl_object_key (const ucl_object_t *obj)
3534{
3535	return ucl_copy_key_trash (obj);
3536}
3537
3538const char *
3539ucl_object_keyl (const ucl_object_t *obj, size_t *len)
3540{
3541	if (len == NULL || obj == NULL) {
3542		return NULL;
3543	}
3544	*len = obj->keylen;
3545	return obj->key;
3546}
3547
3548ucl_object_t *
3549ucl_object_ref (const ucl_object_t *obj)
3550{
3551	ucl_object_t *res = NULL;
3552
3553	if (obj != NULL) {
3554		if (obj->flags & UCL_OBJECT_EPHEMERAL) {
3555			/*
3556			 * Use deep copy for ephemeral objects, note that its refcount
3557			 * is NOT increased, since ephemeral objects does not need refcount
3558			 * at all
3559			 */
3560			res = ucl_object_copy (obj);
3561		}
3562		else {
3563			res = __DECONST (ucl_object_t *, obj);
3564#ifdef HAVE_ATOMIC_BUILTINS
3565			(void)__sync_add_and_fetch (&res->ref, 1);
3566#else
3567			res->ref ++;
3568#endif
3569		}
3570	}
3571	return res;
3572}
3573
3574static ucl_object_t *
3575ucl_object_copy_internal (const ucl_object_t *other, bool allow_array)
3576{
3577
3578	ucl_object_t *new;
3579	ucl_object_iter_t it = NULL;
3580	const ucl_object_t *cur;
3581
3582	new = malloc (sizeof (*new));
3583
3584	if (new != NULL) {
3585		memcpy (new, other, sizeof (*new));
3586		if (other->flags & UCL_OBJECT_EPHEMERAL) {
3587			/* Copied object is always non ephemeral */
3588			new->flags &= ~UCL_OBJECT_EPHEMERAL;
3589		}
3590		new->ref = 1;
3591		/* Unlink from others */
3592		new->next = NULL;
3593		new->prev = new;
3594
3595		/* deep copy of values stored */
3596		if (other->trash_stack[UCL_TRASH_KEY] != NULL) {
3597			new->trash_stack[UCL_TRASH_KEY] =
3598					strdup (other->trash_stack[UCL_TRASH_KEY]);
3599			if (other->key == (const char *)other->trash_stack[UCL_TRASH_KEY]) {
3600				new->key = new->trash_stack[UCL_TRASH_KEY];
3601			}
3602		}
3603		if (other->trash_stack[UCL_TRASH_VALUE] != NULL) {
3604			new->trash_stack[UCL_TRASH_VALUE] =
3605					strdup (other->trash_stack[UCL_TRASH_VALUE]);
3606			if (new->type == UCL_STRING) {
3607				new->value.sv = new->trash_stack[UCL_TRASH_VALUE];
3608			}
3609		}
3610
3611		if (other->type == UCL_ARRAY || other->type == UCL_OBJECT) {
3612			/* reset old value */
3613			memset (&new->value, 0, sizeof (new->value));
3614
3615			while ((cur = ucl_object_iterate (other, &it, true)) != NULL) {
3616				if (other->type == UCL_ARRAY) {
3617					ucl_array_append (new, ucl_object_copy_internal (cur, false));
3618				}
3619				else {
3620					ucl_object_t *cp = ucl_object_copy_internal (cur, true);
3621					if (cp != NULL) {
3622						ucl_object_insert_key (new, cp, cp->key, cp->keylen,
3623								false);
3624					}
3625				}
3626			}
3627		}
3628		else if (allow_array && other->next != NULL) {
3629			LL_FOREACH (other->next, cur) {
3630				ucl_object_t *cp = ucl_object_copy_internal (cur, false);
3631				if (cp != NULL) {
3632					DL_APPEND (new, cp);
3633				}
3634			}
3635		}
3636	}
3637
3638	return new;
3639}
3640
3641ucl_object_t *
3642ucl_object_copy (const ucl_object_t *other)
3643{
3644	return ucl_object_copy_internal (other, true);
3645}
3646
3647void
3648ucl_object_unref (ucl_object_t *obj)
3649{
3650	if (obj != NULL) {
3651#ifdef HAVE_ATOMIC_BUILTINS
3652		unsigned int rc = __sync_sub_and_fetch (&obj->ref, 1);
3653		if (rc == 0) {
3654#else
3655		if (--obj->ref == 0) {
3656#endif
3657			ucl_object_free_internal (obj, true, ucl_object_dtor_unref);
3658		}
3659	}
3660}
3661
3662int
3663ucl_object_compare (const ucl_object_t *o1, const ucl_object_t *o2)
3664{
3665	const ucl_object_t *it1, *it2;
3666	ucl_object_iter_t iter = NULL;
3667	int ret = 0;
3668
3669    // Must check for NULL or code will segfault
3670    if ((o1 == NULL) || (o2 == NULL))
3671    {
3672        // The only way this could be true is of both are NULL
3673        return (o1 == NULL) && (o2 == NULL);
3674    }
3675
3676	if (o1->type != o2->type) {
3677		return (o1->type) - (o2->type);
3678	}
3679
3680	switch (o1->type) {
3681	case UCL_STRING:
3682		if (o1->len == o2->len && o1->len > 0) {
3683			ret = strcmp (ucl_object_tostring(o1), ucl_object_tostring(o2));
3684		}
3685		else {
3686			ret = o1->len - o2->len;
3687		}
3688		break;
3689	case UCL_FLOAT:
3690	case UCL_INT:
3691	case UCL_TIME:
3692		ret = ucl_object_todouble (o1) - ucl_object_todouble (o2);
3693		break;
3694	case UCL_BOOLEAN:
3695		ret = ucl_object_toboolean (o1) - ucl_object_toboolean (o2);
3696		break;
3697	case UCL_ARRAY:
3698		if (o1->len == o2->len && o1->len > 0) {
3699			UCL_ARRAY_GET (vec1, o1);
3700			UCL_ARRAY_GET (vec2, o2);
3701			unsigned i;
3702
3703			/* Compare all elements in both arrays */
3704			for (i = 0; i < vec1->n; i ++) {
3705				it1 = kv_A (*vec1, i);
3706				it2 = kv_A (*vec2, i);
3707
3708				if (it1 == NULL && it2 != NULL) {
3709					return -1;
3710				}
3711				else if (it2 == NULL && it1 != NULL) {
3712					return 1;
3713				}
3714				else if (it1 != NULL && it2 != NULL) {
3715					ret = ucl_object_compare (it1, it2);
3716					if (ret != 0) {
3717						break;
3718					}
3719				}
3720			}
3721		}
3722		else {
3723			ret = o1->len - o2->len;
3724		}
3725		break;
3726	case UCL_OBJECT:
3727		if (o1->len == o2->len && o1->len > 0) {
3728			while ((it1 = ucl_object_iterate (o1, &iter, true)) != NULL) {
3729				it2 = ucl_object_lookup (o2, ucl_object_key (it1));
3730				if (it2 == NULL) {
3731					ret = 1;
3732					break;
3733				}
3734				ret = ucl_object_compare (it1, it2);
3735				if (ret != 0) {
3736					break;
3737				}
3738			}
3739		}
3740		else {
3741			ret = o1->len - o2->len;
3742		}
3743		break;
3744	default:
3745		ret = 0;
3746		break;
3747	}
3748
3749	return ret;
3750}
3751
3752int
3753ucl_object_compare_qsort (const ucl_object_t **o1,
3754		const ucl_object_t **o2)
3755{
3756	return ucl_object_compare (*o1, *o2);
3757}
3758
3759void
3760ucl_object_array_sort (ucl_object_t *ar,
3761		int (*cmp)(const ucl_object_t **o1, const ucl_object_t **o2))
3762{
3763	UCL_ARRAY_GET (vec, ar);
3764
3765	if (cmp == NULL || ar == NULL || ar->type != UCL_ARRAY) {
3766		return;
3767	}
3768
3769	qsort (vec->a, vec->n, sizeof (ucl_object_t *),
3770			(int (*)(const void *, const void *))cmp);
3771}
3772
3773void ucl_object_sort_keys (ucl_object_t *obj,
3774		enum ucl_object_keys_sort_flags how)
3775{
3776	if (obj != NULL && obj->type == UCL_OBJECT) {
3777		ucl_hash_sort (obj->value.ov, how);
3778	}
3779}
3780
3781#define PRIOBITS 4
3782
3783unsigned int
3784ucl_object_get_priority (const ucl_object_t *obj)
3785{
3786	if (obj == NULL) {
3787		return 0;
3788	}
3789
3790	return (obj->flags >> ((sizeof (obj->flags) * NBBY) - PRIOBITS));
3791}
3792
3793void
3794ucl_object_set_priority (ucl_object_t *obj,
3795		unsigned int priority)
3796{
3797	if (obj != NULL) {
3798		priority &= (0x1 << PRIOBITS) - 1;
3799		priority <<= ((sizeof (obj->flags) * NBBY) - PRIOBITS);
3800		priority |= obj->flags & ((1 << ((sizeof (obj->flags) * NBBY) -
3801				PRIOBITS)) - 1);
3802		obj->flags = priority;
3803	}
3804}
3805
3806bool
3807ucl_object_string_to_type (const char *input, ucl_type_t *res)
3808{
3809	if (strcasecmp (input, "object") == 0) {
3810		*res = UCL_OBJECT;
3811	}
3812	else if (strcasecmp (input, "array") == 0) {
3813		*res = UCL_ARRAY;
3814	}
3815	else if (strcasecmp (input, "integer") == 0) {
3816		*res = UCL_INT;
3817	}
3818	else if (strcasecmp (input, "number") == 0) {
3819		*res = UCL_FLOAT;
3820	}
3821	else if (strcasecmp (input, "string") == 0) {
3822		*res = UCL_STRING;
3823	}
3824	else if (strcasecmp (input, "boolean") == 0) {
3825		*res = UCL_BOOLEAN;
3826	}
3827	else if (strcasecmp (input, "null") == 0) {
3828		*res = UCL_NULL;
3829	}
3830	else if (strcasecmp (input, "userdata") == 0) {
3831		*res = UCL_USERDATA;
3832	}
3833	else {
3834		return false;
3835	}
3836
3837	return true;
3838}
3839
3840const char *
3841ucl_object_type_to_string (ucl_type_t type)
3842{
3843	const char *res = "unknown";
3844
3845	switch (type) {
3846	case UCL_OBJECT:
3847		res = "object";
3848		break;
3849	case UCL_ARRAY:
3850		res = "array";
3851		break;
3852	case UCL_INT:
3853		res = "integer";
3854		break;
3855	case UCL_FLOAT:
3856	case UCL_TIME:
3857		res = "number";
3858		break;
3859	case UCL_STRING:
3860		res = "string";
3861		break;
3862	case UCL_BOOLEAN:
3863		res = "boolean";
3864		break;
3865	case UCL_USERDATA:
3866		res = "userdata";
3867		break;
3868	case UCL_NULL:
3869		res = "null";
3870		break;
3871	}
3872
3873	return res;
3874}
3875
3876const ucl_object_t *
3877ucl_parser_get_comments (struct ucl_parser *parser)
3878{
3879	if (parser && parser->comments) {
3880		return parser->comments;
3881	}
3882
3883	return NULL;
3884}
3885
3886const ucl_object_t *
3887ucl_comments_find (const ucl_object_t *comments,
3888		const ucl_object_t *srch)
3889{
3890	if (comments && srch) {
3891		return ucl_object_lookup_len (comments, (const char *)&srch,
3892				sizeof (void *));
3893	}
3894
3895	return NULL;
3896}
3897
3898bool
3899ucl_comments_move (ucl_object_t *comments,
3900		const ucl_object_t *from, const ucl_object_t *to)
3901{
3902	const ucl_object_t *found;
3903	ucl_object_t *obj;
3904
3905	if (comments && from && to) {
3906		found = ucl_object_lookup_len (comments,
3907				(const char *)&from, sizeof (void *));
3908
3909		if (found) {
3910			/* Replace key */
3911			obj = ucl_object_ref (found);
3912			ucl_object_delete_keyl (comments, (const char *)&from,
3913					sizeof (void *));
3914			ucl_object_insert_key (comments, obj, (const char *)&to,
3915					sizeof (void *), true);
3916
3917			return true;
3918		}
3919	}
3920
3921	return false;
3922}
3923
3924void
3925ucl_comments_add (ucl_object_t *comments, const ucl_object_t *obj,
3926		const char *comment)
3927{
3928	if (comments && obj && comment) {
3929		ucl_object_insert_key (comments, ucl_object_fromstring (comment),
3930				(const char *)&obj, sizeof (void *), true);
3931	}
3932}
3933
3934void
3935ucl_parser_set_include_tracer (struct ucl_parser *parser,
3936							   ucl_include_trace_func_t func,
3937							   void *user_data)
3938{
3939	parser->include_trace_func = func;
3940	parser->include_trace_ud = user_data;
3941}
3942
3943const char *
3944ucl_parser_get_cur_file (struct ucl_parser *parser)
3945{
3946	return parser->cur_file;
3947}
3948