xref: /freebsd/contrib/libucl/lua/lua_ucl.c (revision abda442d92fdbadcf81c79bc9ddba001d133c429)
1 /* Copyright (c) 2014, Vsevolod Stakhov
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *       * Redistributions of source code must retain the above copyright
7  *         notice, this list of conditions and the following disclaimer.
8  *       * Redistributions in binary form must reproduce the above copyright
9  *         notice, this list of conditions and the following disclaimer in the
10  *         documentation and/or other materials provided with the distribution.
11  *
12  * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
13  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15  * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
16  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
19  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22  */
23 
24 /**
25  * @file lua ucl bindings
26  */
27 
28 #include "ucl.h"
29 #include "ucl_internal.h"
30 #include "lua_ucl.h"
31 #include <strings.h>
32 
33 #include "bootstrap.h"
34 
35 /***
36  * @module ucl
37  * This lua module allows to parse objects from strings and to store data into
38  * ucl objects. It uses `libucl` C library to parse and manipulate with ucl objects.
39  * @example
40 local ucl = require("ucl")
41 
42 local parser = ucl.parser()
43 local res,err = parser:parse_string('{key=value}')
44 
45 if not res then
46 	print('parser error: ' .. err)
47 else
48 	local obj = parser:get_object()
49 	local got = ucl.to_format(obj, 'json')
50 endif
51 
52 local table = {
53   str = 'value',
54   num = 100500,
55   null = ucl.null,
56   func = function ()
57     return 'huh'
58   end
59 }
60 
61 print(ucl.to_format(table, 'ucl'))
62 -- Output:
63 --[[
64 num = 100500;
65 str = "value";
66 null = null;
67 func = "huh";
68 --]]
69  */
70 
71 #define PARSER_META "ucl.parser.meta"
72 #define EMITTER_META "ucl.emitter.meta"
73 #define NULL_META "ucl.null.meta"
74 #define OBJECT_META "ucl.object.meta"
75 #define UCL_OBJECT_TYPE_META "ucl.type.object"
76 #define UCL_ARRAY_TYPE_META "ucl.type.array"
77 #define UCL_IMPL_ARRAY_TYPE_META "ucl.type.impl_array"
78 
79 static int ucl_object_lua_push_array (lua_State *L, const ucl_object_t *obj, int flags);
80 static int ucl_object_lua_push_scalar (lua_State *L, const ucl_object_t *obj, int flags);
81 static int ucl_object_push_lua_common (lua_State *L, const ucl_object_t *obj, int flags);
82 static ucl_object_t* ucl_object_lua_fromtable (lua_State *L, int idx, ucl_string_flags_t flags);
83 static ucl_object_t* ucl_object_lua_fromelt (lua_State *L, int idx, ucl_string_flags_t flags);
84 
85 static void *ucl_null;
86 
87 struct _rspamd_lua_text {
88 	const char *start;
89 	unsigned int len;
90 	unsigned int flags;
91 };
92 
93 enum lua_ucl_push_flags {
94 	LUA_UCL_DEFAULT_FLAGS = 0,
95 	LUA_UCL_ALLOW_ARRAY = (1u << 0u),
96 	LUA_UCL_CONVERT_NIL = (1u << 1u),
97 };
98 
99 /**
100  * Push a single element of an object to lua
101  * @param L
102  * @param key
103  * @param obj
104  */
105 static void
106 ucl_object_lua_push_element (lua_State *L, const char *key,
107 		const ucl_object_t *obj, int flags)
108 {
109 	lua_pushstring (L, key);
110 	ucl_object_push_lua_common (L, obj, flags|LUA_UCL_ALLOW_ARRAY);
111 	lua_settable (L, -3);
112 }
113 
114 static void
115 lua_ucl_userdata_dtor (void *ud)
116 {
117 	struct ucl_lua_funcdata *fd = (struct ucl_lua_funcdata *)ud;
118 
119 	luaL_unref (fd->L, LUA_REGISTRYINDEX, fd->idx);
120 	if (fd->ret != NULL) {
121 		free (fd->ret);
122 	}
123 	free (fd);
124 }
125 
126 static const char *
127 lua_ucl_userdata_emitter (void *ud)
128 {
129 	struct ucl_lua_funcdata *fd = (struct ucl_lua_funcdata *)ud;
130 	const char *out = "";
131 
132 	lua_rawgeti (fd->L, LUA_REGISTRYINDEX, fd->idx);
133 
134 	lua_pcall (fd->L, 0, 1, 0);
135 	out = lua_tostring (fd->L, -1);
136 
137 	if (out != NULL) {
138 		/* We need to store temporary string in a more appropriate place */
139 		if (fd->ret) {
140 			free (fd->ret);
141 		}
142 		fd->ret = strdup (out);
143 	}
144 
145 	lua_settop (fd->L, 0);
146 
147 	return fd->ret;
148 }
149 
150 /**
151  * Push a single object to lua
152  * @param L
153  * @param obj
154  * @return
155  */
156 static int
157 ucl_object_lua_push_object (lua_State *L, const ucl_object_t *obj,
158 		int flags)
159 {
160 	const ucl_object_t *cur;
161 	ucl_object_iter_t it = NULL;
162 
163 	if ((flags & LUA_UCL_ALLOW_ARRAY) && obj->next != NULL) {
164 		/* Actually we need to push this as an array */
165 		return ucl_object_lua_push_array (L, obj, flags);
166 	}
167 
168 	lua_createtable (L, 0, obj->len);
169 	it = NULL;
170 
171 	while ((cur = ucl_object_iterate (obj, &it, true)) != NULL) {
172 		ucl_object_lua_push_element (L, ucl_object_key (cur), cur, flags);
173 	}
174 
175 	luaL_getmetatable (L, UCL_OBJECT_TYPE_META);
176 	lua_setmetatable (L, -2);
177 
178 	return 1;
179 }
180 
181 /**
182  * Push an array to lua as table indexed by integers
183  * @param L
184  * @param obj
185  * @return
186  */
187 static int
188 ucl_object_lua_push_array (lua_State *L, const ucl_object_t *obj, int flags)
189 {
190 	const ucl_object_t *cur;
191 	ucl_object_iter_t it;
192 	int i = 1, nelt = 0;
193 
194 	if (obj->type == UCL_ARRAY) {
195 		nelt = obj->len;
196 		it = ucl_object_iterate_new (obj);
197 		lua_createtable (L, nelt, 0);
198 
199 		while ((cur = ucl_object_iterate_safe (it, true))) {
200 			ucl_object_push_lua (L, cur, (flags & ~LUA_UCL_ALLOW_ARRAY));
201 			lua_rawseti (L, -2, i);
202 			i ++;
203 		}
204 
205 		luaL_getmetatable (L, UCL_ARRAY_TYPE_META);
206 		lua_setmetatable (L, -2);
207 
208 		ucl_object_iterate_free (it);
209 	}
210 	else {
211 		/* Optimize allocation by preallocation of table */
212 		LL_FOREACH (obj, cur) {
213 			nelt ++;
214 		}
215 
216 		lua_createtable (L, nelt, 0);
217 
218 		LL_FOREACH (obj, cur) {
219 			ucl_object_push_lua (L, cur, (flags & ~LUA_UCL_ALLOW_ARRAY));
220 			lua_rawseti (L, -2, i);
221 			i ++;
222 		}
223 
224 		luaL_getmetatable (L, UCL_IMPL_ARRAY_TYPE_META);
225 		lua_setmetatable (L, -2);
226 	}
227 
228 	return 1;
229 }
230 
231 /**
232  * Push a simple object to lua depending on its actual type
233  */
234 static int
235 ucl_object_lua_push_scalar (lua_State *L, const ucl_object_t *obj,
236 		int flags)
237 {
238 	struct ucl_lua_funcdata *fd;
239 
240 	if ((flags & LUA_UCL_ALLOW_ARRAY) && obj->next != NULL) {
241 		/* Actually we need to push this as an array */
242 		return ucl_object_lua_push_array (L, obj, flags);
243 	}
244 
245 	switch (obj->type) {
246 	case UCL_BOOLEAN:
247 		lua_pushboolean (L, ucl_obj_toboolean (obj));
248 		break;
249 	case UCL_STRING:
250 		lua_pushlstring (L, ucl_obj_tostring (obj), obj->len);
251 		break;
252 	case UCL_INT:
253 #if LUA_VERSION_NUM >= 501
254 		lua_pushinteger (L, ucl_obj_toint (obj));
255 #else
256 		lua_pushnumber (L, ucl_obj_toint (obj));
257 #endif
258 		break;
259 	case UCL_FLOAT:
260 	case UCL_TIME:
261 		lua_pushnumber (L, ucl_obj_todouble (obj));
262 		break;
263 	case UCL_NULL:
264 		if (flags & LUA_UCL_CONVERT_NIL) {
265 			lua_pushboolean (L, false);
266 		}
267 		else {
268 			lua_getfield (L, LUA_REGISTRYINDEX, "ucl.null");
269 		}
270 		break;
271 	case UCL_USERDATA:
272 		fd = (struct ucl_lua_funcdata *)obj->value.ud;
273 		lua_rawgeti (L, LUA_REGISTRYINDEX, fd->idx);
274 		break;
275 	default:
276 		lua_pushnil (L);
277 		break;
278 	}
279 
280 	return 1;
281 }
282 
283 static int
284 ucl_object_push_lua_common (lua_State *L, const ucl_object_t *obj, int flags)
285 {
286 	switch (obj->type) {
287 	case UCL_OBJECT:
288 		return ucl_object_lua_push_object (L, obj, flags);
289 	case UCL_ARRAY:
290 		return ucl_object_lua_push_array (L, obj, flags);
291 	default:
292 		return ucl_object_lua_push_scalar (L, obj, flags);
293 	}
294 }
295 
296 /***
297  * @function ucl_object_push_lua(L, obj, allow_array)
298  * This is a `C` function to push `UCL` object as lua variable. This function
299  * converts `obj` to lua representation using the following conversions:
300  *
301  * - *scalar* values are directly presented by lua objects
302  * - *userdata* values are converted to lua function objects using `LUA_REGISTRYINDEX`,
303  * this can be used to pass functions from lua to c and vice-versa
304  * - *arrays* are converted to lua tables with numeric indicies suitable for `ipairs` iterations
305  * - *objects* are converted to lua tables with string indicies
306  * @param {lua_State} L lua state pointer
307  * @param {ucl_object_t} obj object to push
308  * @param {bool} allow_array expand implicit arrays (should be true for all but partial arrays)
309  * @return {int} `1` if an object is pushed to lua
310  */
311 int
312 ucl_object_push_lua (lua_State *L, const ucl_object_t *obj, bool allow_array)
313 {
314 	return ucl_object_push_lua_common (L, obj,
315 			allow_array ? LUA_UCL_ALLOW_ARRAY : LUA_UCL_DEFAULT_FLAGS);
316 }
317 
318 int
319 ucl_object_push_lua_filter_nil (lua_State *L, const ucl_object_t *obj, bool allow_array)
320 {
321 	return ucl_object_push_lua_common (L, obj,
322 			allow_array ? (LUA_UCL_ALLOW_ARRAY|LUA_UCL_CONVERT_NIL) :
323 			(LUA_UCL_DEFAULT_FLAGS|LUA_UCL_CONVERT_NIL));
324 }
325 
326 /**
327  * Parse lua table into object top
328  * @param L
329  * @param top
330  * @param idx
331  */
332 static ucl_object_t *
333 ucl_object_lua_fromtable (lua_State *L, int idx, ucl_string_flags_t flags)
334 {
335 	ucl_object_t *obj, *top = NULL, *cur;
336 	size_t keylen;
337 	const char *k;
338 	bool is_array = true, is_implicit = false, found_mt = false;
339 	size_t max = 0, nelts = 0;
340 
341 	if (idx < 0) {
342 		/* For negative indicies we want to invert them */
343 		idx = lua_gettop (L) + idx + 1;
344 	}
345 
346 	/* First, we check from metatable */
347 	if (luaL_getmetafield (L, idx, "class") != 0) {
348 
349 		if (lua_type (L, -1) == LUA_TSTRING) {
350 			const char *classname = lua_tostring (L, -1);
351 
352 			if (strcmp (classname, UCL_OBJECT_TYPE_META) == 0) {
353 				is_array = false;
354 				found_mt = true;
355 			} else if (strcmp (classname, UCL_ARRAY_TYPE_META) == 0) {
356 				is_array = true;
357 				found_mt = true;
358 #if LUA_VERSION_NUM >= 502
359 				max = lua_rawlen (L, idx);
360 #else
361 				max = lua_objlen (L, idx);
362 #endif
363 				nelts = max;
364 			} else if (strcmp (classname, UCL_IMPL_ARRAY_TYPE_META) == 0) {
365 				is_array = true;
366 				is_implicit = true;
367 				found_mt = true;
368 #if LUA_VERSION_NUM >= 502
369 				max = lua_rawlen (L, idx);
370 #else
371 				max = lua_objlen (L, idx);
372 #endif
373 				nelts = max;
374 			}
375 		}
376 
377 		lua_pop (L, 1);
378 	}
379 
380 	if (!found_mt) {
381 		/* Check for array (it is all inefficient) */
382 		lua_pushnil (L);
383 
384 		while (lua_next (L, idx) != 0) {
385 			lua_pushvalue (L, -2);
386 
387 			if (lua_type (L, -1) == LUA_TNUMBER) {
388 				double num = lua_tonumber (L, -1);
389 				if (num == (int) num) {
390 					if (num > max) {
391 						max = num;
392 					}
393 				}
394 				else {
395 					/* Keys are not integer */
396 					is_array = false;
397 				}
398 			}
399 			else {
400 				/* Keys are not numeric */
401 				is_array = false;
402 			}
403 
404 			lua_pop (L, 2);
405 			nelts ++;
406 		}
407 	}
408 
409 	/* Table iterate */
410 	if (is_array) {
411 
412 		if (!is_implicit) {
413 			top = ucl_object_typed_new (UCL_ARRAY);
414 			ucl_object_reserve (top, nelts);
415 		}
416 		else {
417 			top = NULL;
418 		}
419 
420 		for (size_t i = 1; i <= max; i ++) {
421 			lua_pushinteger (L, i);
422 			lua_gettable (L, idx);
423 
424 			obj = ucl_object_lua_fromelt (L, lua_gettop (L), flags);
425 
426 			if (obj != NULL) {
427 				if (is_implicit) {
428 					DL_APPEND (top, obj);
429 				}
430 				else {
431 					ucl_array_append (top, obj);
432 				}
433 			}
434 			lua_pop (L, 1);
435 		}
436 	}
437 	else {
438 		lua_pushnil (L);
439 		top = ucl_object_typed_new (UCL_OBJECT);
440 		ucl_object_reserve (top, nelts);
441 
442 		while (lua_next (L, idx) != 0) {
443 			/* copy key to avoid modifications */
444 			lua_pushvalue (L, -2);
445 			k = lua_tolstring (L, -1, &keylen);
446 			obj = ucl_object_lua_fromelt (L, lua_gettop (L) - 1, flags);
447 
448 			if (obj != NULL) {
449 				ucl_object_insert_key (top, obj, k, keylen, true);
450 
451 				DL_FOREACH (obj, cur) {
452 					if (cur->keylen == 0) {
453 						cur->keylen = obj->keylen;
454 						cur->key = obj->key;
455 					}
456 				}
457 			}
458 			lua_pop (L, 2);
459 		}
460 	}
461 
462 	return top;
463 }
464 
465 /**
466  * Get a single element from lua to object obj
467  * @param L
468  * @param obj
469  * @param idx
470  */
471 static ucl_object_t *
472 ucl_object_lua_fromelt (lua_State *L, int idx, ucl_string_flags_t flags)
473 {
474 	int type;
475 	double num;
476 	ucl_object_t *obj = NULL;
477 	struct ucl_lua_funcdata *fd;
478 	const char *str;
479 	size_t sz;
480 
481 	type = lua_type (L, idx);
482 
483 	switch (type) {
484 	case LUA_TSTRING:
485 		str = lua_tolstring (L, idx, &sz);
486 
487 		if (str) {
488 			/*
489 			 * ucl_object_fromstring_common has a `logic` to use strlen if sz is zero
490 			 * which is totally broken...
491 			 */
492 			if (sz > 0) {
493 				obj = ucl_object_fromstring_common(str, sz, flags);
494 			}
495 			else {
496 				obj = ucl_object_fromstring_common("", sz, flags);
497 			}
498 		}
499 		else {
500 			obj = ucl_object_typed_new (UCL_NULL);
501 		}
502 		break;
503 	case LUA_TNUMBER:
504 		num = lua_tonumber (L, idx);
505 		if (num == (int64_t)num) {
506 			obj = ucl_object_fromint (num);
507 		}
508 		else {
509 			obj = ucl_object_fromdouble (num);
510 		}
511 		break;
512 	case LUA_TBOOLEAN:
513 		obj = ucl_object_frombool (lua_toboolean (L, idx));
514 		break;
515 	case LUA_TUSERDATA:
516 		if (lua_topointer (L, idx) == ucl_null) {
517 			obj = ucl_object_typed_new (UCL_NULL);
518 		}
519 		else {
520 			/* Assume it is a text like object */
521 			struct _rspamd_lua_text *t = lua_touserdata (L, idx);
522 
523 			if (t) {
524 				if (t->len >0) {
525 					obj = ucl_object_fromstring_common(t->start, t->len, 0);
526 				}
527 				else {
528 					obj = ucl_object_fromstring_common("", 0, 0);
529 				}
530 
531 				/* Binary text */
532 				if (t->flags & (1u << 5u)) {
533 					obj->flags |= UCL_OBJECT_BINARY;
534 				}
535 			}
536 		}
537 		break;
538 	case LUA_TTABLE:
539 	case LUA_TFUNCTION:
540 	case LUA_TTHREAD:
541 		if (luaL_getmetafield (L, idx, "__gen_ucl")) {
542 			if (lua_isfunction (L, -1)) {
543 				lua_settop (L, 3); /* gen, obj, func */
544 				lua_insert (L, 1); /* func, gen, obj */
545 				lua_insert (L, 2); /* func, obj, gen */
546 				lua_call(L, 2, 1);
547 				obj = ucl_object_lua_fromelt (L, 1, flags);
548 			}
549 			lua_pop (L, 2);
550 		}
551 		else {
552 			if (type == LUA_TTABLE) {
553 				obj = ucl_object_lua_fromtable (L, idx, flags);
554 			}
555 			else if (type == LUA_TFUNCTION) {
556 				fd = malloc (sizeof (*fd));
557 				if (fd != NULL) {
558 					lua_pushvalue (L, idx);
559 					fd->L = L;
560 					fd->ret = NULL;
561 					fd->idx = luaL_ref (L, LUA_REGISTRYINDEX);
562 
563 					obj = ucl_object_new_userdata (lua_ucl_userdata_dtor,
564 							lua_ucl_userdata_emitter, (void *)fd);
565 				}
566 			}
567 		}
568 		break;
569 	}
570 
571 	return obj;
572 }
573 
574 /**
575  * @function ucl_object_lua_import(L, idx)
576  * Extracts ucl object from lua variable at `idx` position,
577  * @see ucl_object_push_lua for conversion definitions
578  * @param {lua_state} L lua state machine pointer
579  * @param {int} idx index where the source variable is placed
580  * @return {ucl_object_t} new ucl object extracted from lua variable. Reference count of this object is 1,
581  * this object thus needs to be unref'ed after usage.
582  */
583 ucl_object_t *
584 ucl_object_lua_import (lua_State *L, int idx)
585 {
586 	ucl_object_t *obj;
587 	int t;
588 
589 	t = lua_type (L, idx);
590 	switch (t) {
591 	case LUA_TTABLE:
592 		obj = ucl_object_lua_fromtable (L, idx, UCL_STRING_RAW);
593 		break;
594 	default:
595 		obj = ucl_object_lua_fromelt (L, idx, UCL_STRING_RAW);
596 		break;
597 	}
598 
599 	return obj;
600 }
601 
602 /**
603  * @function ucl_object_lua_import_escape(L, idx)
604  * Extracts ucl object from lua variable at `idx` position escaping JSON strings
605  * @see ucl_object_push_lua for conversion definitions
606  * @param {lua_state} L lua state machine pointer
607  * @param {int} idx index where the source variable is placed
608  * @return {ucl_object_t} new ucl object extracted from lua variable. Reference count of this object is 1,
609  * this object thus needs to be unref'ed after usage.
610  */
611 ucl_object_t *
612 ucl_object_lua_import_escape (lua_State *L, int idx)
613 {
614 	ucl_object_t *obj;
615 	int t;
616 
617 	t = lua_type (L, idx);
618 	switch (t) {
619 	case LUA_TTABLE:
620 		obj = ucl_object_lua_fromtable (L, idx, UCL_STRING_ESCAPE);
621 		break;
622 	default:
623 		obj = ucl_object_lua_fromelt (L, idx, UCL_STRING_ESCAPE);
624 		break;
625 	}
626 
627 	return obj;
628 }
629 
630 static int
631 lua_ucl_to_string (lua_State *L, const ucl_object_t *obj, enum ucl_emitter type)
632 {
633 	unsigned char *result;
634 	size_t outlen;
635 
636 	result = ucl_object_emit_len (obj, type, &outlen);
637 
638 	if (result != NULL) {
639 		lua_pushlstring (L, (const char *)result, outlen);
640 		free (result);
641 	}
642 	else {
643 		lua_pushnil (L);
644 	}
645 
646 	return 1;
647 }
648 
649 static int
650 lua_ucl_parser_init (lua_State *L)
651 {
652 	struct ucl_parser *parser, **pparser;
653 	/*
654 	 * We disable file variables and macros by default, as
655 	 * the most use cases are parsing of JSON and not of the real
656 	 * files. Macros in the parser are very dangerous and should be used
657 	 * for trusted data only.
658 	 */
659 	int flags = UCL_PARSER_NO_FILEVARS|UCL_PARSER_DISABLE_MACRO;
660 
661 	if (lua_gettop (L) >= 1) {
662 		flags = lua_tonumber (L, 1);
663 	}
664 
665 	parser = ucl_parser_new (flags);
666 	if (parser == NULL) {
667 		lua_pushnil (L);
668 	}
669 
670 	pparser = lua_newuserdata (L, sizeof (parser));
671 	*pparser = parser;
672 	luaL_getmetatable (L, PARSER_META);
673 	lua_setmetatable (L, -2);
674 
675 	return 1;
676 }
677 
678 static struct ucl_parser *
679 lua_ucl_parser_get (lua_State *L, int index)
680 {
681 	return *((struct ucl_parser **) luaL_checkudata(L, index, PARSER_META));
682 }
683 
684 static ucl_object_t *
685 lua_ucl_object_get (lua_State *L, int index)
686 {
687 	return *((ucl_object_t **) luaL_checkudata(L, index, OBJECT_META));
688 }
689 
690 static void
691 lua_ucl_push_opaque (lua_State *L, ucl_object_t *obj)
692 {
693 	ucl_object_t **pobj;
694 
695 	pobj = lua_newuserdata (L, sizeof (*pobj));
696 	*pobj = obj;
697 	luaL_getmetatable (L, OBJECT_META);
698 	lua_setmetatable (L, -2);
699 }
700 
701 static inline enum ucl_parse_type
702 lua_ucl_str_to_parse_type (const char *str)
703 {
704 	enum ucl_parse_type type = UCL_PARSE_UCL;
705 
706 	if (str != NULL) {
707 		if (strcasecmp (str, "msgpack") == 0) {
708 			type = UCL_PARSE_MSGPACK;
709 		}
710 		else if (strcasecmp (str, "sexp") == 0 ||
711 				strcasecmp (str, "csexp") == 0) {
712 			type = UCL_PARSE_CSEXP;
713 		}
714 		else if (strcasecmp (str, "auto") == 0) {
715 			type = UCL_PARSE_AUTO;
716 		}
717 	}
718 
719 	return type;
720 }
721 
722 /***
723  * @method parser:parse_file(name)
724  * Parse UCL object from file.
725  * @param {string} name filename to parse
726  * @return {bool[, string]} if res is `true` then file has been parsed successfully, otherwise an error string is also returned
727 @example
728 local parser = ucl.parser()
729 local res,err = parser:parse_file('/some/file.conf')
730 
731 if not res then
732 	print('parser error: ' .. err)
733 else
734 	-- Do something with object
735 end
736  */
737 static int
738 lua_ucl_parser_parse_file (lua_State *L)
739 {
740 	struct ucl_parser *parser;
741 	const char *file;
742 	int ret = 2;
743 
744 	parser = lua_ucl_parser_get (L, 1);
745 	file = luaL_checkstring (L, 2);
746 
747 	if (parser != NULL && file != NULL) {
748 		if (ucl_parser_add_file (parser, file)) {
749 			lua_pushboolean (L, true);
750 			ret = 1;
751 		}
752 		else {
753 			lua_pushboolean (L, false);
754 			lua_pushstring (L, ucl_parser_get_error (parser));
755 		}
756 	}
757 	else {
758 		lua_pushboolean (L, false);
759 		lua_pushstring (L, "invalid arguments");
760 	}
761 
762 	return ret;
763 }
764 
765 /***
766  * @method parser:register_variable(name, value)
767  * Register parser variable
768  * @param {string} name name of variable
769  * @param {string} value value of variable
770  * @return {bool} success
771 @example
772 local parser = ucl.parser()
773 local res = parser:register_variable('CONFDIR', '/etc/foo')
774  */
775 static int
776 lua_ucl_parser_register_variable (lua_State *L)
777 {
778 	struct ucl_parser *parser;
779 	const char *name, *value;
780 	int ret = 2;
781 
782 	parser = lua_ucl_parser_get (L, 1);
783 	name = luaL_checkstring (L, 2);
784 	value = luaL_checkstring (L, 3);
785 
786 	if (parser != NULL && name != NULL && value != NULL) {
787 		ucl_parser_register_variable (parser, name, value);
788 		lua_pushboolean (L, true);
789 		ret = 1;
790 	}
791 	else {
792 		return luaL_error (L, "invalid arguments");
793 	}
794 
795 	return ret;
796 }
797 
798 /***
799  * @method parser:register_variables(vars)
800  * Register parser variables
801  * @param {table} vars names/values of variables
802  * @return {bool} success
803 @example
804 local parser = ucl.parser()
805 local res = parser:register_variables({CONFDIR = '/etc/foo', VARDIR = '/var'})
806  */
807 static int
808 lua_ucl_parser_register_variables (lua_State *L)
809 {
810 	struct ucl_parser *parser;
811 	const char *name, *value;
812 	int ret = 2;
813 
814 	parser = lua_ucl_parser_get (L, 1);
815 
816 	if (parser != NULL && lua_type (L, 2) == LUA_TTABLE) {
817 		for (lua_pushnil (L); lua_next (L, 2); lua_pop (L, 1)) {
818 			lua_pushvalue (L, -2);
819 			name = luaL_checkstring (L, -1);
820 			value = luaL_checkstring (L, -2);
821 			ucl_parser_register_variable (parser, name, value);
822 			lua_pop (L, 1);
823 		}
824 
825 		lua_pushboolean (L, true);
826 		ret = 1;
827 	}
828 	else {
829 		return luaL_error (L, "invalid arguments");
830 	}
831 
832 	return ret;
833 }
834 
835 /***
836  * @method parser:parse_string(input)
837  * Parse UCL object from file.
838  * @param {string} input string to parse
839  * @return {bool[, string]} if res is `true` then file has been parsed successfully, otherwise an error string is also returned
840  */
841 static int
842 lua_ucl_parser_parse_string (lua_State *L)
843 {
844 	struct ucl_parser *parser;
845 	const char *string;
846 	size_t llen;
847 	enum ucl_parse_type type = UCL_PARSE_UCL;
848 	int ret = 2;
849 
850 	parser = lua_ucl_parser_get (L, 1);
851 	string = luaL_checklstring (L, 2, &llen);
852 
853 	if (lua_type (L, 3) == LUA_TSTRING) {
854 		type = lua_ucl_str_to_parse_type (lua_tostring (L, 3));
855 	}
856 
857 	if (parser != NULL && string != NULL) {
858 		if (ucl_parser_add_chunk_full (parser, (const unsigned char *)string,
859 				llen, 0, UCL_DUPLICATE_APPEND, type)) {
860 			lua_pushboolean (L, true);
861 			ret = 1;
862 		}
863 		else {
864 			lua_pushboolean (L, false);
865 			lua_pushstring (L, ucl_parser_get_error (parser));
866 		}
867 	}
868 	else {
869 		lua_pushboolean (L, false);
870 		lua_pushstring (L, "invalid arguments");
871 	}
872 
873 	return ret;
874 }
875 
876 /***
877  * @method parser:parse_text(input)
878  * Parse UCL object from text object (Rspamd specific).
879  * @param {rspamd_text} input text to parse
880  * @return {bool[, string]} if res is `true` then file has been parsed successfully, otherwise an error string is also returned
881  */
882 static int
883 lua_ucl_parser_parse_text (lua_State *L)
884 {
885 	struct ucl_parser *parser;
886 	struct _rspamd_lua_text *t;
887 	enum ucl_parse_type type = UCL_PARSE_UCL;
888 	int ret = 2;
889 
890 	parser = lua_ucl_parser_get (L, 1);
891 
892 	if (lua_type (L, 2) == LUA_TUSERDATA) {
893 		t = lua_touserdata (L, 2);
894 	}
895 	else if (lua_type (L, 2) == LUA_TSTRING) {
896 		const char *s;
897 		size_t len;
898 		static struct _rspamd_lua_text st_t;
899 
900 		s = lua_tolstring (L, 2, &len);
901 		st_t.start = s;
902 		st_t.len = len;
903 
904 		t = &st_t;
905 	}
906 	else {
907 		return luaL_error(L, "invalid argument as input, expected userdata or a string");
908 	}
909 
910 	if (lua_type (L, 3) == LUA_TSTRING) {
911 		type = lua_ucl_str_to_parse_type (lua_tostring (L, 3));
912 	}
913 
914 	if (parser != NULL && t != NULL) {
915 		if (ucl_parser_add_chunk_full (parser, (const unsigned char *)t->start,
916 				t->len, 0, UCL_DUPLICATE_APPEND, type)) {
917 			lua_pushboolean (L, true);
918 			ret = 1;
919 		}
920 		else {
921 			lua_pushboolean (L, false);
922 			lua_pushstring (L, ucl_parser_get_error (parser));
923 		}
924 	}
925 	else {
926 		lua_pushboolean (L, false);
927 		lua_pushstring (L, "invalid arguments");
928 	}
929 
930 	return ret;
931 }
932 
933 /***
934  * @method parser:get_object()
935  * Get top object from parser and export it to lua representation.
936  * @return {variant or nil} ucl object as lua native variable
937  */
938 static int
939 lua_ucl_parser_get_object (lua_State *L)
940 {
941 	struct ucl_parser *parser;
942 	ucl_object_t *obj;
943 	int ret = 1;
944 
945 	parser = lua_ucl_parser_get (L, 1);
946 	obj = ucl_parser_get_object (parser);
947 
948 	if (obj != NULL) {
949 		ret = ucl_object_push_lua (L, obj, false);
950 		/* no need to keep reference */
951 		ucl_object_unref (obj);
952 	}
953 	else {
954 		lua_pushnil (L);
955 	}
956 
957 	return ret;
958 }
959 
960 /***
961  * @method parser:get_object_wrapped()
962  * Get top object from parser and export it to userdata object without
963  * unwrapping to lua.
964  * @return {ucl.object or nil} ucl object wrapped variable
965  */
966 static int
967 lua_ucl_parser_get_object_wrapped (lua_State *L)
968 {
969 	struct ucl_parser *parser;
970 	ucl_object_t *obj;
971 	int ret = 1;
972 
973 	parser = lua_ucl_parser_get (L, 1);
974 	obj = ucl_parser_get_object (parser);
975 
976 	if (obj != NULL) {
977 		lua_ucl_push_opaque (L, obj);
978 	}
979 	else {
980 		lua_pushnil (L);
981 	}
982 
983 	return ret;
984 }
985 
986 /***
987  * @method parser:validate(schema)
988  * Validates the top object in the parser against schema. Schema might be
989  * another object or a string that represents file to load schema from.
990  *
991  * @param {string/table} schema input schema
992  * @return {result,err} two values: boolean result and the corresponding error
993  *
994  */
995 static int
996 lua_ucl_parser_validate (lua_State *L)
997 {
998 	struct ucl_parser *parser, *schema_parser;
999 	ucl_object_t *schema;
1000 	const char *schema_file;
1001 	struct ucl_schema_error err;
1002 
1003 	parser = lua_ucl_parser_get (L, 1);
1004 
1005 	if (parser && parser->top_obj) {
1006 		if (lua_type (L, 2) == LUA_TTABLE) {
1007 			schema = ucl_object_lua_import (L, 2);
1008 
1009 			if (schema == NULL) {
1010 				lua_pushboolean (L, false);
1011 				lua_pushstring (L, "cannot load schema from lua table");
1012 
1013 				return 2;
1014 			}
1015 		}
1016 		else if (lua_type (L, 2) == LUA_TSTRING) {
1017 			schema_parser = ucl_parser_new (0);
1018 			schema_file = luaL_checkstring (L, 2);
1019 
1020 			if (!ucl_parser_add_file (schema_parser, schema_file)) {
1021 				lua_pushboolean (L, false);
1022 				lua_pushfstring (L, "cannot parse schema file \"%s\": "
1023 						"%s", schema_file, ucl_parser_get_error (parser));
1024 				ucl_parser_free (schema_parser);
1025 
1026 				return 2;
1027 			}
1028 
1029 			schema = ucl_parser_get_object (schema_parser);
1030 			ucl_parser_free (schema_parser);
1031 		}
1032 		else {
1033 			lua_pushboolean (L, false);
1034 			lua_pushstring (L, "invalid schema argument");
1035 
1036 			return 2;
1037 		}
1038 
1039 		if (!ucl_object_validate (schema, parser->top_obj, &err)) {
1040 			lua_pushboolean (L, false);
1041 			lua_pushfstring (L, "validation error: "
1042 					"%s", err.msg);
1043 		}
1044 		else {
1045 			lua_pushboolean (L, true);
1046 			lua_pushnil (L);
1047 		}
1048 
1049 		ucl_object_unref (schema);
1050 	}
1051 	else {
1052 		lua_pushboolean (L, false);
1053 		lua_pushstring (L, "invalid parser or empty top object");
1054 	}
1055 
1056 	return 2;
1057 }
1058 
1059 static int
1060 lua_ucl_parser_gc (lua_State *L)
1061 {
1062 	struct ucl_parser *parser;
1063 
1064 	parser = lua_ucl_parser_get (L, 1);
1065 	ucl_parser_free (parser);
1066 
1067 	return 0;
1068 }
1069 
1070 /***
1071  * @method object:unwrap()
1072  * Unwraps opaque ucl object to the native lua object (performing copying)
1073  * @return {variant} any lua object
1074  */
1075 static int
1076 lua_ucl_object_unwrap (lua_State *L)
1077 {
1078 	ucl_object_t *obj;
1079 
1080 	obj = lua_ucl_object_get (L, 1);
1081 
1082 	if (obj) {
1083 		ucl_object_push_lua (L, obj, true);
1084 	}
1085 	else {
1086 		lua_pushnil (L);
1087 	}
1088 
1089 	return 1;
1090 }
1091 
1092 static inline enum ucl_emitter
1093 lua_ucl_str_to_emit_type (const char *strtype)
1094 {
1095 	enum ucl_emitter format = UCL_EMIT_JSON_COMPACT;
1096 
1097 	if (strcasecmp (strtype, "json") == 0) {
1098 		format = UCL_EMIT_JSON;
1099 	}
1100 	else if (strcasecmp (strtype, "json-compact") == 0) {
1101 		format = UCL_EMIT_JSON_COMPACT;
1102 	}
1103 	else if (strcasecmp (strtype, "yaml") == 0) {
1104 		format = UCL_EMIT_YAML;
1105 	}
1106 	else if (strcasecmp (strtype, "config") == 0 ||
1107 			strcasecmp (strtype, "ucl") == 0) {
1108 		format = UCL_EMIT_CONFIG;
1109 	}
1110 
1111 	return format;
1112 }
1113 
1114 /***
1115  * @method object:tostring(type)
1116  * Unwraps opaque ucl object to string (json by default). Optionally you can
1117  * specify output format:
1118  *
1119  * - `json` - fine printed json
1120  * - `json-compact` - compacted json
1121  * - `config` - fine printed configuration
1122  * - `ucl` - same as `config`
1123  * - `yaml` - embedded yaml
1124  * @param {string} type optional
1125  * @return {string} string representation of the opaque ucl object
1126  */
1127 static int
1128 lua_ucl_object_tostring (lua_State *L)
1129 {
1130 	ucl_object_t *obj;
1131 	enum ucl_emitter format = UCL_EMIT_JSON_COMPACT;
1132 
1133 	obj = lua_ucl_object_get (L, 1);
1134 
1135 	if (obj) {
1136 		if (lua_gettop (L) > 1) {
1137 			if (lua_type (L, 2) == LUA_TSTRING) {
1138 				const char *strtype = lua_tostring (L, 2);
1139 
1140 				format = lua_ucl_str_to_emit_type (strtype);
1141 			}
1142 		}
1143 
1144 		return lua_ucl_to_string (L, obj, format);
1145 	}
1146 	else {
1147 		lua_pushnil (L);
1148 	}
1149 
1150 	return 1;
1151 }
1152 
1153 /***
1154  * @method object:validate(schema[, path[, ext_refs]])
1155  * Validates the given ucl object using schema object represented as another
1156  * opaque ucl object. You can also specify path in the form `#/path/def` to
1157  * specify the specific schema element to perform validation.
1158  *
1159  * @param {ucl.object} schema schema object
1160  * @param {string} path optional path for validation procedure
1161  * @return {result,err} two values: boolean result and the corresponding
1162  * error, if `ext_refs` are also specified, then they are returned as opaque
1163  * ucl object as {result,err,ext_refs}
1164  */
1165 static int
1166 lua_ucl_object_validate (lua_State *L)
1167 {
1168 	ucl_object_t *obj, *schema, *ext_refs = NULL;
1169 	const ucl_object_t *schema_elt;
1170 	bool res = false;
1171 	struct ucl_schema_error err;
1172 	const char *path = NULL;
1173 
1174 	obj = lua_ucl_object_get (L, 1);
1175 	schema = lua_ucl_object_get (L, 2);
1176 
1177 	if (schema && obj && ucl_object_type (schema) == UCL_OBJECT) {
1178 		if (lua_gettop (L) > 2) {
1179 			if (lua_type (L, 3) == LUA_TSTRING) {
1180 				path = lua_tostring (L, 3);
1181 				if (path[0] == '#') {
1182 					path++;
1183 				}
1184 			}
1185 			else if (lua_type (L, 3) == LUA_TUSERDATA || lua_type (L, 3) ==
1186 						LUA_TTABLE) {
1187 				/* External refs */
1188 				ext_refs = lua_ucl_object_get (L, 3);
1189 			}
1190 
1191 			if (lua_gettop (L) > 3) {
1192 				if (lua_type (L, 4) == LUA_TUSERDATA || lua_type (L, 4) ==
1193 						LUA_TTABLE) {
1194 					/* External refs */
1195 					ext_refs = lua_ucl_object_get (L, 4);
1196 				}
1197 			}
1198 		}
1199 
1200 		if (path) {
1201 			schema_elt = ucl_object_lookup_path_char (schema, path, '/');
1202 		}
1203 		else {
1204 			/* Use the top object */
1205 			schema_elt = schema;
1206 		}
1207 
1208 		if (schema_elt) {
1209 			res = ucl_object_validate_root_ext (schema_elt, obj, schema,
1210 					ext_refs, &err);
1211 
1212 			if (res) {
1213 				lua_pushboolean (L, res);
1214 				lua_pushnil (L);
1215 
1216 				if (ext_refs) {
1217 					lua_ucl_push_opaque (L, ext_refs);
1218 				}
1219 			}
1220 			else {
1221 				lua_pushboolean (L, res);
1222 				lua_pushfstring (L, "validation error: %s", err.msg);
1223 
1224 				if (ext_refs) {
1225 					lua_ucl_push_opaque (L, ext_refs);
1226 				}
1227 			}
1228 		}
1229 		else {
1230 			lua_pushboolean (L, res);
1231 
1232 			lua_pushfstring (L, "cannot find the requested path: %s", path);
1233 
1234 			if (ext_refs) {
1235 				lua_ucl_push_opaque (L, ext_refs);
1236 			}
1237 		}
1238 	}
1239 	else {
1240 		lua_pushboolean (L, res);
1241 		lua_pushstring (L, "invalid object or schema");
1242 	}
1243 
1244 	if (ext_refs) {
1245 		return 3;
1246 	}
1247 
1248 	return 2;
1249 }
1250 
1251 static int
1252 lua_ucl_object_gc (lua_State *L)
1253 {
1254 	ucl_object_t *obj;
1255 
1256 	obj = lua_ucl_object_get (L, 1);
1257 
1258 	ucl_object_unref (obj);
1259 
1260 	return 0;
1261 }
1262 
1263 static void
1264 lua_ucl_parser_mt (lua_State *L)
1265 {
1266 	luaL_newmetatable (L, PARSER_META);
1267 
1268 	lua_pushvalue(L, -1);
1269 	lua_setfield(L, -2, "__index");
1270 
1271 	lua_pushcfunction (L, lua_ucl_parser_gc);
1272 	lua_setfield (L, -2, "__gc");
1273 
1274 	lua_pushcfunction (L, lua_ucl_parser_parse_file);
1275 	lua_setfield (L, -2, "parse_file");
1276 
1277 	lua_pushcfunction (L, lua_ucl_parser_parse_string);
1278 	lua_setfield (L, -2, "parse_string");
1279 
1280 	lua_pushcfunction (L, lua_ucl_parser_parse_text);
1281 	lua_setfield (L, -2, "parse_text");
1282 
1283 	lua_pushcfunction (L, lua_ucl_parser_register_variable);
1284 	lua_setfield (L, -2, "register_variable");
1285 
1286 	lua_pushcfunction (L, lua_ucl_parser_register_variables);
1287 	lua_setfield (L, -2, "register_variables");
1288 
1289 	lua_pushcfunction (L, lua_ucl_parser_get_object);
1290 	lua_setfield (L, -2, "get_object");
1291 
1292 	lua_pushcfunction (L, lua_ucl_parser_get_object_wrapped);
1293 	lua_setfield (L, -2, "get_object_wrapped");
1294 
1295 	lua_pushcfunction (L, lua_ucl_parser_validate);
1296 	lua_setfield (L, -2, "validate");
1297 
1298 	lua_pop (L, 1);
1299 }
1300 
1301 static void
1302 lua_ucl_object_mt (lua_State *L)
1303 {
1304 	luaL_newmetatable (L, OBJECT_META);
1305 
1306 	lua_pushvalue(L, -1);
1307 	lua_setfield(L, -2, "__index");
1308 
1309 	lua_pushcfunction (L, lua_ucl_object_gc);
1310 	lua_setfield (L, -2, "__gc");
1311 
1312 	lua_pushcfunction (L, lua_ucl_object_tostring);
1313 	lua_setfield (L, -2, "__tostring");
1314 
1315 	lua_pushcfunction (L, lua_ucl_object_tostring);
1316 	lua_setfield (L, -2, "tostring");
1317 
1318 	lua_pushcfunction (L, lua_ucl_object_unwrap);
1319 	lua_setfield (L, -2, "unwrap");
1320 
1321 	lua_pushcfunction (L, lua_ucl_object_unwrap);
1322 	lua_setfield (L, -2, "tolua");
1323 
1324 	lua_pushcfunction (L, lua_ucl_object_validate);
1325 	lua_setfield (L, -2, "validate");
1326 
1327 	lua_pushstring (L, OBJECT_META);
1328 	lua_setfield (L, -2, "class");
1329 
1330 	lua_pop (L, 1);
1331 }
1332 
1333 static void
1334 lua_ucl_types_mt (lua_State *L)
1335 {
1336 	luaL_newmetatable (L, UCL_OBJECT_TYPE_META);
1337 
1338 	lua_pushcfunction (L, lua_ucl_object_tostring);
1339 	lua_setfield (L, -2, "__tostring");
1340 
1341 	lua_pushcfunction (L, lua_ucl_object_tostring);
1342 	lua_setfield (L, -2, "tostring");
1343 
1344 	lua_pushstring (L, UCL_OBJECT_TYPE_META);
1345 	lua_setfield (L, -2, "class");
1346 
1347 	lua_pop (L, 1);
1348 
1349 	luaL_newmetatable (L, UCL_ARRAY_TYPE_META);
1350 
1351 	lua_pushcfunction (L, lua_ucl_object_tostring);
1352 	lua_setfield (L, -2, "__tostring");
1353 
1354 	lua_pushcfunction (L, lua_ucl_object_tostring);
1355 	lua_setfield (L, -2, "tostring");
1356 
1357 	lua_pushstring (L, UCL_ARRAY_TYPE_META);
1358 	lua_setfield (L, -2, "class");
1359 
1360 	lua_pop (L, 1);
1361 
1362 	luaL_newmetatable (L, UCL_IMPL_ARRAY_TYPE_META);
1363 
1364 	lua_pushcfunction (L, lua_ucl_object_tostring);
1365 	lua_setfield (L, -2, "__tostring");
1366 
1367 	lua_pushcfunction (L, lua_ucl_object_tostring);
1368 	lua_setfield (L, -2, "tostring");
1369 
1370 	lua_pushstring (L, UCL_IMPL_ARRAY_TYPE_META);
1371 	lua_setfield (L, -2, "class");
1372 
1373 	lua_pop (L, 1);
1374 }
1375 
1376 static int
1377 lua_ucl_to_json (lua_State *L)
1378 {
1379 	ucl_object_t *obj;
1380 	int format = UCL_EMIT_JSON;
1381 
1382 	if (lua_gettop (L) > 1) {
1383 		if (lua_toboolean (L, 2)) {
1384 			format = UCL_EMIT_JSON_COMPACT;
1385 		}
1386 	}
1387 
1388 	obj = ucl_object_lua_import (L, 1);
1389 	if (obj != NULL) {
1390 		lua_ucl_to_string (L, obj, format);
1391 		ucl_object_unref (obj);
1392 	}
1393 	else {
1394 		lua_pushnil (L);
1395 	}
1396 
1397 	return 1;
1398 }
1399 
1400 static int
1401 lua_ucl_to_config (lua_State *L)
1402 {
1403 	ucl_object_t *obj;
1404 
1405 	obj = ucl_object_lua_import (L, 1);
1406 	if (obj != NULL) {
1407 		lua_ucl_to_string (L, obj, UCL_EMIT_CONFIG);
1408 		ucl_object_unref (obj);
1409 	}
1410 	else {
1411 		lua_pushnil (L);
1412 	}
1413 
1414 	return 1;
1415 }
1416 
1417 /***
1418  * @function ucl.to_format(var, format)
1419  * Converts lua variable `var` to the specified `format`. Formats supported are:
1420  *
1421  * - `json` - fine printed json
1422  * - `json-compact` - compacted json
1423  * - `config` - fine printed configuration
1424  * - `ucl` - same as `config`
1425  * - `yaml` - embedded yaml
1426  *
1427  * If `var` contains function, they are called during output formatting and if
1428  * they return string value, then this value is used for output.
1429  * @param {variant} var any sort of lua variable (if userdata then metafield `__to_ucl` is searched for output)
1430  * @param {string} format any available format
1431  * @return {string} string representation of `var` in the specific `format`.
1432  * @example
1433 local table = {
1434   str = 'value',
1435   num = 100500,
1436   null = ucl.null,
1437   func = function ()
1438     return 'huh'
1439   end
1440 }
1441 
1442 print(ucl.to_format(table, 'ucl'))
1443 -- Output:
1444 --[[
1445 num = 100500;
1446 str = "value";
1447 null = null;
1448 func = "huh";
1449 --]]
1450  */
1451 static int
1452 lua_ucl_to_format (lua_State *L)
1453 {
1454 	ucl_object_t *obj;
1455 	int format = UCL_EMIT_JSON;
1456 	bool sort = false;
1457 
1458 	if (lua_gettop (L) > 1) {
1459 		if (lua_type (L, 2) == LUA_TNUMBER) {
1460 			format = lua_tonumber (L, 2);
1461 			if (format < 0 || format >= UCL_EMIT_YAML) {
1462 				lua_pushnil (L);
1463 				return 1;
1464 			}
1465 		}
1466 		else if (lua_type (L, 2) == LUA_TSTRING) {
1467 			const char *strtype = lua_tostring (L, 2);
1468 
1469 			if (strcasecmp (strtype, "json") == 0) {
1470 				format = UCL_EMIT_JSON;
1471 			}
1472 			else if (strcasecmp (strtype, "json-compact") == 0) {
1473 				format = UCL_EMIT_JSON_COMPACT;
1474 			}
1475 			else if (strcasecmp (strtype, "yaml") == 0) {
1476 				format = UCL_EMIT_YAML;
1477 			}
1478 			else if (strcasecmp (strtype, "config") == 0 ||
1479 					 strcasecmp (strtype, "ucl") == 0) {
1480 				format = UCL_EMIT_CONFIG;
1481 			}
1482 			else if (strcasecmp (strtype, "msgpack") == 0 ||
1483 					 strcasecmp (strtype, "messagepack") == 0) {
1484 				format = UCL_EMIT_MSGPACK;
1485 			}
1486 		}
1487 
1488 		if (lua_isboolean (L, 3)) {
1489 			sort = lua_toboolean (L, 3);
1490 		}
1491 	}
1492 
1493 	obj = ucl_object_lua_import (L, 1);
1494 
1495 	if (obj != NULL) {
1496 
1497 		if (sort) {
1498 			if (ucl_object_type (obj) == UCL_OBJECT) {
1499 				ucl_object_sort_keys (obj, UCL_SORT_KEYS_RECURSIVE);
1500 			}
1501 		}
1502 
1503 		lua_ucl_to_string (L, obj, format);
1504 		ucl_object_unref (obj);
1505 	}
1506 	else {
1507 		lua_pushnil (L);
1508 	}
1509 
1510 	return 1;
1511 }
1512 
1513 static int
1514 lua_ucl_null_tostring (lua_State* L)
1515 {
1516 	lua_pushstring (L, "null");
1517 	return 1;
1518 }
1519 
1520 static void
1521 lua_ucl_null_mt (lua_State *L)
1522 {
1523 	luaL_newmetatable (L, NULL_META);
1524 
1525 	lua_pushcfunction (L, lua_ucl_null_tostring);
1526 	lua_setfield (L, -2, "__tostring");
1527 
1528 	lua_pop (L, 1);
1529 }
1530 
1531 int
1532 luaopen_ucl (lua_State *L)
1533 {
1534 	lua_ucl_parser_mt (L);
1535 	lua_ucl_null_mt (L);
1536 	lua_ucl_object_mt (L);
1537 	lua_ucl_types_mt (L);
1538 
1539 	/* Create the refs weak table: */
1540 	lua_createtable (L, 0, 2);
1541 	lua_pushliteral (L, "v"); /* tbl, "v" */
1542 	lua_setfield (L, -2, "__mode");
1543 	lua_pushvalue (L, -1); /* tbl, tbl */
1544 	lua_setmetatable (L, -2); /* tbl */
1545 	lua_setfield (L, LUA_REGISTRYINDEX, "ucl.refs");
1546 
1547 	lua_newtable (L);
1548 
1549 	lua_pushcfunction (L, lua_ucl_parser_init);
1550 	lua_setfield (L, -2, "parser");
1551 
1552 	lua_pushcfunction (L, lua_ucl_to_json);
1553 	lua_setfield (L, -2, "to_json");
1554 
1555 	lua_pushcfunction (L, lua_ucl_to_config);
1556 	lua_setfield (L, -2, "to_config");
1557 
1558 	lua_pushcfunction (L, lua_ucl_to_format);
1559 	lua_setfield (L, -2, "to_format");
1560 
1561 	ucl_null = lua_newuserdata (L, 0);
1562 	luaL_getmetatable (L, NULL_META);
1563 	lua_setmetatable (L, -2);
1564 
1565 	lua_pushvalue (L, -1);
1566 	lua_setfield (L, LUA_REGISTRYINDEX, "ucl.null");
1567 
1568 	lua_setfield (L, -2, "null");
1569 
1570 	return 1;
1571 }
1572 
1573 struct ucl_lua_funcdata*
1574 ucl_object_toclosure (const ucl_object_t *obj)
1575 {
1576 	if (obj == NULL || obj->type != UCL_USERDATA) {
1577 		return NULL;
1578 	}
1579 
1580 	return (struct ucl_lua_funcdata*)obj->value.ud;
1581 }
1582 
1583 FLUA_MODULE(ucl);
1584