/ external / libucl / src / ucl_util.c
ucl_util.c
   1  /* Copyright (c) 2013, Vsevolod Stakhov
   2   * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
   3   * All rights reserved.
   4   *
   5   * Redistribution and use in source and binary forms, with or without
   6   * modification, are permitted provided that the following conditions are met:
   7   *       * Redistributions of source code must retain the above copyright
   8   *         notice, this list of conditions and the following disclaimer.
   9   *       * Redistributions in binary form must reproduce the above copyright
  10   *         notice, this list of conditions and the following disclaimer in the
  11   *         documentation and/or other materials provided with the distribution.
  12   *
  13   * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
  14   * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  15   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  16   * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
  17   * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  18   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  19   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  20   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  21   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  22   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23   */
  24  
  25  #include "ucl.h"
  26  #include "ucl_internal.h"
  27  #include "ucl_chartable.h"
  28  #include "kvec.h"
  29  #include <limits.h>
  30  #include <stdarg.h>
  31  #include <stdio.h> /* for snprintf */
  32  
  33  #ifndef _WIN32
  34  #include <glob.h>
  35  #include <sys/param.h>
  36  #else
  37  #ifndef NBBY
  38  #define NBBY 8
  39  #endif
  40  #endif
  41  
  42  #ifdef HAVE_LIBGEN_H
  43  #ifndef _WIN32
  44  #  include <libgen.h> /* For dirname */
  45  #endif
  46  #endif
  47  
  48  typedef kvec_t(ucl_object_t *) ucl_array_t;
  49  
  50  #define UCL_ARRAY_GET(ar, obj) ucl_array_t *ar = \
  51  	(ucl_array_t *)((obj) != NULL ? (obj)->value.av : NULL)
  52  
  53  #ifdef HAVE_OPENSSL
  54  #include <openssl/err.h>
  55  #include <openssl/sha.h>
  56  #include <openssl/rsa.h>
  57  #include <openssl/ssl.h>
  58  #include <openssl/evp.h>
  59  #endif
  60  
  61  #ifdef CURL_FOUND
  62  /* Seems to be broken */
  63  #define CURL_DISABLE_TYPECHECK 1
  64  #include <curl/curl.h>
  65  #endif
  66  #ifdef HAVE_FETCH_H
  67  #include <fetch.h>
  68  #endif
  69  
  70  #if defined(_WIN32)
  71  #include <windows.h>
  72  #include <io.h>
  73  #include <direct.h>
  74  
  75  #ifndef PROT_READ
  76  #define PROT_READ       1
  77  #endif
  78  #ifndef PROT_WRITE
  79  #define PROT_WRITE      2
  80  #endif
  81  #ifndef PROT_READWRITE
  82  #define PROT_READWRITE  3
  83  #endif
  84  #ifndef MAP_SHARED
  85  #define MAP_SHARED      1
  86  #endif
  87  #ifndef MAP_PRIVATE
  88  #define MAP_PRIVATE     2
  89  #endif
  90  #ifndef MAP_FAILED
  91  #define MAP_FAILED      ((void *) -1)
  92  #endif
  93  
  94  #define getcwd _getcwd
  95  #define open _open
  96  #define close _close
  97  
  98  static void *ucl_mmap(char *addr, size_t length, int prot, int access, int fd, off_t offset)
  99  {
 100  	void *map = NULL;
 101  	HANDLE handle = INVALID_HANDLE_VALUE;
 102  
 103  	switch (prot) {
 104  	default:
 105  	case PROT_READ:
 106  		{
 107  			handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READONLY, 0, length, 0);
 108  			if (!handle) break;
 109  			map = (void *) MapViewOfFile(handle, FILE_MAP_READ, 0, 0, length);
 110  			CloseHandle(handle);
 111  			break;
 112  		}
 113  	case PROT_WRITE:
 114  		{
 115  			handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READWRITE, 0, length, 0);
 116  			if (!handle) break;
 117  			map = (void *) MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, length);
 118  			CloseHandle(handle);
 119  			break;
 120  		}
 121  	case PROT_READWRITE:
 122  		{
 123  			handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READWRITE, 0, length, 0);
 124  			if (!handle) break;
 125  			map = (void *) MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, length);
 126  			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  
 136  static int ucl_munmap(void *map,size_t length)
 137  {
 138  	if (!UnmapViewOfFile(map)) {
 139  		return(-1);
 140  	}
 141  	return(0);
 142  }
 143  
 144  static 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  
 158  char *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  
 172  char *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  
 191  typedef void (*ucl_object_dtor) (ucl_object_t *obj);
 192  static void ucl_object_free_internal (ucl_object_t *obj, bool allow_rec,
 193  		ucl_object_dtor dtor);
 194  static void ucl_object_dtor_unref (ucl_object_t *obj);
 195  
 196  static void
 197  ucl_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   */
 225  static void
 226  ucl_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  
 240  static void
 241  ucl_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  
 252  static void
 253  ucl_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  
 295  void
 296  ucl_object_free (ucl_object_t *obj)
 297  {
 298  	ucl_object_free_internal (obj, true, ucl_object_dtor_free);
 299  }
 300  
 301  size_t
 302  ucl_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  
 434  size_t
 435  ucl_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  
 497  char *
 498  ucl_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  
 519  void
 520  ucl_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  
 548  char *
 549  ucl_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  
 592  ucl_object_t*
 593  ucl_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  
 602  void
 603  ucl_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  
 662  const char *
 663  ucl_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  
 676  int
 677  ucl_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  
 686  unsigned
 687  ucl_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  
 696  unsigned
 697  ucl_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  
 706  void
 707  ucl_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  
 716  bool
 717  ucl_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  
 750  void 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
 757  struct ucl_curl_cbdata {
 758  	unsigned char *buf;
 759  	size_t buflen;
 760  };
 761  
 762  static size_t
 763  ucl_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   */
 789  bool
 790  ucl_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   */
 886  bool
 887  ucl_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  	if ((fd = open (filename, O_RDONLY)) == -1) {
 893  		ucl_create_err (err, "cannot open file %s: %s",
 894  				filename, strerror (errno));
 895  		return false;
 896  	}
 897  
 898  	if (fstat (fd, &st) == -1) {
 899  		if (must_exist || errno == EPERM) {
 900  			ucl_create_err (err, "cannot stat file %s: %s",
 901  					filename, strerror (errno));
 902  		}
 903  		close (fd);
 904  
 905  		return false;
 906  	}
 907  	if (!S_ISREG (st.st_mode)) {
 908  		if (must_exist) {
 909  			ucl_create_err (err, "file %s is not a regular file", filename);
 910  		}
 911  		close (fd);
 912  
 913  		return false;
 914  	}
 915  
 916  	if (st.st_size == 0) {
 917  		/* Do not map empty files */
 918  		*buf = NULL;
 919  		*buflen = 0;
 920  	}
 921  	else {
 922  		if ((*buf = ucl_mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
 923  			close(fd);
 924  			ucl_create_err(err, "cannot mmap file %s: %s",
 925  					filename, strerror(errno));
 926  			*buf = NULL;
 927  
 928  			return false;
 929  		}
 930  		*buflen = st.st_size;
 931  	}
 932  
 933  	close (fd);
 934  
 935  	return true;
 936  }
 937  
 938  
 939  #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
 940  static inline bool
 941  ucl_sig_check (const unsigned char *data, size_t datalen,
 942  		const unsigned char *sig, size_t siglen, struct ucl_parser *parser)
 943  {
 944  	struct ucl_pubkey *key;
 945  	char dig[EVP_MAX_MD_SIZE];
 946  	unsigned int diglen;
 947  	EVP_PKEY_CTX *key_ctx;
 948  	EVP_MD_CTX *sign_ctx = NULL;
 949  
 950  	sign_ctx = EVP_MD_CTX_create ();
 951  
 952  	LL_FOREACH (parser->keys, key) {
 953  		key_ctx = EVP_PKEY_CTX_new (key->key, NULL);
 954  		if (key_ctx != NULL) {
 955  			if (EVP_PKEY_verify_init (key_ctx) <= 0) {
 956  				EVP_PKEY_CTX_free (key_ctx);
 957  				continue;
 958  			}
 959  			if (EVP_PKEY_CTX_set_rsa_padding (key_ctx, RSA_PKCS1_PADDING) <= 0) {
 960  				EVP_PKEY_CTX_free (key_ctx);
 961  				continue;
 962  			}
 963  			if (EVP_PKEY_CTX_set_signature_md (key_ctx, EVP_sha256 ()) <= 0) {
 964  				EVP_PKEY_CTX_free (key_ctx);
 965  				continue;
 966  			}
 967  			EVP_DigestInit (sign_ctx, EVP_sha256 ());
 968  			EVP_DigestUpdate (sign_ctx, data, datalen);
 969  			EVP_DigestFinal (sign_ctx, dig, &diglen);
 970  
 971  			if (EVP_PKEY_verify (key_ctx, sig, siglen, dig, diglen) == 1) {
 972  				EVP_MD_CTX_destroy (sign_ctx);
 973  				EVP_PKEY_CTX_free (key_ctx);
 974  				return true;
 975  			}
 976  
 977  			EVP_PKEY_CTX_free (key_ctx);
 978  		}
 979  	}
 980  
 981  	EVP_MD_CTX_destroy (sign_ctx);
 982  
 983  	return false;
 984  }
 985  #endif
 986  
 987  struct ucl_include_params {
 988  	bool check_signature;
 989  	bool must_exist;
 990  	bool use_glob;
 991  	bool use_prefix;
 992  	bool soft_fail;
 993  	bool allow_glob;
 994  	unsigned priority;
 995  	enum ucl_duplicate_strategy strat;
 996  	enum ucl_parse_type parse_type;
 997  	const char *prefix;
 998  	const char *target;
 999  };
1000  
1001  /**
1002   * Include an url to configuration
1003   * @param data
1004   * @param len
1005   * @param parser
1006   * @param err
1007   * @return
1008   */
1009  static bool
1010  ucl_include_url (const unsigned char *data, size_t len,
1011  		struct ucl_parser *parser,
1012  		struct ucl_include_params *params)
1013  {
1014  
1015  	bool res;
1016  	unsigned char *buf = NULL;
1017  	size_t buflen = 0;
1018  	struct ucl_chunk *chunk;
1019  	char urlbuf[PATH_MAX];
1020  	int prev_state;
1021  
1022  	snprintf (urlbuf, sizeof (urlbuf), "%.*s", (int)len, data);
1023  
1024  	if (!ucl_fetch_url (urlbuf, &buf, &buflen, &parser->err, params->must_exist)) {
1025  		if (!params->must_exist) {
1026  			ucl_parser_clear_error (parser);
1027  		}
1028  		return !params->must_exist;
1029  	}
1030  
1031  	if (params->check_signature) {
1032  #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
1033  		unsigned char *sigbuf = NULL;
1034  		size_t siglen = 0;
1035  		/* We need to check signature first */
1036  		snprintf (urlbuf, sizeof (urlbuf), "%.*s.sig", (int)len, data);
1037  		if (!ucl_fetch_url (urlbuf, &sigbuf, &siglen, &parser->err, true)) {
1038  			return false;
1039  		}
1040  		if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
1041  			ucl_create_err (&parser->err, "cannot verify url %s: %s",
1042  							urlbuf,
1043  							ERR_error_string (ERR_get_error (), NULL));
1044  			if (siglen > 0) {
1045  				ucl_munmap (sigbuf, siglen);
1046  			}
1047  			return false;
1048  		}
1049  		if (siglen > 0) {
1050  			ucl_munmap (sigbuf, siglen);
1051  		}
1052  #endif
1053  	}
1054  
1055  	prev_state = parser->state;
1056  	parser->state = UCL_STATE_INIT;
1057  
1058  	res = ucl_parser_add_chunk_full (parser, buf, buflen, params->priority,
1059  			params->strat, params->parse_type);
1060  	if (res == true) {
1061  		/* Remove chunk from the stack */
1062  		chunk = parser->chunks;
1063  		if (chunk != NULL) {
1064  			parser->chunks = chunk->next;
1065  			ucl_chunk_free (chunk);
1066  		}
1067  	}
1068  
1069  	parser->state = prev_state;
1070  	free (buf);
1071  
1072  	return res;
1073  }
1074  
1075  /**
1076   * Include a single file to the parser
1077   * @param data
1078   * @param len
1079   * @param parser
1080   * @param check_signature
1081   * @param must_exist
1082   * @param allow_glob
1083   * @param priority
1084   * @return
1085   */
1086  static bool
1087  ucl_include_file_single (const unsigned char *data, size_t len,
1088  		struct ucl_parser *parser, struct ucl_include_params *params)
1089  {
1090  	bool res;
1091  	struct ucl_chunk *chunk;
1092  	unsigned char *buf = NULL;
1093  	char *old_curfile, *ext;
1094  	size_t buflen = 0;
1095  	char filebuf[PATH_MAX], realbuf[PATH_MAX];
1096  	int prev_state;
1097  	struct ucl_variable *cur_var, *tmp_var, *old_curdir = NULL,
1098  			*old_filename = NULL;
1099  	ucl_object_t *nest_obj = NULL, *old_obj = NULL, *new_obj = NULL;
1100  	ucl_hash_t *container = NULL;
1101  	struct ucl_stack *st = NULL;
1102  
1103  	snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data);
1104  	if (ucl_realpath (filebuf, realbuf) == NULL) {
1105  		if (params->soft_fail) {
1106  			return false;
1107  		}
1108  		if (!params->must_exist && errno != EPERM) {
1109  			return true;
1110  		}
1111  
1112  		ucl_create_err (&parser->err, "cannot open file %s: %s",
1113  									filebuf,
1114  									strerror (errno));
1115  		return false;
1116  	}
1117  
1118  	if (parser->cur_file && strcmp (realbuf, parser->cur_file) == 0) {
1119  		/* We are likely including the file itself */
1120  		if (params->soft_fail) {
1121  			return false;
1122  		}
1123  
1124  		ucl_create_err (&parser->err, "trying to include the file %s from itself",
1125  				realbuf);
1126  		return false;
1127  	}
1128  
1129  	if (!ucl_fetch_file (realbuf, &buf, &buflen, &parser->err, params->must_exist)) {
1130  		if (params->soft_fail) {
1131  			return false;
1132  		}
1133  
1134  		if (params->must_exist || parser->err != NULL) {
1135  			/* The case of fatal errors */
1136  			return false;
1137  		}
1138  
1139  		ucl_parser_clear_error (parser);
1140  
1141  		return true;
1142  	}
1143  
1144  	if (params->check_signature) {
1145  #if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
1146  		unsigned char *sigbuf = NULL;
1147  		size_t siglen = 0;
1148  		/* We need to check signature first */
1149  		snprintf (filebuf, sizeof (filebuf), "%s.sig", realbuf);
1150  		if (!ucl_fetch_file (filebuf, &sigbuf, &siglen, &parser->err, true)) {
1151  			if (buf) {
1152  				ucl_munmap (buf, buflen);
1153  			}
1154  
1155  			return false;
1156  		}
1157  		if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
1158  			ucl_create_err (&parser->err, "cannot verify file %s: %s",
1159  							filebuf,
1160  							ERR_error_string (ERR_get_error (), NULL));
1161  			if (sigbuf) {
1162  				ucl_munmap (sigbuf, siglen);
1163  			}
1164  			if (buf) {
1165  				ucl_munmap (buf, buflen);
1166  			}
1167  
1168  			return false;
1169  		}
1170  
1171  		if (sigbuf) {
1172  			ucl_munmap (sigbuf, siglen);
1173  		}
1174  #endif
1175  	}
1176  
1177  	old_curfile = parser->cur_file;
1178  	parser->cur_file = NULL;
1179  
1180  	/* Store old file vars */
1181  	DL_FOREACH_SAFE (parser->variables, cur_var, tmp_var) {
1182  		if (strcmp (cur_var->var, "CURDIR") == 0) {
1183  			old_curdir = cur_var;
1184  			DL_DELETE (parser->variables, cur_var);
1185  		}
1186  		else if (strcmp (cur_var->var, "FILENAME") == 0) {
1187  			old_filename = cur_var;
1188  			DL_DELETE (parser->variables, cur_var);
1189  		}
1190  	}
1191  
1192  	ucl_parser_set_filevars (parser, realbuf, false);
1193  
1194  	prev_state = parser->state;
1195  	parser->state = UCL_STATE_INIT;
1196  
1197  	if (params->use_prefix && params->prefix == NULL) {
1198  		/* Auto generate a key name based on the included filename */
1199  		params->prefix = basename (realbuf);
1200  		ext = strrchr (params->prefix, '.');
1201  		if (ext != NULL && (strcmp (ext, ".conf") == 0 || strcmp (ext, ".ucl") == 0)) {
1202  			/* Strip off .conf or .ucl */
1203  			*ext = '\0';
1204  		}
1205  	}
1206  	if (params->prefix != NULL) {
1207  		/* This is a prefixed include */
1208  		container = parser->stack->obj->value.ov;
1209  
1210  		old_obj = __DECONST (ucl_object_t *, ucl_hash_search (container,
1211  				params->prefix, strlen (params->prefix)));
1212  
1213  		if (strcasecmp (params->target, "array") == 0) {
1214  			if (old_obj == NULL) {
1215  				/* Create an array with key: prefix */
1216  				old_obj = ucl_object_new_full (UCL_ARRAY, params->priority);
1217  				old_obj->key = params->prefix;
1218  				old_obj->keylen = strlen (params->prefix);
1219  				ucl_copy_key_trash (old_obj);
1220  				old_obj->prev = old_obj;
1221  				old_obj->next = NULL;
1222  
1223  				container = ucl_hash_insert_object (container, old_obj,
1224  						parser->flags & UCL_PARSER_KEY_LOWERCASE);
1225  				parser->stack->obj->len++;
1226  
1227  				nest_obj = ucl_object_new_full (UCL_OBJECT, params->priority);
1228  				nest_obj->prev = nest_obj;
1229  				nest_obj->next = NULL;
1230  
1231  				ucl_array_append (old_obj, nest_obj);
1232  			}
1233  			else {
1234  				if (ucl_object_type (old_obj) == UCL_ARRAY) {
1235  					/* Append to the existing array */
1236  					nest_obj = ucl_object_new_full (UCL_OBJECT,
1237  							params->priority);
1238  					if (nest_obj == NULL) {
1239  						ucl_create_err (&parser->err,
1240  								"cannot allocate memory for an object");
1241  						if (buf) {
1242  							ucl_munmap (buf, buflen);
1243  						}
1244  
1245  						return false;
1246  					}
1247  					nest_obj->prev = nest_obj;
1248  					nest_obj->next = NULL;
1249  
1250  					ucl_array_append (old_obj, nest_obj);
1251  				}
1252  				else {
1253  					/* Convert the object to an array */
1254  					new_obj = ucl_object_typed_new (UCL_ARRAY);
1255  					if (new_obj == NULL) {
1256  						ucl_create_err (&parser->err,
1257  								"cannot allocate memory for an object");
1258  						if (buf) {
1259  							ucl_munmap (buf, buflen);
1260  						}
1261  
1262  						return false;
1263  					}
1264  					new_obj->key = old_obj->key;
1265  					new_obj->keylen = old_obj->keylen;
1266  					new_obj->flags |= UCL_OBJECT_MULTIVALUE;
1267  					new_obj->prev = new_obj;
1268  					new_obj->next = NULL;
1269  
1270  					nest_obj = ucl_object_new_full (UCL_OBJECT,
1271  							params->priority);
1272  					if (nest_obj == NULL) {
1273  						ucl_create_err (&parser->err,
1274  								"cannot allocate memory for an object");
1275  						if (buf) {
1276  							ucl_munmap (buf, buflen);
1277  						}
1278  
1279  						ucl_object_unref (new_obj);
1280  
1281  						return false;
1282  					}
1283  					nest_obj->prev = nest_obj;
1284  					nest_obj->next = NULL;
1285  
1286  					ucl_array_append (new_obj, old_obj);
1287  					ucl_array_append (new_obj, nest_obj);
1288  					ucl_hash_replace (container, old_obj, new_obj);
1289  				}
1290  			}
1291  		}
1292  		else {
1293  			/* Case of object */
1294  			if (old_obj == NULL) {
1295  				/* Create an object with key: prefix */
1296  				nest_obj = ucl_object_new_full (UCL_OBJECT, params->priority);
1297  
1298  				if (nest_obj == NULL) {
1299  					ucl_create_err (&parser->err, "cannot allocate memory for an object");
1300  					if (buf) {
1301  						ucl_munmap (buf, buflen);
1302  					}
1303  
1304  					return false;
1305  				}
1306  
1307  				nest_obj->key = params->prefix;
1308  				nest_obj->keylen = strlen (params->prefix);
1309  				ucl_copy_key_trash(nest_obj);
1310  				nest_obj->prev = nest_obj;
1311  				nest_obj->next = NULL;
1312  
1313  				container = ucl_hash_insert_object (container, nest_obj,
1314  						parser->flags & UCL_PARSER_KEY_LOWERCASE);
1315  				parser->stack->obj->len ++;
1316  			}
1317  			else {
1318  				if (ucl_object_type (old_obj) == UCL_OBJECT) {
1319  					/* Append to existing Object*/
1320  					nest_obj = old_obj;
1321  				}
1322  				else {
1323  					/* The key is not an object */
1324  					ucl_create_err (&parser->err,
1325  							"Conflicting type for key: %s, asked %s, has %s",
1326  							params->prefix, params->target,
1327  							ucl_object_type_to_string (ucl_object_type (old_obj)));
1328  					if (buf) {
1329  						ucl_munmap (buf, buflen);
1330  					}
1331  
1332  					return false;
1333  				}
1334  			}
1335  		}
1336  
1337  
1338  		/* Put all of the content of the include inside that object */
1339  		parser->stack->obj->value.ov = container;
1340  
1341  		st = UCL_ALLOC (sizeof (struct ucl_stack));
1342  		if (st == NULL) {
1343  			ucl_create_err (&parser->err, "cannot allocate memory for an object");
1344  			ucl_object_unref (nest_obj);
1345  
1346  			if (buf) {
1347  				ucl_munmap (buf, buflen);
1348  			}
1349  
1350  			return false;
1351  		}
1352  		st->obj = nest_obj;
1353  		st->e.params.level = parser->stack->e.params.level;
1354  		st->e.params.flags = parser->stack->e.params.flags;
1355  		st->e.params.line = parser->stack->e.params.line;
1356  		st->chunk = parser->chunks;
1357  		LL_PREPEND (parser->stack, st);
1358  		parser->cur_obj = nest_obj;
1359  	}
1360  
1361  	res = ucl_parser_add_chunk_full (parser, buf, buflen, params->priority,
1362  			params->strat, params->parse_type);
1363  
1364  	if (res) {
1365  		/* Stop nesting the include, take 1 level off the stack */
1366  		if (params->prefix != NULL && nest_obj != NULL) {
1367  			parser->stack = st->next;
1368  			UCL_FREE (sizeof (struct ucl_stack), st);
1369  		}
1370  
1371  		/* Remove chunk from the stack */
1372  		chunk = parser->chunks;
1373  		if (chunk != NULL) {
1374  			parser->chunks = chunk->next;
1375  			ucl_chunk_free (chunk);
1376  			parser->recursion--;
1377  		}
1378  
1379  		/* Restore old file vars */
1380  		if (parser->cur_file) {
1381  			free (parser->cur_file);
1382  		}
1383  
1384  		parser->cur_file = old_curfile;
1385  		DL_FOREACH_SAFE (parser->variables, cur_var, tmp_var) {
1386  			if (strcmp (cur_var->var, "CURDIR") == 0 && old_curdir) {
1387  				DL_DELETE (parser->variables, cur_var);
1388  				free (cur_var->var);
1389  				free (cur_var->value);
1390  				UCL_FREE (sizeof (struct ucl_variable), cur_var);
1391  			} else if (strcmp (cur_var->var, "FILENAME") == 0 && old_filename) {
1392  				DL_DELETE (parser->variables, cur_var);
1393  				free (cur_var->var);
1394  				free (cur_var->value);
1395  				UCL_FREE (sizeof (struct ucl_variable), cur_var);
1396  			}
1397  		}
1398  		if (old_filename) {
1399  			DL_APPEND (parser->variables, old_filename);
1400  		}
1401  		if (old_curdir) {
1402  			DL_APPEND (parser->variables, old_curdir);
1403  		}
1404  
1405  		parser->state = prev_state;
1406  	}
1407  
1408  	if (buflen > 0) {
1409  		ucl_munmap (buf, buflen);
1410  	}
1411  
1412  	return res;
1413  }
1414  
1415  /**
1416   * Include a file to configuration
1417   * @param data
1418   * @param len
1419   * @param parser
1420   * @param err
1421   * @return
1422   */
1423  static bool
1424  ucl_include_file (const unsigned char *data, size_t len,
1425  				  struct ucl_parser *parser,
1426  				  struct ucl_include_params *params,
1427  				  const ucl_object_t *args)
1428  {
1429  	const unsigned char *p = data, *end = data + len;
1430  	bool need_glob = false;
1431  	int cnt = 0;
1432  	char glob_pattern[PATH_MAX];
1433  	size_t i;
1434  
1435  #ifndef _WIN32
1436  	if (!params->allow_glob) {
1437  		return ucl_include_file_single (data, len, parser, params);
1438  	}
1439  	else {
1440  		/* Check for special symbols in a filename */
1441  		while (p != end) {
1442  			if (*p == '*' || *p == '?') {
1443  				need_glob = true;
1444  				break;
1445  			}
1446  			p ++;
1447  		}
1448  		if (need_glob) {
1449  			glob_t globbuf;
1450  			memset (&globbuf, 0, sizeof (globbuf));
1451  			ucl_strlcpy (glob_pattern, (const char *)data,
1452  				(len + 1 < sizeof (glob_pattern) ? len + 1 : sizeof (glob_pattern)));
1453  			if (glob (glob_pattern, 0, NULL, &globbuf) != 0) {
1454  				return (!params->must_exist || false);
1455  			}
1456  			for (i = 0; i < globbuf.gl_pathc; i ++) {
1457  
1458  				if (parser->include_trace_func) {
1459  					const ucl_object_t *parent = NULL;
1460  
1461  					if (parser->stack) {
1462  						parent = parser->stack->obj;
1463  					}
1464  
1465  					parser->include_trace_func (parser, parent, NULL,
1466  							globbuf.gl_pathv[i],
1467  							strlen (globbuf.gl_pathv[i]),
1468  							parser->include_trace_ud);
1469  				}
1470  
1471  				if (!ucl_include_file_single ((unsigned char *)globbuf.gl_pathv[i],
1472  						strlen (globbuf.gl_pathv[i]), parser, params)) {
1473  					if (params->soft_fail) {
1474  						continue;
1475  					}
1476  					globfree (&globbuf);
1477  					return false;
1478  				}
1479  				cnt ++;
1480  			}
1481  			globfree (&globbuf);
1482  
1483  			if (cnt == 0 && params->must_exist) {
1484  				ucl_create_err (&parser->err, "cannot match any files for pattern %s",
1485  					glob_pattern);
1486  				return false;
1487  			}
1488  		}
1489  		else {
1490  			return ucl_include_file_single (data, len, parser, params);
1491  		}
1492  	}
1493  #else
1494  	/* Win32 compilers do not support globbing. Therefore, for Win32,
1495  	   treat allow_glob/need_glob as a NOOP and just return */
1496  	return ucl_include_file_single (data, len, parser, params);
1497  #endif
1498  
1499  	return true;
1500  }
1501  
1502  /**
1503   * Common function to handle .*include* macros
1504   * @param data
1505   * @param len
1506   * @param args
1507   * @param parser
1508   * @param default_try
1509   * @param default_sign
1510   * @return
1511   */
1512  static bool
1513  ucl_include_common (const unsigned char *data, size_t len,
1514  		const ucl_object_t *args, struct ucl_parser *parser,
1515  		bool default_try,
1516  		bool default_sign)
1517  {
1518  	bool allow_url = false, search = false;
1519  	const char *duplicate;
1520  	const ucl_object_t *param;
1521  	ucl_object_iter_t it = NULL, ip = NULL;
1522  	char ipath[PATH_MAX];
1523  	struct ucl_include_params params;
1524  
1525  	/* Default values */
1526  	params.soft_fail = default_try;
1527  	params.allow_glob = false;
1528  	params.check_signature = default_sign;
1529  	params.use_prefix = false;
1530  	params.target = "object";
1531  	params.prefix = NULL;
1532  	params.priority = 0;
1533  	params.parse_type = UCL_PARSE_UCL;
1534  	params.strat = UCL_DUPLICATE_APPEND;
1535  	params.must_exist = !default_try;
1536  
1537  	if (parser->include_trace_func) {
1538  		const ucl_object_t *parent = NULL;
1539  
1540  		if (parser->stack) {
1541  			parent = parser->stack->obj;
1542  		}
1543  
1544  		parser->include_trace_func (parser, parent, args,
1545  				data, len, parser->include_trace_ud);
1546  	}
1547  
1548  	/* Process arguments */
1549  	if (args != NULL && args->type == UCL_OBJECT) {
1550  		while ((param = ucl_object_iterate (args, &it, true)) != NULL) {
1551  			if (param->type == UCL_BOOLEAN) {
1552  				if (strncmp (param->key, "try", param->keylen) == 0) {
1553  					params.must_exist = !ucl_object_toboolean (param);
1554  				}
1555  				else if (strncmp (param->key, "sign", param->keylen) == 0) {
1556  					params.check_signature = ucl_object_toboolean (param);
1557  				}
1558  				else if (strncmp (param->key, "glob", param->keylen) == 0) {
1559  					params.allow_glob = ucl_object_toboolean (param);
1560  				}
1561  				else if (strncmp (param->key, "url", param->keylen) == 0) {
1562  					allow_url = ucl_object_toboolean (param);
1563  				}
1564  				else if (strncmp (param->key, "prefix", param->keylen) == 0) {
1565  					params.use_prefix = ucl_object_toboolean (param);
1566  				}
1567  			}
1568  			else if (param->type == UCL_STRING) {
1569  				if (strncmp (param->key, "key", param->keylen) == 0) {
1570  					params.prefix = ucl_object_tostring (param);
1571  				}
1572  				else if (strncmp (param->key, "target", param->keylen) == 0) {
1573  					params.target = ucl_object_tostring (param);
1574  				}
1575  				else if (strncmp (param->key, "duplicate", param->keylen) == 0) {
1576  					duplicate = ucl_object_tostring (param);
1577  
1578  					if (strcmp (duplicate, "append") == 0) {
1579  						params.strat = UCL_DUPLICATE_APPEND;
1580  					}
1581  					else if (strcmp (duplicate, "merge") == 0) {
1582  						params.strat = UCL_DUPLICATE_MERGE;
1583  					}
1584  					else if (strcmp (duplicate, "rewrite") == 0) {
1585  						params.strat = UCL_DUPLICATE_REWRITE;
1586  					}
1587  					else if (strcmp (duplicate, "error") == 0) {
1588  						params.strat = UCL_DUPLICATE_ERROR;
1589  					}
1590  				}
1591  			}
1592  			else if (param->type == UCL_ARRAY) {
1593  				if (strncmp (param->key, "path", param->keylen) == 0) {
1594  					ucl_set_include_path (parser, __DECONST(ucl_object_t *, param));
1595  				}
1596  			}
1597  			else if (param->type == UCL_INT) {
1598  				if (strncmp (param->key, "priority", param->keylen) == 0) {
1599  					params.priority = ucl_object_toint (param);
1600  				}
1601  			}
1602  		}
1603  	}
1604  
1605  	if (parser->includepaths == NULL) {
1606  		if (allow_url && ucl_strnstr (data, "://", len) != NULL) {
1607  			/* Globbing is not used for URL's */
1608  			return ucl_include_url (data, len, parser, &params);
1609  		}
1610  		else if (data != NULL) {
1611  			/* Try to load a file */
1612  			return ucl_include_file (data, len, parser, &params, args);
1613  		}
1614  	}
1615  	else {
1616  		if (allow_url && ucl_strnstr (data, "://", len) != NULL) {
1617  			/* Globbing is not used for URL's */
1618  			return ucl_include_url (data, len, parser, &params);
1619  		}
1620  
1621  		ip = ucl_object_iterate_new (parser->includepaths);
1622  		while ((param = ucl_object_iterate_safe (ip, true)) != NULL) {
1623  			if (ucl_object_type(param) == UCL_STRING) {
1624  				snprintf (ipath, sizeof (ipath), "%s/%.*s", ucl_object_tostring(param),
1625  						(int)len, data);
1626  				if ((search = ucl_include_file (ipath, strlen (ipath),
1627  						parser, &params, args))) {
1628  					if (!params.allow_glob) {
1629  						break;
1630  					}
1631  				}
1632  			}
1633  		}
1634  		ucl_object_iterate_free (ip);
1635  		if (search == true) {
1636  			return true;
1637  		}
1638  		else {
1639  			ucl_create_err (&parser->err,
1640  					"cannot find file: %.*s in search path",
1641  					(int)len, data);
1642  			return false;
1643  		}
1644  	}
1645  
1646  	return false;
1647  }
1648  
1649  /**
1650   * Handle include macro
1651   * @param data include data
1652   * @param len length of data
1653   * @param args UCL object representing arguments to the macro
1654   * @param ud user data
1655   * @return
1656   */
1657  bool
1658  ucl_include_handler (const unsigned char *data, size_t len,
1659  		const ucl_object_t *args, void* ud)
1660  {
1661  	struct ucl_parser *parser = ud;
1662  
1663  	return ucl_include_common (data, len, args, parser, false, false);
1664  }
1665  
1666  /**
1667   * Handle includes macro
1668   * @param data include data
1669   * @param len length of data
1670   * @param args UCL object representing arguments to the macro
1671   * @param ud user data
1672   * @return
1673   */
1674  bool
1675  ucl_includes_handler (const unsigned char *data, size_t len,
1676  		const ucl_object_t *args, void* ud)
1677  {
1678  	struct ucl_parser *parser = ud;
1679  
1680  	return ucl_include_common (data, len, args, parser, false, true);
1681  }
1682  
1683  /**
1684   * Handle tryinclude macro
1685   * @param data include data
1686   * @param len length of data
1687   * @param args UCL object representing arguments to the macro
1688   * @param ud user data
1689   * @return
1690   */
1691  bool
1692  ucl_try_include_handler (const unsigned char *data, size_t len,
1693  		const ucl_object_t *args, void* ud)
1694  {
1695  	struct ucl_parser *parser = ud;
1696  
1697  	return ucl_include_common (data, len, args, parser, true, false);
1698  }
1699  
1700  /**
1701   * Handle priority macro
1702   * @param data include data
1703   * @param len length of data
1704   * @param args UCL object representing arguments to the macro
1705   * @param ud user data
1706   * @return
1707   */
1708  bool
1709  ucl_priority_handler (const unsigned char *data, size_t len,
1710  		const ucl_object_t *args, void* ud)
1711  {
1712  	struct ucl_parser *parser = ud;
1713  	unsigned priority = 255;
1714  	const ucl_object_t *param;
1715  	bool found = false;
1716  	char *value = NULL, *leftover = NULL;
1717  	ucl_object_iter_t it = NULL;
1718  
1719  	if (parser == NULL) {
1720  		return false;
1721  	}
1722  
1723  	/* Process arguments */
1724  	if (args != NULL && args->type == UCL_OBJECT) {
1725  		while ((param = ucl_object_iterate (args, &it, true)) != NULL) {
1726  			if (param->type == UCL_INT) {
1727  				if (strncmp (param->key, "priority", param->keylen) == 0) {
1728  					priority = ucl_object_toint (param);
1729  					found = true;
1730  				}
1731  			}
1732  		}
1733  	}
1734  
1735  	if (len > 0) {
1736  		value = malloc(len + 1);
1737  		ucl_strlcpy(value, (const char *)data, len + 1);
1738  		priority = strtol(value, &leftover, 10);
1739  		if (*leftover != '\0') {
1740  			ucl_create_err (&parser->err, "Invalid priority value in macro: %s",
1741  				value);
1742  			free(value);
1743  			return false;
1744  		}
1745  		free(value);
1746  		found = true;
1747  	}
1748  
1749  	if (found == true) {
1750  		parser->chunks->priority = priority;
1751  		return true;
1752  	}
1753  
1754  	ucl_create_err (&parser->err, "Unable to parse priority macro");
1755  	return false;
1756  }
1757  
1758  /**
1759   * Handle load macro
1760   * @param data include data
1761   * @param len length of data
1762   * @param args UCL object representing arguments to the macro
1763   * @param ud user data
1764   * @return
1765   */
1766  bool
1767  ucl_load_handler (const unsigned char *data, size_t len,
1768  		const ucl_object_t *args, void* ud)
1769  {
1770  	struct ucl_parser *parser = ud;
1771  	const ucl_object_t *param;
1772  	ucl_object_t *obj, *old_obj;
1773  	ucl_object_iter_t it = NULL;
1774  	bool try_load, multiline, test;
1775  	const char *target, *prefix;
1776  	char *load_file, *tmp;
1777  	unsigned char *buf;
1778  	size_t buflen;
1779  	unsigned priority;
1780  	int64_t iv;
1781  	ucl_object_t *container = NULL;
1782  	enum ucl_string_flags flags;
1783  
1784  	/* Default values */
1785  	try_load = false;
1786  	multiline = false;
1787  	test = false;
1788  	target = "string";
1789  	prefix = NULL;
1790  	load_file = NULL;
1791  	buf = NULL;
1792  	buflen = 0;
1793  	priority = 0;
1794  	obj = NULL;
1795  	old_obj = NULL;
1796  	flags = 0;
1797  
1798  	if (parser == NULL) {
1799  		return false;
1800  	}
1801  
1802  	/* Process arguments */
1803  	if (args != NULL && args->type == UCL_OBJECT) {
1804  		while ((param = ucl_object_iterate (args, &it, true)) != NULL) {
1805  			if (param->type == UCL_BOOLEAN) {
1806  				if (strncmp (param->key, "try", param->keylen) == 0) {
1807  					try_load = ucl_object_toboolean (param);
1808  				}
1809  				else if (strncmp (param->key, "multiline", param->keylen) == 0) {
1810  					multiline = ucl_object_toboolean (param);
1811  				}
1812  				else if (strncmp (param->key, "escape", param->keylen) == 0) {
1813  					test = ucl_object_toboolean (param);
1814  					if (test) {
1815  						flags |= UCL_STRING_ESCAPE;
1816  					}
1817  				}
1818  				else if (strncmp (param->key, "trim", param->keylen) == 0) {
1819  					test = ucl_object_toboolean (param);
1820  					if (test) {
1821  						flags |= UCL_STRING_TRIM;
1822  					}
1823  				}
1824  			}
1825  			else if (param->type == UCL_STRING) {
1826  				if (strncmp (param->key, "key", param->keylen) == 0) {
1827  					prefix = ucl_object_tostring (param);
1828  				}
1829  				else if (strncmp (param->key, "target", param->keylen) == 0) {
1830  					target = ucl_object_tostring (param);
1831  				}
1832  			}
1833  			else if (param->type == UCL_INT) {
1834  				if (strncmp (param->key, "priority", param->keylen) == 0) {
1835  					priority = ucl_object_toint (param);
1836  				}
1837  			}
1838  		}
1839  	}
1840  
1841  	if (prefix == NULL || strlen (prefix) == 0) {
1842  		ucl_create_err (&parser->err, "No Key specified in load macro");
1843  		return false;
1844  	}
1845  
1846  	if (len > 0) {
1847  		load_file = malloc (len + 1);
1848  		if (!load_file) {
1849  			ucl_create_err (&parser->err, "cannot allocate memory for suffix");
1850  
1851  			return false;
1852  		}
1853  
1854  		snprintf (load_file, len + 1, "%.*s", (int)len, data);
1855  
1856  		if (!ucl_fetch_file (load_file, &buf, &buflen, &parser->err,
1857  				!try_load)) {
1858  			free (load_file);
1859  
1860  			if (try_load) {
1861  				ucl_parser_clear_error (parser);
1862  			}
1863  
1864  			return (try_load || false);
1865  		}
1866  
1867  		free (load_file);
1868  		container = parser->stack->obj;
1869  		old_obj = __DECONST (ucl_object_t *, ucl_object_lookup (container,
1870  				prefix));
1871  
1872  		if (old_obj != NULL) {
1873  			ucl_create_err (&parser->err, "Key %s already exists", prefix);
1874  			if (buf) {
1875  				ucl_munmap (buf, buflen);
1876  			}
1877  
1878  			return false;
1879  		}
1880  
1881  		if (strcasecmp (target, "string") == 0) {
1882  			obj = ucl_object_fromstring_common (buf, buflen, flags);
1883  			ucl_copy_value_trash (obj);
1884  			if (multiline) {
1885  				obj->flags |= UCL_OBJECT_MULTILINE;
1886  			}
1887  		}
1888  		else if (strcasecmp (target, "int") == 0) {
1889  			tmp = malloc (buflen + 1);
1890  
1891  			if (tmp == NULL) {
1892  				ucl_create_err (&parser->err, "Memory allocation failed");
1893  				if (buf) {
1894  					ucl_munmap (buf, buflen);
1895  				}
1896  
1897  				return false;
1898  			}
1899  
1900  			snprintf (tmp, buflen + 1, "%.*s", (int)buflen, buf);
1901  			iv = strtoll (tmp, NULL, 10);
1902  			obj = ucl_object_fromint (iv);
1903  			free (tmp);
1904  		}
1905  
1906  		if (buf) {
1907  			ucl_munmap (buf, buflen);
1908  		}
1909  
1910  		if (obj != NULL) {
1911  			obj->key = prefix;
1912  			obj->keylen = strlen (prefix);
1913  			ucl_copy_key_trash (obj);
1914  			obj->prev = obj;
1915  			obj->next = NULL;
1916  			ucl_object_set_priority (obj, priority);
1917  			ucl_object_insert_key (container, obj, obj->key, obj->keylen, false);
1918  		}
1919  
1920  		return true;
1921  	}
1922  
1923  	ucl_create_err (&parser->err, "Unable to parse load macro");
1924  	return false;
1925  }
1926  
1927  bool
1928  ucl_inherit_handler (const unsigned char *data, size_t len,
1929  		const ucl_object_t *args, const ucl_object_t *ctx, void* ud)
1930  {
1931  	const ucl_object_t *parent, *cur;
1932  	ucl_object_t *target, *copy;
1933  	ucl_object_iter_t it = NULL;
1934  	bool replace = false;
1935  	struct ucl_parser *parser = ud;
1936  
1937  	parent = ucl_object_lookup_len (ctx, data, len);
1938  
1939  	/* Some sanity checks */
1940  	if (parent == NULL || ucl_object_type (parent) != UCL_OBJECT) {
1941  		ucl_create_err (&parser->err, "Unable to find inherited object %.*s",
1942  				(int)len, data);
1943  		return false;
1944  	}
1945  
1946  	if (parser->stack == NULL || parser->stack->obj == NULL ||
1947  			ucl_object_type (parser->stack->obj) != UCL_OBJECT) {
1948  		ucl_create_err (&parser->err, "Invalid inherit context");
1949  		return false;
1950  	}
1951  
1952  	target = parser->stack->obj;
1953  
1954  	if (args && (cur = ucl_object_lookup (args, "replace")) != NULL) {
1955  		replace = ucl_object_toboolean (cur);
1956  	}
1957  
1958  	while ((cur = ucl_object_iterate (parent, &it, true))) {
1959  		/* We do not replace existing keys */
1960  		if (!replace && ucl_object_lookup_len (target, cur->key, cur->keylen)) {
1961  			continue;
1962  		}
1963  
1964  		copy = ucl_object_copy (cur);
1965  
1966  		if (!replace) {
1967  			copy->flags |= UCL_OBJECT_INHERITED;
1968  		}
1969  
1970  		ucl_object_insert_key (target, copy, copy->key,
1971  				copy->keylen, false);
1972  	}
1973  
1974  	return true;
1975  }
1976  
1977  bool
1978  ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand)
1979  {
1980  	char realbuf[PATH_MAX], *curdir;
1981  
1982  	if (filename != NULL) {
1983  		if (need_expand) {
1984  			if (ucl_realpath (filename, realbuf) == NULL) {
1985  				return false;
1986  			}
1987  		}
1988  		else {
1989  			ucl_strlcpy (realbuf, filename, sizeof (realbuf));
1990  		}
1991  
1992  		if (parser->cur_file) {
1993  			free (parser->cur_file);
1994  		}
1995  
1996  		parser->cur_file = strdup (realbuf);
1997  
1998  		/* Define variables */
1999  		ucl_parser_register_variable (parser, "FILENAME", realbuf);
2000  		curdir = dirname (realbuf);
2001  		ucl_parser_register_variable (parser, "CURDIR", curdir);
2002  	}
2003  	else {
2004  		/* Set everything from the current dir */
2005  		curdir = getcwd (realbuf, sizeof (realbuf));
2006  		ucl_parser_register_variable (parser, "FILENAME", "undef");
2007  		ucl_parser_register_variable (parser, "CURDIR", curdir);
2008  	}
2009  
2010  	return true;
2011  }
2012  
2013  bool
2014  ucl_parser_add_file_full (struct ucl_parser *parser, const char *filename,
2015  		unsigned priority, enum ucl_duplicate_strategy strat,
2016  		enum ucl_parse_type parse_type)
2017  {
2018  	unsigned char *buf;
2019  	size_t len;
2020  	bool ret;
2021  	char realbuf[PATH_MAX];
2022  
2023  	if (ucl_realpath (filename, realbuf) == NULL) {
2024  		ucl_create_err (&parser->err, "cannot open file %s: %s",
2025  				filename,
2026  				strerror (errno));
2027  		return false;
2028  	}
2029  
2030  	if (!ucl_fetch_file (realbuf, &buf, &len, &parser->err, true)) {
2031  		return false;
2032  	}
2033  
2034  	ucl_parser_set_filevars (parser, realbuf, false);
2035  	ret = ucl_parser_add_chunk_full (parser, buf, len, priority, strat,
2036  			parse_type);
2037  
2038  	if (len > 0) {
2039  		ucl_munmap (buf, len);
2040  	}
2041  
2042  	return ret;
2043  }
2044  
2045  bool
2046  ucl_parser_add_file_priority (struct ucl_parser *parser, const char *filename,
2047  		unsigned priority)
2048  {
2049  	if (parser == NULL) {
2050  		return false;
2051  	}
2052  
2053  	return ucl_parser_add_file_full(parser, filename, priority,
2054  			UCL_DUPLICATE_APPEND, UCL_PARSE_UCL);
2055  }
2056  
2057  bool
2058  ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
2059  {
2060  	if (parser == NULL) {
2061  		return false;
2062  	}
2063  
2064  	return ucl_parser_add_file_full(parser, filename,
2065  			parser->default_priority, UCL_DUPLICATE_APPEND,
2066  			UCL_PARSE_UCL);
2067  }
2068  
2069  
2070  bool
2071  ucl_parser_add_fd_full (struct ucl_parser *parser, int fd,
2072  		unsigned priority, enum ucl_duplicate_strategy strat,
2073  		enum ucl_parse_type parse_type)
2074  {
2075  	unsigned char *buf;
2076  	size_t len;
2077  	bool ret;
2078  	struct stat st;
2079  
2080  	if (fstat (fd, &st) == -1) {
2081  		ucl_create_err (&parser->err, "cannot stat fd %d: %s",
2082  			fd, strerror (errno));
2083  		return false;
2084  	}
2085  	if (st.st_size == 0) {
2086  		return true;
2087  	}
2088  	if ((buf = ucl_mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
2089  		ucl_create_err (&parser->err, "cannot mmap fd %d: %s",
2090  			fd, strerror (errno));
2091  		return false;
2092  	}
2093  
2094  	if (parser->cur_file) {
2095  		free (parser->cur_file);
2096  	}
2097  	parser->cur_file = NULL;
2098  	len = st.st_size;
2099  	ret = ucl_parser_add_chunk_full (parser, buf, len, priority, strat,
2100  			parse_type);
2101  
2102  	if (len > 0) {
2103  		ucl_munmap (buf, len);
2104  	}
2105  
2106  	return ret;
2107  }
2108  
2109  bool
2110  ucl_parser_add_fd_priority (struct ucl_parser *parser, int fd,
2111  		unsigned priority)
2112  {
2113  	if (parser == NULL) {
2114  		return false;
2115  	}
2116  
2117  	return ucl_parser_add_fd_full(parser, fd, parser->default_priority,
2118  			UCL_DUPLICATE_APPEND, UCL_PARSE_UCL);
2119  }
2120  
2121  bool
2122  ucl_parser_add_fd (struct ucl_parser *parser, int fd)
2123  {
2124  	if (parser == NULL) {
2125  		return false;
2126  	}
2127  
2128  	return ucl_parser_add_fd_priority(parser, fd, parser->default_priority);
2129  }
2130  
2131  size_t
2132  ucl_strlcpy (char *dst, const char *src, size_t siz)
2133  {
2134  	char *d = dst;
2135  	const char *s = src;
2136  	size_t n = siz;
2137  
2138  	/* Copy as many bytes as will fit */
2139  	if (n != 0) {
2140  		while (--n != 0) {
2141  			if ((*d++ = *s++) == '\0') {
2142  				break;
2143  			}
2144  		}
2145  	}
2146  
2147  	if (n == 0 && siz != 0) {
2148  		*d = '\0';
2149  	}
2150  
2151  	return (s - src - 1);    /* count does not include NUL */
2152  }
2153  
2154  size_t
2155  ucl_strlcpy_unsafe (char *dst, const char *src, size_t siz)
2156  {
2157  	memcpy (dst, src, siz - 1);
2158  	dst[siz - 1] = '\0';
2159  
2160  	return siz - 1;
2161  }
2162  
2163  size_t
2164  ucl_strlcpy_tolower (char *dst, const char *src, size_t siz)
2165  {
2166  	char *d = dst;
2167  	const char *s = src;
2168  	size_t n = siz;
2169  
2170  	/* Copy as many bytes as will fit */
2171  	if (n != 0) {
2172  		while (--n != 0) {
2173  			if ((*d++ = tolower (*s++)) == '\0') {
2174  				break;
2175  			}
2176  		}
2177  	}
2178  
2179  	if (n == 0 && siz != 0) {
2180  		*d = '\0';
2181  	}
2182  
2183  	return (s - src);    /* count does not include NUL */
2184  }
2185  
2186  /*
2187   * Find the first occurrence of find in s
2188   */
2189  char *
2190  ucl_strnstr (const char *s, const char *find, int len)
2191  {
2192  	char c, sc;
2193  	int mlen;
2194  
2195  	if ((c = *find++) != 0) {
2196  		mlen = strlen (find);
2197  		do {
2198  			do {
2199  				if ((sc = *s++) == 0 || len-- < mlen)
2200  					return (NULL);
2201  			} while (sc != c);
2202  		} while (strncmp (s, find, mlen) != 0);
2203  		s--;
2204  	}
2205  	return ((char *)s);
2206  }
2207  
2208  /*
2209   * Find the first occurrence of find in s, ignore case.
2210   */
2211  char *
2212  ucl_strncasestr (const char *s, const char *find, int len)
2213  {
2214  	char c, sc;
2215  	int mlen;
2216  
2217  	if ((c = *find++) != 0) {
2218  		c = tolower (c);
2219  		mlen = strlen (find);
2220  		do {
2221  			do {
2222  				if ((sc = *s++) == 0 || len-- == 0)
2223  					return (NULL);
2224  			} while (tolower (sc) != c);
2225  		} while (strncasecmp (s, find, mlen) != 0);
2226  		s--;
2227  	}
2228  	return ((char *)s);
2229  }
2230  
2231  ucl_object_t *
2232  ucl_object_fromstring_common (const char *str, size_t len, enum ucl_string_flags flags)
2233  {
2234  	ucl_object_t *obj;
2235  	const char *start, *end, *p, *pos;
2236  	char *dst, *d;
2237  	size_t escaped_len;
2238  
2239  	if (str == NULL) {
2240  		return NULL;
2241  	}
2242  
2243  	obj = ucl_object_new ();
2244  	if (obj) {
2245  		if (len == 0) {
2246  			len = strlen (str);
2247  		}
2248  		if (flags & UCL_STRING_TRIM) {
2249  			/* Skip leading spaces */
2250  			for (start = str; (size_t)(start - str) < len; start ++) {
2251  				if (!ucl_test_character (*start, UCL_CHARACTER_WHITESPACE_UNSAFE)) {
2252  					break;
2253  				}
2254  			}
2255  			/* Skip trailing spaces */
2256  			for (end = str + len - 1; end > start; end --) {
2257  				if (!ucl_test_character (*end, UCL_CHARACTER_WHITESPACE_UNSAFE)) {
2258  					break;
2259  				}
2260  			}
2261  			end ++;
2262  		}
2263  		else {
2264  			start = str;
2265  			end = str + len;
2266  		}
2267  
2268  		obj->type = UCL_STRING;
2269  		if (flags & UCL_STRING_ESCAPE) {
2270  			for (p = start, escaped_len = 0; p < end; p ++, escaped_len ++) {
2271  				if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE | UCL_CHARACTER_WHITESPACE_UNSAFE)) {
2272  					switch (*p) {
2273  					case '\v':
2274  					case '\0':
2275  						escaped_len += 5;
2276  						break;
2277  					case ' ':
2278  						break;
2279  					default:
2280  						escaped_len ++;
2281  						break;
2282  					}
2283  				}
2284  			}
2285  			dst = malloc (escaped_len + 1);
2286  			if (dst != NULL) {
2287  				for (p = start, d = dst; p < end; p ++, d ++) {
2288  					if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE | UCL_CHARACTER_WHITESPACE_UNSAFE)) {
2289  						switch (*p) {
2290  						case '\n':
2291  							*d++ = '\\';
2292  							*d = 'n';
2293  							break;
2294  						case '\r':
2295  							*d++ = '\\';
2296  							*d = 'r';
2297  							break;
2298  						case '\b':
2299  							*d++ = '\\';
2300  							*d = 'b';
2301  							break;
2302  						case '\t':
2303  							*d++ = '\\';
2304  							*d = 't';
2305  							break;
2306  						case '\f':
2307  							*d++ = '\\';
2308  							*d = 'f';
2309  							break;
2310  						case '\0':
2311  							*d++ = '\\';
2312  							*d++ = 'u';
2313  							*d++ = '0';
2314  							*d++ = '0';
2315  							*d++ = '0';
2316  							*d   = '0';
2317  							break;
2318  						case '\v':
2319  							*d++ = '\\';
2320  							*d++ = 'u';
2321  							*d++ = '0';
2322  							*d++ = '0';
2323  							*d++ = '0';
2324  							*d   = 'B';
2325  							break;
2326  						case '\\':
2327  							*d++ = '\\';
2328  							*d = '\\';
2329  							break;
2330  						case ' ':
2331  							*d = ' ';
2332  							break;
2333  						case '"':
2334  							*d++ = '\\';
2335  							*d = '"';
2336  							break;
2337  						}
2338  					}
2339  					else {
2340  						*d = *p;
2341  					}
2342  				}
2343  				*d = '\0';
2344  				obj->value.sv = dst;
2345  				obj->trash_stack[UCL_TRASH_VALUE] = dst;
2346  				obj->len = escaped_len;
2347  			}
2348  		}
2349  		else {
2350  			dst = malloc (end - start + 1);
2351  			if (dst != NULL) {
2352  				ucl_strlcpy_unsafe (dst, start, end - start + 1);
2353  				obj->value.sv = dst;
2354  				obj->trash_stack[UCL_TRASH_VALUE] = dst;
2355  				obj->len = end - start;
2356  			}
2357  		}
2358  		if ((flags & UCL_STRING_PARSE) && dst != NULL) {
2359  			/* Parse what we have */
2360  			if (flags & UCL_STRING_PARSE_BOOLEAN) {
2361  				if (!ucl_maybe_parse_boolean (obj, dst, obj->len) && (flags & UCL_STRING_PARSE_NUMBER)) {
2362  					ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
2363  							flags & UCL_STRING_PARSE_DOUBLE,
2364  							flags & UCL_STRING_PARSE_BYTES,
2365  							flags & UCL_STRING_PARSE_TIME);
2366  				}
2367  			}
2368  			else {
2369  				ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
2370  						flags & UCL_STRING_PARSE_DOUBLE,
2371  						flags & UCL_STRING_PARSE_BYTES,
2372  						flags & UCL_STRING_PARSE_TIME);
2373  			}
2374  		}
2375  	}
2376  
2377  	return obj;
2378  }
2379  
2380  static bool
2381  ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt,
2382  		const char *key, size_t keylen, bool copy_key, bool merge, bool replace)
2383  {
2384  	ucl_object_t *found, *tmp;
2385  	const ucl_object_t *cur;
2386  	ucl_object_iter_t it = NULL;
2387  	const char *p;
2388  	int ret = true;
2389  
2390  	if (elt == NULL || key == NULL) {
2391  		return false;
2392  	}
2393  
2394  	if (top == NULL) {
2395  		return false;
2396  	}
2397  
2398  	if (top->type != UCL_OBJECT) {
2399  		/* It is possible to convert NULL type to an object */
2400  		if (top->type == UCL_NULL) {
2401  			top->type = UCL_OBJECT;
2402  		}
2403  		else {
2404  			/* Refuse converting of other object types */
2405  			return false;
2406  		}
2407  	}
2408  
2409  	if (top->value.ov == NULL) {
2410  		top->value.ov = ucl_hash_create (false);
2411  	}
2412  
2413  	if (keylen == 0) {
2414  		keylen = strlen (key);
2415  	}
2416  
2417  	for (p = key; p < key + keylen; p ++) {
2418  		if (ucl_test_character (*p, UCL_CHARACTER_UCL_UNSAFE)) {
2419  			elt->flags |= UCL_OBJECT_NEED_KEY_ESCAPE;
2420  			break;
2421  		}
2422  	}
2423  
2424  	/* workaround for some use cases */
2425  	if (elt->trash_stack[UCL_TRASH_KEY] != NULL &&
2426  			key != (const char *)elt->trash_stack[UCL_TRASH_KEY]) {
2427  		/* Remove copied key */
2428  		free (elt->trash_stack[UCL_TRASH_KEY]);
2429  		elt->trash_stack[UCL_TRASH_KEY] = NULL;
2430  		elt->flags &= ~UCL_OBJECT_ALLOCATED_KEY;
2431  	}
2432  
2433  	elt->key = key;
2434  	elt->keylen = keylen;
2435  
2436  	if (copy_key) {
2437  		ucl_copy_key_trash (elt);
2438  	}
2439  
2440  	found = __DECONST (ucl_object_t *, ucl_hash_search_obj (top->value.ov, elt));
2441  
2442  	if (found == NULL) {
2443  		top->value.ov = ucl_hash_insert_object (top->value.ov, elt, false);
2444  		top->len ++;
2445  		if (replace) {
2446  			ret = false;
2447  		}
2448  	}
2449  	else {
2450  		if (replace) {
2451  			ucl_hash_replace (top->value.ov, found, elt);
2452  			ucl_object_unref (found);
2453  		}
2454  		else if (merge) {
2455  			if (found->type != UCL_OBJECT && elt->type == UCL_OBJECT) {
2456  				/* Insert old elt to new one */
2457  				ucl_object_insert_key_common (elt, found, found->key,
2458  						found->keylen, copy_key, false, false);
2459  				ucl_hash_delete (top->value.ov, found);
2460  				top->value.ov = ucl_hash_insert_object (top->value.ov, elt, false);
2461  			}
2462  			else if (found->type == UCL_OBJECT && elt->type != UCL_OBJECT) {
2463  				/* Insert new to old */
2464  				ucl_object_insert_key_common (found, elt, elt->key,
2465  						elt->keylen, copy_key, false, false);
2466  			}
2467  			else if (found->type == UCL_OBJECT && elt->type == UCL_OBJECT) {
2468  				/* Mix two hashes */
2469  				while ((cur = ucl_object_iterate (elt, &it, true)) != NULL) {
2470  					tmp = ucl_object_ref (cur);
2471  					ucl_object_insert_key_common (found, tmp, cur->key,
2472  							cur->keylen, copy_key, true, false);
2473  				}
2474  				ucl_object_unref (elt);
2475  			}
2476  			else {
2477  				/* Just make a list of scalars */
2478  				DL_CONCAT (found, elt);
2479  			}
2480  		}
2481  		else {
2482  			DL_CONCAT (found, elt);
2483  		}
2484  	}
2485  
2486  	return ret;
2487  }
2488  
2489  bool
2490  ucl_object_delete_keyl (ucl_object_t *top, const char *key, size_t keylen)
2491  {
2492  	ucl_object_t *found;
2493  
2494  	if (top == NULL || key == NULL) {
2495  		return false;
2496  	}
2497  
2498  	found = __DECONST (ucl_object_t *, ucl_object_lookup_len (top, key, keylen));
2499  
2500  	if (found == NULL) {
2501  		return false;
2502  	}
2503  
2504  	ucl_hash_delete (top->value.ov, found);
2505  	ucl_object_unref (found);
2506  	top->len --;
2507  
2508  	return true;
2509  }
2510  
2511  bool
2512  ucl_object_delete_key (ucl_object_t *top, const char *key)
2513  {
2514  	return ucl_object_delete_keyl (top, key, strlen (key));
2515  }
2516  
2517  ucl_object_t*
2518  ucl_object_pop_keyl (ucl_object_t *top, const char *key, size_t keylen)
2519  {
2520  	const ucl_object_t *found;
2521  
2522  	if (top == NULL || key == NULL) {
2523  		return false;
2524  	}
2525  	found = ucl_object_lookup_len (top, key, keylen);
2526  
2527  	if (found == NULL) {
2528  		return NULL;
2529  	}
2530  	ucl_hash_delete (top->value.ov, found);
2531  	top->len --;
2532  
2533  	return __DECONST (ucl_object_t *, found);
2534  }
2535  
2536  ucl_object_t*
2537  ucl_object_pop_key (ucl_object_t *top, const char *key)
2538  {
2539  	return ucl_object_pop_keyl (top, key, strlen (key));
2540  }
2541  
2542  bool
2543  ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt,
2544  		const char *key, size_t keylen, bool copy_key)
2545  {
2546  	return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, false);
2547  }
2548  
2549  bool
2550  ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt,
2551  		const char *key, size_t keylen, bool copy_key)
2552  {
2553  	return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, true, false);
2554  }
2555  
2556  bool
2557  ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt,
2558  		const char *key, size_t keylen, bool copy_key)
2559  {
2560  	return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, true);
2561  }
2562  
2563  bool
2564  ucl_object_merge (ucl_object_t *top, ucl_object_t *elt, bool copy)
2565  {
2566  	ucl_object_t *cur = NULL, *cp = NULL, *found = NULL;
2567  	ucl_object_iter_t iter = NULL;
2568  
2569  	if (top == NULL || elt == NULL) {
2570  		return false;
2571  	}
2572  
2573  	if (top->type == UCL_ARRAY) {
2574  		if (elt->type == UCL_ARRAY) {
2575  			/* Merge two arrays */
2576  			return ucl_array_merge (top, elt, copy);
2577  		}
2578  		else {
2579  			if (copy) {
2580  				ucl_array_append (top, ucl_object_copy (elt));
2581  
2582  				return true;
2583  			}
2584  			else {
2585  				ucl_array_append (top, ucl_object_ref (elt));
2586  
2587  				return true;
2588  			}
2589  		}
2590  	}
2591  	else if (top->type == UCL_OBJECT) {
2592  		if (elt->type == UCL_OBJECT) {
2593  			/* Mix two hashes */
2594  			while ((cur = (ucl_object_t *) ucl_hash_iterate (elt->value.ov,
2595  					&iter))) {
2596  
2597  				if (copy) {
2598  					cp = ucl_object_copy (cur);
2599  				} else {
2600  					cp = ucl_object_ref (cur);
2601  				}
2602  
2603  				found = __DECONST(ucl_object_t *,
2604  						ucl_hash_search (top->value.ov, cp->key, cp->keylen));
2605  
2606  				if (found == NULL) {
2607  					/* The key does not exist */
2608  					top->value.ov = ucl_hash_insert_object (top->value.ov, cp,
2609  							false);
2610  					top->len++;
2611  				}
2612  				else {
2613  					/* The key already exists, merge it recursively */
2614  					if (found->type == UCL_OBJECT || found->type == UCL_ARRAY) {
2615  						if (!ucl_object_merge (found, cp, copy)) {
2616  							return false;
2617  						}
2618  						ucl_object_unref (cp);
2619  					}
2620  					else {
2621  						ucl_hash_replace (top->value.ov, found, cp);
2622  						ucl_object_unref (found);
2623  					}
2624  				}
2625  			}
2626  		}
2627  		else {
2628  			if (copy) {
2629  				cp = ucl_object_copy (elt);
2630  			}
2631  			else {
2632  				cp = ucl_object_ref (elt);
2633  			}
2634  
2635  			found = __DECONST(ucl_object_t *,
2636  					ucl_hash_search (top->value.ov, cp->key, cp->keylen));
2637  
2638  			if (found == NULL) {
2639  				/* The key does not exist */
2640  				top->value.ov = ucl_hash_insert_object (top->value.ov, cp,
2641  						false);
2642  				top->len++;
2643  			}
2644  			else {
2645  				/* The key already exists, merge it recursively */
2646  				if (found->type == UCL_OBJECT || found->type == UCL_ARRAY) {
2647  					if (!ucl_object_merge (found, cp, copy)) {
2648  						return false;
2649  					}
2650  					ucl_object_unref (cp);
2651  				}
2652  				else {
2653  					ucl_hash_replace (top->value.ov, found, cp);
2654  					ucl_object_unref (found);
2655  				}
2656  			}
2657  		}
2658  	}
2659  	else {
2660  		/* Cannot merge trivial objects */
2661  		return false;
2662  	}
2663  
2664  	return true;
2665  }
2666  
2667  const ucl_object_t *
2668  ucl_object_lookup_len (const ucl_object_t *obj, const char *key, size_t klen)
2669  {
2670  	const ucl_object_t *ret;
2671  	ucl_object_t srch;
2672  
2673  	if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) {
2674  		return NULL;
2675  	}
2676  
2677  	srch.key = key;
2678  	srch.keylen = klen;
2679  	ret = ucl_hash_search_obj (obj->value.ov, &srch);
2680  
2681  	return ret;
2682  }
2683  
2684  const ucl_object_t *
2685  ucl_object_lookup (const ucl_object_t *obj, const char *key)
2686  {
2687  	if (key == NULL) {
2688  		return NULL;
2689  	}
2690  
2691  	return ucl_object_lookup_len (obj, key, strlen (key));
2692  }
2693  
2694  const ucl_object_t*
2695  ucl_object_lookup_any (const ucl_object_t *obj,
2696  		const char *key, ...)
2697  {
2698  	va_list ap;
2699  	const ucl_object_t *ret = NULL;
2700  	const char *nk = NULL;
2701  
2702  	if (obj == NULL || key == NULL) {
2703  		return NULL;
2704  	}
2705  
2706  	ret = ucl_object_lookup_len (obj, key, strlen (key));
2707  
2708  	if (ret == NULL) {
2709  		va_start (ap, key);
2710  
2711  		while (ret == NULL) {
2712  			nk = va_arg (ap, const char *);
2713  
2714  			if (nk == NULL) {
2715  				break;
2716  			}
2717  			else {
2718  				ret = ucl_object_lookup_len (obj, nk, strlen (nk));
2719  			}
2720  		}
2721  
2722  		va_end (ap);
2723  	}
2724  
2725  	return ret;
2726  }
2727  
2728  const ucl_object_t*
2729  ucl_object_iterate_with_error (const ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values,
2730      int *ep)
2731  {
2732  	const ucl_object_t *elt = NULL;
2733  
2734  	if (obj == NULL || iter == NULL) {
2735  		return NULL;
2736  	}
2737  
2738  	if (expand_values) {
2739  		switch (obj->type) {
2740  		case UCL_OBJECT:
2741  			return (const ucl_object_t*)ucl_hash_iterate2 (obj->value.ov, iter, ep);
2742  			break;
2743  		case UCL_ARRAY: {
2744  			unsigned int idx;
2745  			UCL_ARRAY_GET (vec, obj);
2746  			idx = (unsigned int)(uintptr_t)(*iter);
2747  
2748  			if (vec != NULL) {
2749  				while (idx < kv_size (*vec)) {
2750  					if ((elt = kv_A (*vec, idx)) != NULL) {
2751  						idx ++;
2752  						break;
2753  					}
2754  					idx ++;
2755  				}
2756  				*iter = (void *)(uintptr_t)idx;
2757  			}
2758  
2759  			return elt;
2760  			break;
2761  		}
2762  		default:
2763  			/* Go to linear iteration */
2764  			break;
2765  		}
2766  	}
2767  	/* Treat everything as a linear list */
2768  	elt = *iter;
2769  	if (elt == NULL) {
2770  		elt = obj;
2771  	}
2772  	else if (elt == obj) {
2773  		return NULL;
2774  	}
2775  	*iter = __DECONST (void *, elt->next ? elt->next : obj);
2776  	return elt;
2777  
2778  	/* Not reached */
2779  	return NULL;
2780  }
2781  
2782  enum ucl_safe_iter_flags {
2783  	UCL_ITERATE_FLAG_UNDEFINED = 0,
2784  	UCL_ITERATE_FLAG_INSIDE_ARRAY,
2785  	UCL_ITERATE_FLAG_INSIDE_OBJECT,
2786  	UCL_ITERATE_FLAG_IMPLICIT,
2787  	UCL_ITERATE_FLAG_EXCEPTION
2788  };
2789  
2790  static const char safe_iter_magic[4] = {'u', 'i', 't', 'e'};
2791  struct ucl_object_safe_iter {
2792  	char magic[4]; /* safety check */
2793  	uint32_t flags;
2794  	const ucl_object_t *impl_it; /* implicit object iteration */
2795  	ucl_object_iter_t expl_it; /* explicit iteration */
2796  };
2797  
2798  #define UCL_SAFE_ITER(ptr) (struct ucl_object_safe_iter *)(ptr)
2799  #define UCL_SAFE_ITER_CHECK(it) do { \
2800  	assert (it != NULL); \
2801  	assert (memcmp (it->magic, safe_iter_magic, sizeof (it->magic)) == 0); \
2802   } while (0)
2803  
2804  ucl_object_iter_t
2805  ucl_object_iterate_new (const ucl_object_t *obj)
2806  {
2807  	struct ucl_object_safe_iter *it;
2808  
2809  	it = UCL_ALLOC (sizeof (*it));
2810  	if (it != NULL) {
2811  		memcpy (it->magic, safe_iter_magic, sizeof (it->magic));
2812  		it->flags = UCL_ITERATE_FLAG_UNDEFINED;
2813  		it->expl_it = NULL;
2814  		it->impl_it = obj;
2815  	}
2816  
2817  	return (ucl_object_iter_t)it;
2818  }
2819  
2820  bool
2821  ucl_object_iter_chk_excpn(ucl_object_iter_t *it)
2822  {
2823          struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it);
2824  
2825          UCL_SAFE_ITER_CHECK (rit);
2826  
2827  	return (rit->flags == UCL_ITERATE_FLAG_EXCEPTION);
2828  }
2829  
2830  ucl_object_iter_t
2831  ucl_object_iterate_reset (ucl_object_iter_t it, const ucl_object_t *obj)
2832  {
2833  	struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it);
2834  
2835  	UCL_SAFE_ITER_CHECK (rit);
2836  
2837  	if (rit->expl_it != NULL) {
2838  		if (rit->flags == UCL_ITERATE_FLAG_INSIDE_OBJECT) {
2839  			UCL_FREE (sizeof (*rit->expl_it), rit->expl_it);
2840  		}
2841  	}
2842  
2843  	rit->impl_it = obj;
2844  	rit->expl_it = NULL;
2845  	rit->flags = UCL_ITERATE_FLAG_UNDEFINED;
2846  
2847  	return it;
2848  }
2849  
2850  const ucl_object_t*
2851  ucl_object_iterate_safe (ucl_object_iter_t it, bool expand_values)
2852  {
2853  	return ucl_object_iterate_full (it, expand_values ? UCL_ITERATE_BOTH :
2854  			UCL_ITERATE_IMPLICIT);
2855  }
2856  
2857  const ucl_object_t*
2858  ucl_object_iterate_full (ucl_object_iter_t it, enum ucl_iterate_type type)
2859  {
2860  	struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it);
2861  	const ucl_object_t *ret = NULL;
2862  	int ern;
2863  
2864  	UCL_SAFE_ITER_CHECK (rit);
2865  
2866  	if (rit->impl_it == NULL) {
2867  		return NULL;
2868  	}
2869  
2870  	if (rit->impl_it->type == UCL_OBJECT) {
2871  		rit->flags = UCL_ITERATE_FLAG_INSIDE_OBJECT;
2872  		ret = ucl_object_iterate_with_error (rit->impl_it, &rit->expl_it, true, &ern);
2873  
2874  		if (ret == NULL && ern != 0) {
2875  			rit->flags = UCL_ITERATE_FLAG_EXCEPTION;
2876  			return NULL;
2877  		}
2878  
2879  		if (ret == NULL && (type & UCL_ITERATE_IMPLICIT)) {
2880  			/* Need to switch to another implicit object in chain */
2881  			rit->impl_it = rit->impl_it->next;
2882  			rit->expl_it = NULL;
2883  
2884  			return ucl_object_iterate_safe (it, type);
2885  		}
2886  	}
2887  	else if (rit->impl_it->type == UCL_ARRAY) {
2888  		rit->flags = UCL_ITERATE_FLAG_INSIDE_ARRAY;
2889  		ret = ucl_object_iterate (rit->impl_it, &rit->expl_it, true);
2890  
2891  		if (ret == NULL && (type & UCL_ITERATE_IMPLICIT)) {
2892  			/* Need to switch to another implicit object in chain */
2893  			rit->impl_it = rit->impl_it->next;
2894  			rit->expl_it = NULL;
2895  
2896  			return ucl_object_iterate_safe (it, type);
2897  		}
2898  	}
2899  	else {
2900  		/* Just iterate over the implicit array */
2901  		rit->flags = UCL_ITERATE_FLAG_IMPLICIT;
2902  		ret = rit->impl_it;
2903  		rit->impl_it = rit->impl_it->next;
2904  
2905  		if (type & UCL_ITERATE_EXPLICIT) {
2906  			/* We flatten objects if need to expand values */
2907  			if (ret->type == UCL_OBJECT || ret->type == UCL_ARRAY) {
2908  				return ucl_object_iterate_safe (it, type);
2909  			}
2910  		}
2911  	}
2912  
2913  	return ret;
2914  }
2915  
2916  void
2917  ucl_object_iterate_free (ucl_object_iter_t it)
2918  {
2919  	struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it);
2920  
2921  	UCL_SAFE_ITER_CHECK (rit);
2922  
2923  	if (rit->expl_it != NULL) {
2924  		if (rit->flags == UCL_ITERATE_FLAG_INSIDE_OBJECT) {
2925  			UCL_FREE (sizeof (*rit->expl_it), rit->expl_it);
2926  		}
2927  	}
2928  
2929  	UCL_FREE (sizeof (*rit), it);
2930  }
2931  
2932  const ucl_object_t *
2933  ucl_object_lookup_path (const ucl_object_t *top, const char *path_in) {
2934  	return ucl_object_lookup_path_char (top, path_in, '.');
2935  }
2936  
2937  
2938  const ucl_object_t *
2939  ucl_object_lookup_path_char (const ucl_object_t *top, const char *path_in, const char sep) {
2940  	const ucl_object_t *o = NULL, *found;
2941  	const char *p, *c;
2942  	char *err_str;
2943  	unsigned index;
2944  
2945  	if (path_in == NULL || top == NULL) {
2946  		return NULL;
2947  	}
2948  
2949  	found = NULL;
2950  	p = path_in;
2951  
2952  	/* Skip leading dots */
2953  	while (*p == sep) {
2954  		p ++;
2955  	}
2956  
2957  	c = p;
2958  	while (*p != '\0') {
2959  		p ++;
2960  		if (*p == sep || *p == '\0') {
2961  			if (p > c) {
2962  				switch (top->type) {
2963  				case UCL_ARRAY:
2964  					/* Key should be an int */
2965  					index = strtoul (c, &err_str, 10);
2966  					if (err_str != NULL && (*err_str != sep && *err_str != '\0')) {
2967  						return NULL;
2968  					}
2969  					o = ucl_array_find_index (top, index);
2970  					break;
2971  				default:
2972  					o = ucl_object_lookup_len (top, c, p - c);
2973  					break;
2974  				}
2975  				if (o == NULL) {
2976  					return NULL;
2977  				}
2978  				top = o;
2979  			}
2980  			if (*p != '\0') {
2981  				c = p + 1;
2982  			}
2983  		}
2984  	}
2985  	found = o;
2986  
2987  	return found;
2988  }
2989  
2990  
2991  ucl_object_t *
2992  ucl_object_new (void)
2993  {
2994  	return ucl_object_typed_new (UCL_NULL);
2995  }
2996  
2997  ucl_object_t *
2998  ucl_object_typed_new (ucl_type_t type)
2999  {
3000  	return ucl_object_new_full (type, 0);
3001  }
3002  
3003  ucl_object_t *
3004  ucl_object_new_full (ucl_type_t type, unsigned priority)
3005  {
3006  	ucl_object_t *new;
3007  
3008  	if (type != UCL_USERDATA) {
3009  		new = UCL_ALLOC (sizeof (ucl_object_t));
3010  		if (new != NULL) {
3011  			memset (new, 0, sizeof (ucl_object_t));
3012  			new->ref = 1;
3013  			new->type = (type <= UCL_NULL ? type : UCL_NULL);
3014  			new->next = NULL;
3015  			new->prev = new;
3016  			ucl_object_set_priority (new, priority);
3017  
3018  			if (type == UCL_ARRAY) {
3019  				new->value.av = UCL_ALLOC (sizeof (ucl_array_t));
3020  				if (new->value.av) {
3021  					memset (new->value.av, 0, sizeof (ucl_array_t));
3022  					UCL_ARRAY_GET (vec, new);
3023  
3024  					/* Preallocate some space for arrays */
3025  					kv_resize_safe (ucl_object_t *, *vec, 8, enomem);
3026  				}
3027  			}
3028  		}
3029  	}
3030  	else {
3031  		new = ucl_object_new_userdata (NULL, NULL, NULL);
3032  		ucl_object_set_priority (new, priority);
3033  	}
3034  enomem:
3035  	return new;
3036  }
3037  
3038  bool ucl_object_reserve (ucl_object_t *obj, size_t reserved)
3039  {
3040  	if (obj->type == UCL_ARRAY) {
3041  		UCL_ARRAY_GET (vec, obj);
3042  
3043  		if (vec->m < reserved) {
3044  			/* Preallocate some space for arrays */
3045  			kv_resize_safe (ucl_object_t *, *vec, reserved, e0);
3046  		}
3047  	}
3048  	else if (obj->type == UCL_OBJECT) {
3049  		ucl_hash_reserve (obj->value.ov, reserved);
3050  	}
3051  	return true;
3052  e0:
3053  	return false;
3054  }
3055  
3056  ucl_object_t*
3057  ucl_object_new_userdata (ucl_userdata_dtor dtor,
3058  		ucl_userdata_emitter emitter,
3059  		void *ptr)
3060  {
3061  	struct ucl_object_userdata *new;
3062  	size_t nsize = sizeof (*new);
3063  
3064  	new = UCL_ALLOC (nsize);
3065  	if (new != NULL) {
3066  		memset (new, 0, nsize);
3067  		new->obj.ref = 1;
3068  		new->obj.type = UCL_USERDATA;
3069  		new->obj.next = NULL;
3070  		new->obj.prev = (ucl_object_t *)new;
3071  		new->dtor = dtor;
3072  		new->emitter = emitter;
3073  		new->obj.value.ud = ptr;
3074  	}
3075  
3076  	return (ucl_object_t *)new;
3077  }
3078  
3079  ucl_type_t
3080  ucl_object_type (const ucl_object_t *obj)
3081  {
3082  	if (obj == NULL) {
3083  		return UCL_NULL;
3084  	}
3085  
3086  	return obj->type;
3087  }
3088  
3089  ucl_object_t*
3090  ucl_object_fromstring (const char *str)
3091  {
3092  	return ucl_object_fromstring_common (str, 0, UCL_STRING_RAW);
3093  }
3094  
3095  ucl_object_t *
3096  ucl_object_fromlstring (const char *str, size_t len)
3097  {
3098  	return ucl_object_fromstring_common (str, len, UCL_STRING_RAW);
3099  }
3100  
3101  ucl_object_t *
3102  ucl_object_fromint (int64_t iv)
3103  {
3104  	ucl_object_t *obj;
3105  
3106  	obj = ucl_object_new ();
3107  	if (obj != NULL) {
3108  		obj->type = UCL_INT;
3109  		obj->value.iv = iv;
3110  	}
3111  
3112  	return obj;
3113  }
3114  
3115  ucl_object_t *
3116  ucl_object_fromdouble (double dv)
3117  {
3118  	ucl_object_t *obj;
3119  
3120  	obj = ucl_object_new ();
3121  	if (obj != NULL) {
3122  		obj->type = UCL_FLOAT;
3123  		obj->value.dv = dv;
3124  	}
3125  
3126  	return obj;
3127  }
3128  
3129  ucl_object_t*
3130  ucl_object_frombool (bool bv)
3131  {
3132  	ucl_object_t *obj;
3133  
3134  	obj = ucl_object_new ();
3135  	if (obj != NULL) {
3136  		obj->type = UCL_BOOLEAN;
3137  		obj->value.iv = bv;
3138  	}
3139  
3140  	return obj;
3141  }
3142  
3143  bool
3144  ucl_array_append (ucl_object_t *top, ucl_object_t *elt)
3145  {
3146  	UCL_ARRAY_GET (vec, top);
3147  
3148  	if (elt == NULL || top == NULL) {
3149  		return false;
3150  	}
3151  
3152  	if (vec == NULL) {
3153  		vec = UCL_ALLOC (sizeof (*vec));
3154  
3155  		if (vec == NULL) {
3156  			return false;
3157  		}
3158  
3159  		kv_init (*vec);
3160  		top->value.av = (void *)vec;
3161  	}
3162  
3163  	kv_push_safe (ucl_object_t *, *vec, elt, e0);
3164  
3165  	top->len ++;
3166  
3167  	return true;
3168  e0:
3169  	return false;
3170  }
3171  
3172  bool
3173  ucl_array_prepend (ucl_object_t *top, ucl_object_t *elt)
3174  {
3175  	UCL_ARRAY_GET (vec, top);
3176  
3177  	if (elt == NULL || top == NULL) {
3178  		return false;
3179  	}
3180  
3181  	if (vec == NULL) {
3182  		vec = UCL_ALLOC (sizeof (*vec));
3183  		kv_init (*vec);
3184  		top->value.av = (void *)vec;
3185  		kv_push_safe (ucl_object_t *, *vec, elt, e0);
3186  	}
3187  	else {
3188  		/* Slow O(n) algorithm */
3189  		kv_prepend_safe (ucl_object_t *, *vec, elt, e0);
3190  	}
3191  
3192  	top->len ++;
3193  
3194  	return true;
3195  e0:
3196  	return false;
3197  }
3198  
3199  bool
3200  ucl_array_merge (ucl_object_t *top, ucl_object_t *elt, bool copy)
3201  {
3202  	unsigned i;
3203  	ucl_object_t *cp = NULL;
3204  	ucl_object_t **obj;
3205  
3206  	if (elt == NULL || top == NULL || top->type != UCL_ARRAY || elt->type != UCL_ARRAY) {
3207  		return false;
3208  	}
3209  
3210  	if (copy) {
3211  		cp = ucl_object_copy (elt);
3212  	}
3213  	else {
3214  		cp = ucl_object_ref (elt);
3215  	}
3216  
3217  	UCL_ARRAY_GET (v1, top);
3218  	UCL_ARRAY_GET (v2, cp);
3219  
3220  	if (v1 && v2) {
3221  		kv_concat_safe (ucl_object_t *, *v1, *v2, e0);
3222  
3223  		for (i = v2->n; i < v1->n; i ++) {
3224  			obj = &kv_A (*v1, i);
3225  			if (*obj == NULL) {
3226  				continue;
3227  			}
3228  			top->len ++;
3229  		}
3230  	}
3231  
3232  	return true;
3233  e0:
3234  	return false;
3235  }
3236  
3237  ucl_object_t *
3238  ucl_array_delete (ucl_object_t *top, ucl_object_t *elt)
3239  {
3240  	UCL_ARRAY_GET (vec, top);
3241  	ucl_object_t *ret = NULL;
3242  	unsigned i;
3243  
3244  	if (vec == NULL) {
3245  		return NULL;
3246  	}
3247  
3248  	for (i = 0; i < vec->n; i ++) {
3249  		if (kv_A (*vec, i) == elt) {
3250  			kv_del (ucl_object_t *, *vec, i);
3251  			ret = elt;
3252  			top->len --;
3253  			break;
3254  		}
3255  	}
3256  
3257  	return ret;
3258  }
3259  
3260  const ucl_object_t *
3261  ucl_array_head (const ucl_object_t *top)
3262  {
3263  	UCL_ARRAY_GET (vec, top);
3264  
3265  	if (vec == NULL || top == NULL || top->type != UCL_ARRAY ||
3266  			top->value.av == NULL) {
3267  		return NULL;
3268  	}
3269  
3270  	return (vec->n > 0 ? vec->a[0] : NULL);
3271  }
3272  
3273  const ucl_object_t *
3274  ucl_array_tail (const ucl_object_t *top)
3275  {
3276  	UCL_ARRAY_GET (vec, top);
3277  
3278  	if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
3279  		return NULL;
3280  	}
3281  
3282  	return (vec->n > 0 ? vec->a[vec->n - 1] : NULL);
3283  }
3284  
3285  ucl_object_t *
3286  ucl_array_pop_last (ucl_object_t *top)
3287  {
3288  	UCL_ARRAY_GET (vec, top);
3289  	ucl_object_t **obj, *ret = NULL;
3290  
3291  	if (vec != NULL && vec->n > 0) {
3292  		obj = &kv_A (*vec, vec->n - 1);
3293  		ret = *obj;
3294  		kv_del (ucl_object_t *, *vec, vec->n - 1);
3295  		top->len --;
3296  	}
3297  
3298  	return ret;
3299  }
3300  
3301  ucl_object_t *
3302  ucl_array_pop_first (ucl_object_t *top)
3303  {
3304  	UCL_ARRAY_GET (vec, top);
3305  	ucl_object_t **obj, *ret = NULL;
3306  
3307  	if (vec != NULL && vec->n > 0) {
3308  		obj = &kv_A (*vec, 0);
3309  		ret = *obj;
3310  		kv_del (ucl_object_t *, *vec, 0);
3311  		top->len --;
3312  	}
3313  
3314  	return ret;
3315  }
3316  
3317  unsigned int
3318  ucl_array_size (const ucl_object_t *top)
3319  {
3320  	if (top == NULL || top->type != UCL_ARRAY) {
3321  		return 0;
3322  	}
3323  
3324  	UCL_ARRAY_GET (vec, top);
3325  
3326  	if (vec != NULL) {
3327  		return kv_size(*vec);
3328  	}
3329  
3330  	return 0;
3331  }
3332  
3333  const ucl_object_t *
3334  ucl_array_find_index (const ucl_object_t *top, unsigned int index)
3335  {
3336  	UCL_ARRAY_GET (vec, top);
3337  
3338  	if (vec != NULL && vec->n > 0 && index < vec->n) {
3339  		return kv_A (*vec, index);
3340  	}
3341  
3342  	return NULL;
3343  }
3344  
3345  unsigned int
3346  ucl_array_index_of (ucl_object_t *top, ucl_object_t *elt)
3347  {
3348  	UCL_ARRAY_GET (vec, top);
3349  	unsigned i;
3350  
3351  	if (vec == NULL) {
3352  		return (unsigned int)(-1);
3353  	}
3354  
3355  	for (i = 0; i < vec->n; i ++) {
3356  		if (kv_A (*vec, i) == elt) {
3357  			return i;
3358  		}
3359  	}
3360  
3361  	return (unsigned int)(-1);
3362  }
3363  
3364  ucl_object_t *
3365  ucl_array_replace_index (ucl_object_t *top, ucl_object_t *elt,
3366  	unsigned int index)
3367  {
3368  	UCL_ARRAY_GET (vec, top);
3369  	ucl_object_t *ret = NULL;
3370  
3371  	if (vec != NULL && vec->n > 0 && index < vec->n) {
3372  		ret = kv_A (*vec, index);
3373  		kv_A (*vec, index) = elt;
3374  	}
3375  
3376  	return ret;
3377  }
3378  
3379  ucl_object_t *
3380  ucl_elt_append (ucl_object_t *head, ucl_object_t *elt)
3381  {
3382  
3383  	if (head == NULL) {
3384  		elt->next = NULL;
3385  		elt->prev = elt;
3386  		head = elt;
3387  	}
3388  	else {
3389  		elt->prev = head->prev;
3390  		head->prev->next = elt;
3391  		head->prev = elt;
3392  		elt->next = NULL;
3393  	}
3394  
3395  	return head;
3396  }
3397  
3398  bool
3399  ucl_object_todouble_safe (const ucl_object_t *obj, double *target)
3400  {
3401  	if (obj == NULL || target == NULL) {
3402  		return false;
3403  	}
3404  	switch (obj->type) {
3405  	case UCL_INT:
3406  		*target = obj->value.iv; /* Probably could cause overflow */
3407  		break;
3408  	case UCL_FLOAT:
3409  	case UCL_TIME:
3410  		*target = obj->value.dv;
3411  		break;
3412  	default:
3413  		return false;
3414  	}
3415  
3416  	return true;
3417  }
3418  
3419  double
3420  ucl_object_todouble (const ucl_object_t *obj)
3421  {
3422  	double result = 0.;
3423  
3424  	ucl_object_todouble_safe (obj, &result);
3425  	return result;
3426  }
3427  
3428  bool
3429  ucl_object_toint_safe (const ucl_object_t *obj, int64_t *target)
3430  {
3431  	if (obj == NULL || target == NULL) {
3432  		return false;
3433  	}
3434  	switch (obj->type) {
3435  	case UCL_INT:
3436  		*target = obj->value.iv;
3437  		break;
3438  	case UCL_FLOAT:
3439  	case UCL_TIME:
3440  		*target = obj->value.dv; /* Losing of decimal points */
3441  		break;
3442  	default:
3443  		return false;
3444  	}
3445  
3446  	return true;
3447  }
3448  
3449  int64_t
3450  ucl_object_toint (const ucl_object_t *obj)
3451  {
3452  	int64_t result = 0;
3453  
3454  	ucl_object_toint_safe (obj, &result);
3455  	return result;
3456  }
3457  
3458  bool
3459  ucl_object_toboolean_safe (const ucl_object_t *obj, bool *target)
3460  {
3461  	if (obj == NULL || target == NULL) {
3462  		return false;
3463  	}
3464  	switch (obj->type) {
3465  	case UCL_BOOLEAN:
3466  		*target = (obj->value.iv == true);
3467  		break;
3468  	default:
3469  		return false;
3470  	}
3471  
3472  	return true;
3473  }
3474  
3475  bool
3476  ucl_object_toboolean (const ucl_object_t *obj)
3477  {
3478  	bool result = false;
3479  
3480  	ucl_object_toboolean_safe (obj, &result);
3481  	return result;
3482  }
3483  
3484  bool
3485  ucl_object_tostring_safe (const ucl_object_t *obj, const char **target)
3486  {
3487  	if (obj == NULL || target == NULL) {
3488  		return false;
3489  	}
3490  
3491  	switch (obj->type) {
3492  	case UCL_STRING:
3493  		if (!(obj->flags & UCL_OBJECT_BINARY)) {
3494  			*target = ucl_copy_value_trash (obj);
3495  		}
3496  		break;
3497  	default:
3498  		return false;
3499  	}
3500  
3501  	return true;
3502  }
3503  
3504  const char *
3505  ucl_object_tostring (const ucl_object_t *obj)
3506  {
3507  	const char *result = NULL;
3508  
3509  	ucl_object_tostring_safe (obj, &result);
3510  	return result;
3511  }
3512  
3513  const char *
3514  ucl_object_tostring_forced (const ucl_object_t *obj)
3515  {
3516  	/* TODO: For binary strings we might encode string here */
3517  	if (!(obj->flags & UCL_OBJECT_BINARY)) {
3518  		return ucl_copy_value_trash (obj);
3519  	}
3520  
3521  	return NULL;
3522  }
3523  
3524  bool
3525  ucl_object_tolstring_safe (const ucl_object_t *obj, const char **target, size_t *tlen)
3526  {
3527  	if (obj == NULL || target == NULL) {
3528  		return false;
3529  	}
3530  	switch (obj->type) {
3531  	case UCL_STRING:
3532  		*target = obj->value.sv;
3533  		if (tlen != NULL) {
3534  			*tlen = obj->len;
3535  		}
3536  		break;
3537  	default:
3538  		return false;
3539  	}
3540  
3541  	return true;
3542  }
3543  
3544  const char *
3545  ucl_object_tolstring (const ucl_object_t *obj, size_t *tlen)
3546  {
3547  	const char *result = NULL;
3548  
3549  	ucl_object_tolstring_safe (obj, &result, tlen);
3550  	return result;
3551  }
3552  
3553  const char *
3554  ucl_object_key (const ucl_object_t *obj)
3555  {
3556  	return ucl_copy_key_trash (obj);
3557  }
3558  
3559  const char *
3560  ucl_object_keyl (const ucl_object_t *obj, size_t *len)
3561  {
3562  	if (len == NULL || obj == NULL) {
3563  		return NULL;
3564  	}
3565  	*len = obj->keylen;
3566  	return obj->key;
3567  }
3568  
3569  ucl_object_t *
3570  ucl_object_ref (const ucl_object_t *obj)
3571  {
3572  	ucl_object_t *res = NULL;
3573  
3574  	if (obj != NULL) {
3575  		if (obj->flags & UCL_OBJECT_EPHEMERAL) {
3576  			/*
3577  			 * Use deep copy for ephemeral objects, note that its refcount
3578  			 * is NOT increased, since ephemeral objects does not need refcount
3579  			 * at all
3580  			 */
3581  			res = ucl_object_copy (obj);
3582  		}
3583  		else {
3584  			res = __DECONST (ucl_object_t *, obj);
3585  #ifdef HAVE_ATOMIC_BUILTINS
3586  			(void)__sync_add_and_fetch (&res->ref, 1);
3587  #else
3588  			res->ref ++;
3589  #endif
3590  		}
3591  	}
3592  	return res;
3593  }
3594  
3595  static ucl_object_t *
3596  ucl_object_copy_internal (const ucl_object_t *other, bool allow_array)
3597  {
3598  
3599  	ucl_object_t *new;
3600  	ucl_object_iter_t it = NULL;
3601  	const ucl_object_t *cur;
3602  
3603  	new = malloc (sizeof (*new));
3604  
3605  	if (new != NULL) {
3606  		memcpy (new, other, sizeof (*new));
3607  		if (other->flags & UCL_OBJECT_EPHEMERAL) {
3608  			/* Copied object is always non ephemeral */
3609  			new->flags &= ~UCL_OBJECT_EPHEMERAL;
3610  		}
3611  		new->ref = 1;
3612  		/* Unlink from others */
3613  		new->next = NULL;
3614  		new->prev = new;
3615  
3616  		/* deep copy of values stored */
3617  		if (other->trash_stack[UCL_TRASH_KEY] != NULL) {
3618  			new->trash_stack[UCL_TRASH_KEY] = NULL;
3619  			if (other->key == (const char *)other->trash_stack[UCL_TRASH_KEY]) {
3620  				new->trash_stack[UCL_TRASH_KEY] = malloc(other->keylen + 1);
3621  				memcpy(new->trash_stack[UCL_TRASH_KEY], other->trash_stack[UCL_TRASH_KEY], other->keylen);
3622  				new->trash_stack[UCL_TRASH_KEY][other->keylen] = '\0';
3623  				new->key = new->trash_stack[UCL_TRASH_KEY];
3624  			}
3625  		}
3626  		if (other->trash_stack[UCL_TRASH_VALUE] != NULL) {
3627  			new->trash_stack[UCL_TRASH_VALUE] =
3628  					strdup (other->trash_stack[UCL_TRASH_VALUE]);
3629  			if (new->type == UCL_STRING) {
3630  				new->value.sv = new->trash_stack[UCL_TRASH_VALUE];
3631  			}
3632  		}
3633  
3634  		if (other->type == UCL_ARRAY || other->type == UCL_OBJECT) {
3635  			/* reset old value */
3636  			memset (&new->value, 0, sizeof (new->value));
3637  
3638  			while ((cur = ucl_object_iterate (other, &it, true)) != NULL) {
3639  				if (other->type == UCL_ARRAY) {
3640  					ucl_array_append (new, ucl_object_copy_internal (cur, false));
3641  				}
3642  				else {
3643  					ucl_object_t *cp = ucl_object_copy_internal (cur, true);
3644  					if (cp != NULL) {
3645  						ucl_object_insert_key (new, cp, cp->key, cp->keylen,
3646  								false);
3647  					}
3648  				}
3649  			}
3650  		}
3651  		else if (allow_array && other->next != NULL) {
3652  			LL_FOREACH (other->next, cur) {
3653  				ucl_object_t *cp = ucl_object_copy_internal (cur, false);
3654  				if (cp != NULL) {
3655  					DL_APPEND (new, cp);
3656  				}
3657  			}
3658  		}
3659  	}
3660  
3661  	return new;
3662  }
3663  
3664  ucl_object_t *
3665  ucl_object_copy (const ucl_object_t *other)
3666  {
3667  	return ucl_object_copy_internal (other, true);
3668  }
3669  
3670  void
3671  ucl_object_unref (ucl_object_t *obj)
3672  {
3673  	if (obj != NULL) {
3674  #ifdef HAVE_ATOMIC_BUILTINS
3675  		unsigned int rc = __sync_sub_and_fetch (&obj->ref, 1);
3676  		if (rc == 0) {
3677  #else
3678  		if (--obj->ref == 0) {
3679  #endif
3680  			ucl_object_free_internal (obj, true, ucl_object_dtor_unref);
3681  		}
3682  	}
3683  }
3684  
3685  int
3686  ucl_object_compare (const ucl_object_t *o1, const ucl_object_t *o2)
3687  {
3688  	const ucl_object_t *it1, *it2;
3689  	ucl_object_iter_t iter = NULL;
3690  	int ret = 0;
3691  
3692  	if (o1->type != o2->type) {
3693  		return (o1->type) - (o2->type);
3694  	}
3695  
3696  	switch (o1->type) {
3697  	case UCL_STRING:
3698  		if (o1->len == o2->len && o1->len > 0) {
3699  			ret = strcmp (ucl_object_tostring(o1), ucl_object_tostring(o2));
3700  		}
3701  		else {
3702  			ret = o1->len - o2->len;
3703  		}
3704  		break;
3705  	case UCL_FLOAT:
3706  	case UCL_INT:
3707  	case UCL_TIME:
3708  		ret = ucl_object_todouble (o1) - ucl_object_todouble (o2);
3709  		break;
3710  	case UCL_BOOLEAN:
3711  		ret = ucl_object_toboolean (o1) - ucl_object_toboolean (o2);
3712  		break;
3713  	case UCL_ARRAY:
3714  		if (o1->len == o2->len && o1->len > 0) {
3715  			UCL_ARRAY_GET (vec1, o1);
3716  			UCL_ARRAY_GET (vec2, o2);
3717  			unsigned i;
3718  
3719  			/* Compare all elements in both arrays */
3720  			for (i = 0; i < vec1->n; i ++) {
3721  				it1 = kv_A (*vec1, i);
3722  				it2 = kv_A (*vec2, i);
3723  
3724  				if (it1 == NULL && it2 != NULL) {
3725  					return -1;
3726  				}
3727  				else if (it2 == NULL && it1 != NULL) {
3728  					return 1;
3729  				}
3730  				else if (it1 != NULL && it2 != NULL) {
3731  					ret = ucl_object_compare (it1, it2);
3732  					if (ret != 0) {
3733  						break;
3734  					}
3735  				}
3736  			}
3737  		}
3738  		else {
3739  			ret = o1->len - o2->len;
3740  		}
3741  		break;
3742  	case UCL_OBJECT:
3743  		if (o1->len == o2->len && o1->len > 0) {
3744  			while ((it1 = ucl_object_iterate (o1, &iter, true)) != NULL) {
3745  				it2 = ucl_object_lookup (o2, ucl_object_key (it1));
3746  				if (it2 == NULL) {
3747  					ret = 1;
3748  					break;
3749  				}
3750  				ret = ucl_object_compare (it1, it2);
3751  				if (ret != 0) {
3752  					break;
3753  				}
3754  			}
3755  		}
3756  		else {
3757  			ret = o1->len - o2->len;
3758  		}
3759  		break;
3760  	default:
3761  		ret = 0;
3762  		break;
3763  	}
3764  
3765  	return ret;
3766  }
3767  
3768  int
3769  ucl_object_compare_qsort (const ucl_object_t **o1,
3770  		const ucl_object_t **o2)
3771  {
3772  	return ucl_object_compare (*o1, *o2);
3773  }
3774  
3775  void
3776  ucl_object_array_sort (ucl_object_t *ar,
3777  		int (*cmp)(const ucl_object_t **o1, const ucl_object_t **o2))
3778  {
3779  	UCL_ARRAY_GET (vec, ar);
3780  
3781  	if (cmp == NULL || ar == NULL || ar->type != UCL_ARRAY) {
3782  		return;
3783  	}
3784  
3785  	qsort (vec->a, vec->n, sizeof (ucl_object_t *),
3786  			(int (*)(const void *, const void *))cmp);
3787  }
3788  
3789  void ucl_object_sort_keys (ucl_object_t *obj,
3790  		enum ucl_object_keys_sort_flags how)
3791  {
3792  	if (obj != NULL && obj->type == UCL_OBJECT) {
3793  		ucl_hash_sort (obj->value.ov, how);
3794  	}
3795  }
3796  
3797  #define PRIOBITS 4
3798  
3799  unsigned int
3800  ucl_object_get_priority (const ucl_object_t *obj)
3801  {
3802  	if (obj == NULL) {
3803  		return 0;
3804  	}
3805  
3806  	return (obj->flags >> ((sizeof (obj->flags) * NBBY) - PRIOBITS));
3807  }
3808  
3809  void
3810  ucl_object_set_priority (ucl_object_t *obj,
3811  		unsigned int priority)
3812  {
3813  	if (obj != NULL) {
3814  		priority &= (0x1 << PRIOBITS) - 1;
3815  		priority <<= ((sizeof (obj->flags) * NBBY) - PRIOBITS);
3816  		priority |= obj->flags & ((1 << ((sizeof (obj->flags) * NBBY) -
3817  				PRIOBITS)) - 1);
3818  		obj->flags = priority;
3819  	}
3820  }
3821  
3822  bool
3823  ucl_object_string_to_type (const char *input, ucl_type_t *res)
3824  {
3825  	if (strcasecmp (input, "object") == 0) {
3826  		*res = UCL_OBJECT;
3827  	}
3828  	else if (strcasecmp (input, "array") == 0) {
3829  		*res = UCL_ARRAY;
3830  	}
3831  	else if (strcasecmp (input, "integer") == 0) {
3832  		*res = UCL_INT;
3833  	}
3834  	else if (strcasecmp (input, "number") == 0) {
3835  		*res = UCL_FLOAT;
3836  	}
3837  	else if (strcasecmp (input, "string") == 0) {
3838  		*res = UCL_STRING;
3839  	}
3840  	else if (strcasecmp (input, "boolean") == 0) {
3841  		*res = UCL_BOOLEAN;
3842  	}
3843  	else if (strcasecmp (input, "null") == 0) {
3844  		*res = UCL_NULL;
3845  	}
3846  	else if (strcasecmp (input, "userdata") == 0) {
3847  		*res = UCL_USERDATA;
3848  	}
3849  	else {
3850  		return false;
3851  	}
3852  
3853  	return true;
3854  }
3855  
3856  const char *
3857  ucl_object_type_to_string (ucl_type_t type)
3858  {
3859  	const char *res = "unknown";
3860  
3861  	switch (type) {
3862  	case UCL_OBJECT:
3863  		res = "object";
3864  		break;
3865  	case UCL_ARRAY:
3866  		res = "array";
3867  		break;
3868  	case UCL_INT:
3869  		res = "integer";
3870  		break;
3871  	case UCL_FLOAT:
3872  	case UCL_TIME:
3873  		res = "number";
3874  		break;
3875  	case UCL_STRING:
3876  		res = "string";
3877  		break;
3878  	case UCL_BOOLEAN:
3879  		res = "boolean";
3880  		break;
3881  	case UCL_USERDATA:
3882  		res = "userdata";
3883  		break;
3884  	case UCL_NULL:
3885  		res = "null";
3886  		break;
3887  	}
3888  
3889  	return res;
3890  }
3891  
3892  const ucl_object_t *
3893  ucl_parser_get_comments (struct ucl_parser *parser)
3894  {
3895  	if (parser && parser->comments) {
3896  		return parser->comments;
3897  	}
3898  
3899  	return NULL;
3900  }
3901  
3902  const ucl_object_t *
3903  ucl_comments_find (const ucl_object_t *comments,
3904  		const ucl_object_t *srch)
3905  {
3906  	if (comments && srch) {
3907  		return ucl_object_lookup_len (comments, (const char *)&srch,
3908  				sizeof (void *));
3909  	}
3910  
3911  	return NULL;
3912  }
3913  
3914  bool
3915  ucl_comments_move (ucl_object_t *comments,
3916  		const ucl_object_t *from, const ucl_object_t *to)
3917  {
3918  	const ucl_object_t *found;
3919  	ucl_object_t *obj;
3920  
3921  	if (comments && from && to) {
3922  		found = ucl_object_lookup_len (comments,
3923  				(const char *)&from, sizeof (void *));
3924  
3925  		if (found) {
3926  			/* Replace key */
3927  			obj = ucl_object_ref (found);
3928  			ucl_object_delete_keyl (comments, (const char *)&from,
3929  					sizeof (void *));
3930  			ucl_object_insert_key (comments, obj, (const char *)&to,
3931  					sizeof (void *), true);
3932  
3933  			return true;
3934  		}
3935  	}
3936  
3937  	return false;
3938  }
3939  
3940  void
3941  ucl_comments_add (ucl_object_t *comments, const ucl_object_t *obj,
3942  		const char *comment)
3943  {
3944  	if (comments && obj && comment) {
3945  		ucl_object_insert_key (comments, ucl_object_fromstring (comment),
3946  				(const char *)&obj, sizeof (void *), true);
3947  	}
3948  }
3949  
3950  void
3951  ucl_parser_set_include_tracer (struct ucl_parser *parser,
3952  							   ucl_include_trace_func_t func,
3953  							   void *user_data)
3954  {
3955  	parser->include_trace_func = func;
3956  	parser->include_trace_ud = user_data;
3957  }
3958  
3959  const char *
3960  ucl_parser_get_cur_file (struct ucl_parser *parser)
3961  {
3962  	return parser->cur_file;
3963  }