Radish alpha
H
HardenedBSD Package Manager
Radicle
Git (anonymous pull)
Log in to clone via SSH
Import newer libucl which among other things improve the error message
Baptiste Daroussin committed 11 years ago
commit 6e2fd8efa5968d7b37292cd94babfbb25a72f218
parent 4c2d6c15ef73c15c9df7d49105bfb46918299494
17 files changed +444 -332
modified external/libucl/ChangeLog.md
@@ -4,3 +4,11 @@

- Streamline emitter has been added, so it is now possible to output partial `ucl` objects
- Emitter now is more flexible due to emitter_context structure
+

+
### 0.5.1
+
- Fixed number of bugs and memory leaks
+

+
### 0.5.2
+

+
- Allow userdata objects to be emitted and destructed
+
- Use userdata objects to store lua function references
modified external/libucl/Makefile.w32
@@ -33,6 +33,7 @@ OBJECTS = $(OBJDIR)/ucl_hash.o \
		$(OBJDIR)/ucl_util.o \
		$(OBJDIR)/ucl_parser.o \
		$(OBJDIR)/ucl_emitter.o \
+
		$(OBJDIR)/ucl_emitter_utils.o \
		$(OBJDIR)/ucl_schema.o \
		$(OBJDIR)/xxhash.o

@@ -51,6 +52,8 @@ $(OBJDIR)/ucl_parser.o: $(SRCDIR)/ucl_parser.c $(HDEPS)
	$(CC) -o $(OBJDIR)/ucl_parser.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/ucl_parser.c
$(OBJDIR)/ucl_emitter.o: $(SRCDIR)/ucl_emitter.c $(HDEPS)
	$(CC) -o $(OBJDIR)/ucl_emitter.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/ucl_emitter.c
+
$(OBJDIR)/ucl_emitter_utils.o: $(SRCDIR)/ucl_emitter_utils.c $(HDEPS)
+
	$(CC) -o $(OBJDIR)/ucl_emitter_utils.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/ucl_emitter_utils.c
$(OBJDIR)/ucl_hash.o: $(SRCDIR)/ucl_hash.c $(HDEPS)
	$(CC) -o $(OBJDIR)/ucl_hash.o $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) -c $(SRCDIR)/ucl_hash.c
$(OBJDIR)/ucl_schema.o: $(SRCDIR)/ucl_schema.c $(HDEPS)
@@ -61,7 +64,7 @@ $(OBJDIR)/xxhash.o: $(SRCDIR)/xxhash.c $(HDEPS)
clean:
	$(RM) $(OBJDIR)/*.o $(OBJDIR)/$(SONAME) $(OBJDIR)/$(SONAME) $(OBJDIR)/chargen $(OBJDIR)/test_basic $(OBJDIR)/test_speed $(OBJDIR)/objdump $(OBJDIR)/test_generate
	$(RMDIR) $(OBJDIR)
-
	
+

# Utils

chargen: utils/chargen.c $(OBJDIR)/$(SONAME)
@@ -75,7 +78,7 @@ test: $(OBJDIR) $(OBJDIR)/$(SONAME) $(OBJDIR)/test_basic $(OBJDIR)/test_speed $(

run-test: test
	TEST_DIR=$(TESTDIR) $(TESTDIR)/run_tests.sh $(OBJDIR)/test_basic $(OBJDIR)/test_speed $(OBJDIR)/test_generate
-
	
+

$(OBJDIR)/test_basic: $(TESTDIR)/test_basic.c $(OBJDIR)/$(SONAME)
	$(CC) -o $(OBJDIR)/test_basic $(CPPFLAGS) $(COPT_FLAGS) $(CFLAGS) $(C_COMMON_FLAGS) $(SSL_CFLAGS) $(FETCH_FLAGS) $(LDFLAGS) $(TESTDIR)/test_basic.c $(LD_UCL_FLAGS)
$(OBJDIR)/test_speed: $(TESTDIR)/test_speed.c $(OBJDIR)/$(SONAME)
modified external/libucl/configure.ac
@@ -1,7 +1,7 @@
m4_define([maj_ver], [0])
m4_define([med_ver], [5])
-
m4_define([min_ver], [0])
-
m4_define([so_version], [2:0:0])
+
m4_define([min_ver], [3])
+
m4_define([so_version], [2:0:2])
m4_define([ucl_version], [maj_ver.med_ver.min_ver])

AC_INIT([libucl],[ucl_version],[https://github.com/vstakhov/libucl],[libucl])
modified external/libucl/include/ucl.h
@@ -203,6 +203,13 @@ typedef struct ucl_object_s {
	unsigned char* trash_stack[2];			/**< Pointer to allocated chunks */
} ucl_object_t;

+
/**
+
 * Destructor type for userdata objects
+
 * @param ud user specified data pointer
+
 */
+
typedef void (*ucl_userdata_dtor)(void *ud);
+
typedef const char* (*ucl_userdata_emitter)(void *ud);
+

/** @} */

/**
@@ -239,6 +246,14 @@ UCL_EXTERN ucl_object_t* ucl_object_new (void) UCL_WARN_UNUSED_RESULT;
UCL_EXTERN ucl_object_t* ucl_object_typed_new (ucl_type_t type) UCL_WARN_UNUSED_RESULT;

/**
+
 * Create new object with userdata dtor
+
 * @param dtor destructor function
+
 * @return new object
+
 */
+
UCL_EXTERN ucl_object_t* ucl_object_new_userdata (ucl_userdata_dtor dtor,
+
		ucl_userdata_emitter emitter) UCL_WARN_UNUSED_RESULT;
+

+
/**
 * Perform deep copy of an object copying everything
 * @param other object to copy
 * @return new object with refcount equal to 1
deleted external/libucl/lua/libucl.rockspec
@@ -1,26 +0,0 @@
-
package="libucl"
-
version="0.5.0-1"
-
source = {
-
  url = "https://github.com/downloads/vstakhov/libucl/libucl-0.5.0.tar.gz",
-
  md5 = "@MD5@",
-
  dir = "libucl-0.5.0"
-
}
-
description = {
-
  summary = "UCL - json like configuration language",
-
  detailed = [[
-
      UCL is heavily infused by nginx configuration as the example 
-
      of a convenient configuration system. 
-
      However, UCL is fully compatible with JSON format and is able 
-
      to parse json files. 
-
   ]],
-
  homepage = "http://github.com/vstakhov/libucl/",
-
  license = ""
-
}
-
dependencies = {
-
  "lua >= 5.1"
-
}
-
build = {
-
  type = "command",
-
  build_command = "LUA=$(LUA) CPPFLAGS=-I$(LUA_INCDIR) ./configure --prefix=$(PREFIX) --libdir=$(LIBDIR) --datadir=$(LUADIR) && make clean && make",
-
  install_command = "make install"
-
}
modified external/libucl/lua/lua_ucl.c
@@ -28,6 +28,43 @@
#include "ucl.h"
#include "ucl_internal.h"
#include "lua_ucl.h"
+
#include <strings.h>
+

+
/***
+
 * @module ucl
+
 * This lua module allows to parse objects from strings and to store data into
+
 * ucl objects. It uses `libucl` C library to parse and manipulate with ucl objects.
+
 * @example
+
local ucl = require("ucl")
+

+
local parser = ucl.parser()
+
local res,err = parser:parse_string('{key=value}')
+

+
if not res then
+
	print('parser error: ' .. err)
+
else
+
	local obj = parser:get_object()
+
	local got = ucl.to_format(obj, 'json')
+
endif
+

+
local table = {
+
  str = 'value',
+
  num = 100500,
+
  null = ucl.null,
+
  func = function ()
+
    return 'huh'
+
  end
+
}
+

+
print(ucl.to_format(table, 'ucl'))
+
-- Output:
+
--[[
+
num = 100500;
+
str = "value";
+
null = null;
+
func = "huh";
+
--]]
+
 */

#define PARSER_META "ucl.parser.meta"
#define EMITTER_META "ucl.emitter.meta"
@@ -40,6 +77,12 @@ static ucl_object_t* ucl_object_lua_fromelt (lua_State *L, int idx);

static void *ucl_null;

+
struct ucl_lua_funcdata {
+
	lua_State *L;
+
	int idx;
+
	char *ret;
+
};
+

/**
 * Push a single element of an object to lua
 * @param L
@@ -55,6 +98,42 @@ ucl_object_lua_push_element (lua_State *L, const char *key,
	lua_settable (L, -3);
}

+
static void
+
lua_ucl_userdata_dtor (void *ud)
+
{
+
	struct ucl_lua_funcdata *fd = (struct ucl_lua_funcdata *)ud;
+

+
	luaL_unref (fd->L, LUA_REGISTRYINDEX, fd->idx);
+
	if (fd->ret != NULL) {
+
		free (fd->ret);
+
	}
+
	free (fd);
+
}
+

+
static const char *
+
lua_ucl_userdata_emitter (void *ud)
+
{
+
	struct ucl_lua_funcdata *fd = (struct ucl_lua_funcdata *)ud;
+
	const char *out = "";
+

+
	lua_rawgeti (fd->L, LUA_REGISTRYINDEX, fd->idx);
+

+
	lua_pcall (fd->L, 0, 1, 0);
+
	out = lua_tostring (fd->L, -1);
+

+
	if (out != NULL) {
+
		/* We need to store temporary string in a more appropriate place */
+
		if (fd->ret) {
+
			free (fd->ret);
+
		}
+
		fd->ret = strdup (out);
+
	}
+

+
	lua_settop (fd->L, 0);
+

+
	return fd->ret;
+
}
+

/**
 * Push a single object to lua
 * @param L
@@ -124,6 +203,8 @@ static int
ucl_object_lua_push_scalar (lua_State *L, const ucl_object_t *obj,
		bool allow_array)
{
+
	struct ucl_lua_funcdata *fd;
+

	if (allow_array && obj->next != NULL) {
		/* Actually we need to push this as an array */
		return ucl_object_lua_push_array (L, obj);
@@ -150,6 +231,10 @@ ucl_object_lua_push_scalar (lua_State *L, const ucl_object_t *obj,
	case UCL_NULL:
		lua_getfield (L, LUA_REGISTRYINDEX, "ucl.null");
		break;
+
	case UCL_USERDATA:
+
		fd = (struct ucl_lua_funcdata *)obj->value.ud;
+
		lua_rawgeti (L, LUA_REGISTRYINDEX, fd->idx);
+
		break;
	default:
		lua_pushnil (L);
		break;
@@ -158,10 +243,20 @@ ucl_object_lua_push_scalar (lua_State *L, const ucl_object_t *obj,
	return 1;
}

-
/**
-
 * Push an object to lua
-
 * @param L lua state
-
 * @param obj object to push
+
/***
+
 * @function ucl_object_push_lua(L, obj, allow_array)
+
 * This is a `C` function to push `UCL` object as lua variable. This function
+
 * converts `obj` to lua representation using the following conversions:
+
 *
+
 * - *scalar* values are directly presented by lua objects
+
 * - *userdata* values are converted to lua function objects using `LUA_REGISTRYINDEX`,
+
 * this can be used to pass functions from lua to c and vice-versa
+
 * - *arrays* are converted to lua tables with numeric indicies suitable for `ipairs` iterations
+
 * - *objects* are converted to lua tables with string indicies
+
 * @param {lua_State} L lua state pointer
+
 * @param {ucl_object_t} obj object to push
+
 * @param {bool} allow_array expand implicit arrays (should be true for all but partial arrays)
+
 * @return {int} `1` if an object is pushed to lua
 */
int
ucl_object_push_lua (lua_State *L, const ucl_object_t *obj, bool allow_array)
@@ -265,6 +360,7 @@ ucl_object_lua_fromelt (lua_State *L, int idx)
	int type;
	double num;
	ucl_object_t *obj = NULL;
+
	struct ucl_lua_funcdata *fd;

	type = lua_type (L, idx);

@@ -302,14 +398,24 @@ ucl_object_lua_fromelt (lua_State *L, int idx)
			}
			lua_pop (L, 2);
		}
-
		if (type == LUA_TTABLE) {
-
			obj = ucl_object_lua_fromtable (L, idx);
-
		}
-
		else if (type == LUA_TFUNCTION) {
-
			lua_pushvalue (L, idx);
-
			obj = ucl_object_new ();
-
			obj->type = UCL_USERDATA;
-
			obj->value.ud = (void *)(uintptr_t)(int)(luaL_ref (L, LUA_REGISTRYINDEX));
+
		else {
+
			if (type == LUA_TTABLE) {
+
				obj = ucl_object_lua_fromtable (L, idx);
+
			}
+
			else if (type == LUA_TFUNCTION) {
+
				fd = malloc (sizeof (*fd));
+
				if (fd != NULL) {
+
					lua_pushvalue (L, idx);
+
					fd->L = L;
+
					fd->ret = NULL;
+
					fd->idx = luaL_ref (L, LUA_REGISTRYINDEX);
+

+
					obj = ucl_object_new_userdata (lua_ucl_userdata_dtor,
+
							lua_ucl_userdata_emitter);
+
					obj->type = UCL_USERDATA;
+
					obj->value.ud = (void *)fd;
+
				}
+
			}
		}
		break;
	}
@@ -318,9 +424,13 @@ ucl_object_lua_fromelt (lua_State *L, int idx)
}

/**
-
 * Extract rcl object from lua object
-
 * @param L
-
 * @return
+
 * @function ucl_object_lua_import(L, idx)
+
 * Extracts ucl object from lua variable at `idx` position,
+
 * @see ucl_object_push_lua for conversion definitions
+
 * @param {lua_state} L lua state machine pointer
+
 * @param {int} idx index where the source variable is placed
+
 * @return {ucl_object_t} new ucl object extracted from lua variable. Reference count of this object is 1,
+
 * this object thus needs to be unref'ed after usage.
 */
ucl_object_t *
ucl_object_lua_import (lua_State *L, int idx)
@@ -370,6 +480,21 @@ lua_ucl_parser_get (lua_State *L, int index)
	return *((struct ucl_parser **) luaL_checkudata(L, index, PARSER_META));
}

+
/***
+
 * @method parser:parse_file(name)
+
 * Parse UCL object from file.
+
 * @param {string} name filename to parse
+
 * @return {bool[, string]} if res is `true` then file has been parsed successfully, otherwise an error string is also returned
+
@example
+
local parser = ucl.parser()
+
local res,err = parser:parse_file('/some/file.conf')
+

+
if not res then
+
	print('parser error: ' .. err)
+
else
+
	-- Do something with object
+
end
+
 */
static int
lua_ucl_parser_parse_file (lua_State *L)
{
@@ -398,6 +523,12 @@ lua_ucl_parser_parse_file (lua_State *L)
	return ret;
}

+
/***
+
 * @method parser:parse_string(input)
+
 * Parse UCL object from file.
+
 * @param {string} input string to parse
+
 * @return {bool[, string]} if res is `true` then file has been parsed successfully, otherwise an error string is also returned
+
 */
static int
lua_ucl_parser_parse_string (lua_State *L)
{
@@ -427,6 +558,11 @@ lua_ucl_parser_parse_string (lua_State *L)
	return ret;
}

+
/***
+
 * @method parser:get_object()
+
 * Get top object from parser and export it to lua representation.
+
 * @return {variant or nil} ucl object as lua native variable
+
 */
static int
lua_ucl_parser_get_object (lua_State *L)
{
@@ -542,6 +678,40 @@ lua_ucl_to_config (lua_State *L)
	return 1;
}

+
/***
+
 * @function ucl.to_format(var, format)
+
 * Converts lua variable `var` to the specified `format`. Formats supported are:
+
 *
+
 * - `json` - fine printed json
+
 * - `json-compact` - compacted json
+
 * - `config` - fine printed configuration
+
 * - `ucl` - same as `config`
+
 * - `yaml` - embedded yaml
+
 *
+
 * If `var` contains function, they are called during output formatting and if
+
 * they return string value, then this value is used for ouptut.
+
 * @param {variant} var any sort of lua variable (if userdata then metafield `__to_ucl` is searched for output)
+
 * @param {string} format any available format
+
 * @return {string} string representation of `var` in the specific `format`.
+
 * @example
+
local table = {
+
  str = 'value',
+
  num = 100500,
+
  null = ucl.null,
+
  func = function ()
+
    return 'huh'
+
  end
+
}
+

+
print(ucl.to_format(table, 'ucl'))
+
-- Output:
+
--[[
+
num = 100500;
+
str = "value";
+
null = null;
+
func = "huh";
+
--]]
+
 */
static int
lua_ucl_to_format (lua_State *L)
{
@@ -549,10 +719,29 @@ lua_ucl_to_format (lua_State *L)
	int format = UCL_EMIT_JSON;

	if (lua_gettop (L) > 1) {
-
		format = lua_tonumber (L, 2);
-
		if (format < 0 || format >= UCL_EMIT_YAML) {
-
			lua_pushnil (L);
-
			return 1;
+
		if (lua_type (L, 2) == LUA_TNUMBER) {
+
			format = lua_tonumber (L, 2);
+
			if (format < 0 || format >= UCL_EMIT_YAML) {
+
				lua_pushnil (L);
+
				return 1;
+
			}
+
		}
+
		else if (lua_type (L, 2) == LUA_TSTRING) {
+
			const char *strtype = lua_tostring (L, 2);
+

+
			if (strcasecmp (strtype, "json") == 0) {
+
				format = UCL_EMIT_JSON;
+
			}
+
			else if (strcasecmp (strtype, "json-compact") == 0) {
+
				format = UCL_EMIT_JSON_COMPACT;
+
			}
+
			else if (strcasecmp (strtype, "yaml") == 0) {
+
				format = UCL_EMIT_YAML;
+
			}
+
			else if (strcasecmp (strtype, "config") == 0 ||
+
				strcasecmp (strtype, "ucl") == 0) {
+
				format = UCL_EMIT_CONFIG;
+
			}
		}
	}

modified external/libucl/lua/test.lua
@@ -32,3 +32,17 @@ function test_simple()
end

test_simple()
+

+
local table = {
+
  str = 'value',
+
  num = 100500,
+
  null = ucl.null,
+
  func = function ()
+
    return 'huh'
+
  end,
+
  badfunc = function()
+
    print("I'm bad")
+
  end
+
}
+

+
print(ucl.to_format(table, 'ucl'))
modified external/libucl/src/ucl_emitter.c
@@ -355,6 +355,8 @@ ucl_emitter_common_elt (struct ucl_emitter_context *ctx,
{
	const struct ucl_emitter_functions *func = ctx->func;
	bool flag;
+
	struct ucl_object_userdata *ud;
+
	const char *ud_out = "";

	if (ctx->id != UCL_EMIT_CONFIG && !first) {
		if (compact) {
@@ -413,6 +415,16 @@ ucl_emitter_common_elt (struct ucl_emitter_context *ctx,
		ucl_emitter_common_end_array (ctx, obj, compact);
		break;
	case UCL_USERDATA:
+
		ud = (struct ucl_object_userdata *)obj;
+
		ucl_emitter_print_key (print_key, ctx, obj, compact);
+
		if (ud->emitter) {
+
			ud_out = ud->emitter (obj->value.ud);
+
			if (ud_out == NULL) {
+
				ud_out = "null";
+
			}
+
		}
+
		ucl_elt_string_write_json (ud_out, strlen (ud_out), ctx);
+
		ucl_emitter_finish_object (ctx, obj, compact, !print_key);
		break;
	}
}
modified external/libucl/src/ucl_emitter_utils.c
@@ -150,7 +150,7 @@ ucl_utstring_append_character (unsigned char c, size_t len, void *ud)
		utstring_append_c (buf, c);
	}
	else {
-
		utstring_reserve (buf, len);
+
		utstring_reserve (buf, len + 1);
		memset (&buf->d[buf->i], c, len);
		buf->i += len;
		buf->d[buf->i] = '\0';
modified external/libucl/src/ucl_hash.c
@@ -66,6 +66,20 @@ ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj,
	HASH_ADD_KEYPTR (hh, hashlin->buckets, key, keylen, node);
}

+
void ucl_hash_replace (ucl_hash_t* hashlin, const ucl_object_t *old,
+
		const ucl_object_t *new)
+
{
+
	ucl_hash_node_t *node;
+

+
	HASH_FIND (hh, hashlin->buckets, old->key, old->keylen, node);
+
	if (node != NULL) {
+
		/* Direct replacement */
+
		node->data = new;
+
		node->hh.key = new->key;
+
		node->hh.keylen = new->keylen;
+
	}
+
}
+

const void*
ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter)
{
@@ -122,5 +136,6 @@ ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj)

	if (found) {
		HASH_DELETE (hh, hashlin->buckets, found);
+
		UCL_FREE (sizeof (ucl_hash_node_t), found);
	}
}
modified external/libucl/src/ucl_hash.h
@@ -66,6 +66,12 @@ void ucl_hash_insert (ucl_hash_t* hashlin, const ucl_object_t *obj, const char *
		unsigned keylen);

/**
+
 * Replace element in the hash
+
 */
+
void ucl_hash_replace (ucl_hash_t* hashlin, const ucl_object_t *old,
+
		const ucl_object_t *new);
+

+
/**
 * Delete an element from the the hashtable.
 */
void ucl_hash_delete (ucl_hash_t* hashlin, const ucl_object_t *obj);
modified external/libucl/src/ucl_internal.h
@@ -192,6 +192,7 @@ struct ucl_parser {
	int flags;
	ucl_object_t *top_obj;
	ucl_object_t *cur_obj;
+
	const char *cur_file;
	struct ucl_macro *macroes;
	struct ucl_stack *stack;
	struct ucl_chunk *chunks;
@@ -202,6 +203,12 @@ struct ucl_parser {
	UT_string *err;
};

+
struct ucl_object_userdata {
+
	ucl_object_t obj;
+
	ucl_userdata_dtor dtor;
+
	ucl_userdata_emitter emitter;
+
};
+

/**
 * Unescape json string inplace
 * @param str
modified external/libucl/src/ucl_parser.c
@@ -56,20 +56,33 @@ struct ucl_parser_saved_state {
    } while (0)

static inline void
-
ucl_set_err (struct ucl_chunk *chunk, int code, const char *str, UT_string **err)
+
ucl_set_err (struct ucl_parser *parser, int code, const char *str, UT_string **err)
{
+
	const char *fmt_string, *filename;
+
	struct ucl_chunk *chunk = parser->chunks;
+

+
	if (parser->cur_file) {
+
		filename = parser->cur_file;
+
	}
+
	else {
+
		filename = "<unknown>";
+
	}
	if (chunk->pos < chunk->end) {
		if (isgraph (*chunk->pos)) {
-
			ucl_create_err (err, "error on line %d at column %d: '%s', character: '%c'",
-
					chunk->line, chunk->column, str, *chunk->pos);
+
			fmt_string = "error while parsing %s: "
+
					"line: %d, column: %d - '%s', character: '%c'";
		}
		else {
-
			ucl_create_err (err, "error on line %d at column %d: '%s', character: '0x%02x'",
-
					chunk->line, chunk->column, str, (int)*chunk->pos);
+
			fmt_string = "error while parsing %s: "
+
					"line: %d, column: %d - '%s', character: '0x%02x'";
		}
+
		ucl_create_err (err, fmt_string,
+
			filename, chunk->line, chunk->column,
+
			str, *chunk->pos);
	}
	else {
-
		ucl_create_err (err, "error at the end of chunk: %s", str);
+
		ucl_create_err (err, "error while parsing %s: at the end of chunk: %s",
+
			filename, str);
	}
}

@@ -84,11 +97,12 @@ ucl_skip_comments (struct ucl_parser *parser)
	struct ucl_chunk *chunk = parser->chunks;
	const unsigned char *p;
	int comments_nested = 0;
+
	bool quoted = false;

	p = chunk->pos;

start:
-
	if (*p == '#') {
+
	if (chunk->remain > 0 && *p == '#') {
		if (parser->state != UCL_STATE_SCOMMENT &&
				parser->state != UCL_STATE_MCOMMENT) {
			while (p < chunk->end) {
@@ -100,34 +114,41 @@ start:
			}
		}
	}
-
	else if (*p == '/' && chunk->remain >= 2) {
+
	else if (chunk->remain >= 2 && *p == '/') {
		if (p[1] == '*') {
			ucl_chunk_skipc (chunk, p);
			comments_nested ++;
			ucl_chunk_skipc (chunk, p);

			while (p < chunk->end) {
-
				if (*p == '*') {
-
					ucl_chunk_skipc (chunk, p);
-
					if (*p == '/') {
-
						comments_nested --;
-
						if (comments_nested == 0) {
-
							ucl_chunk_skipc (chunk, p);
-
							goto start;
+
				if (*p == '"' && *(p - 1) != '\\') {
+
					quoted = !quoted;
+
				}
+

+
				if (!quoted) {
+
					if (*p == '*') {
+
						ucl_chunk_skipc (chunk, p);
+
						if (*p == '/') {
+
							comments_nested --;
+
							if (comments_nested == 0) {
+
								ucl_chunk_skipc (chunk, p);
+
								goto start;
+
							}
						}
+
						ucl_chunk_skipc (chunk, p);
+
					}
+
					else if (p[0] == '/' && chunk->remain >= 2 && p[1] == '*') {
+
						comments_nested ++;
+
						ucl_chunk_skipc (chunk, p);
+
						ucl_chunk_skipc (chunk, p);
+
						continue;
					}
-
					ucl_chunk_skipc (chunk, p);
-
				}
-
				else if (p[0] == '/' && chunk->remain >= 2 && p[1] == '*') {
-
					comments_nested ++;
-
					ucl_chunk_skipc (chunk, p);
-
					ucl_chunk_skipc (chunk, p);
-
					continue;
				}
				ucl_chunk_skipc (chunk, p);
			}
			if (comments_nested != 0) {
-
				ucl_set_err (chunk, UCL_ENESTED, "unfinished multiline comment", &parser->err);
+
				ucl_set_err (parser, UCL_ENESTED,
+
						"unfinished multiline comment", &parser->err);
				return false;
			}
		}
@@ -492,7 +513,8 @@ ucl_copy_or_store_ptr (struct ucl_parser *parser,
		/* Copy string */
		*dst = UCL_ALLOC (in_len + 1);
		if (*dst == NULL) {
-
			ucl_set_err (parser->chunks, 0, "cannot allocate memory for a string", &parser->err);
+
			ucl_set_err (parser, 0, "cannot allocate memory for a string",
+
					&parser->err);
			return false;
		}
		if (need_lowercase) {
@@ -514,6 +536,10 @@ ucl_copy_or_store_ptr (struct ucl_parser *parser,
				*dst = tmp;
				ret = tret;
			}
+
			else {
+
				/* Free unexpanded value */
+
				UCL_FREE (in_len + 1, tmp);
+
			}
		}
		*dst_const = *dst;
	}
@@ -559,7 +585,8 @@ ucl_add_parser_stack (ucl_object_t *obj, struct ucl_parser *parser, bool is_arra

	st = UCL_ALLOC (sizeof (struct ucl_stack));
	if (st == NULL) {
-
		ucl_set_err (parser->chunks, 0, "cannot allocate memory for an object", &parser->err);
+
		ucl_set_err (parser, 0, "cannot allocate memory for an object",
+
				&parser->err);
		return NULL;
	}
	st->obj = obj;
@@ -842,7 +869,7 @@ ucl_lex_number (struct ucl_parser *parser,
		return true;
	}
	else if (ret == ERANGE) {
-
		ucl_set_err (chunk, ERANGE, "numeric value out of range", &parser->err);
+
		ucl_set_err (parser, ERANGE, "numeric value out of range", &parser->err);
	}

	return false;
@@ -867,10 +894,12 @@ ucl_lex_json_string (struct ucl_parser *parser,
		if (c < 0x1F) {
			/* Unmasked control character */
			if (c == '\n') {
-
				ucl_set_err (chunk, UCL_ESYNTAX, "unexpected newline", &parser->err);
+
				ucl_set_err (parser, UCL_ESYNTAX, "unexpected newline",
+
						&parser->err);
			}
			else {
-
				ucl_set_err (chunk, UCL_ESYNTAX, "unexpected control character", &parser->err);
+
				ucl_set_err (parser, UCL_ESYNTAX, "unexpected control character",
+
						&parser->err);
			}
			return false;
		}
@@ -878,7 +907,8 @@ ucl_lex_json_string (struct ucl_parser *parser,
			ucl_chunk_skipc (chunk, p);
			c = *p;
			if (p >= chunk->end) {
-
				ucl_set_err (chunk, UCL_ESYNTAX, "unfinished escape character", &parser->err);
+
				ucl_set_err (parser, UCL_ESYNTAX, "unfinished escape character",
+
						&parser->err);
				return false;
			}
			else if (ucl_test_character (c, UCL_CHARACTER_ESCAPE)) {
@@ -886,13 +916,15 @@ ucl_lex_json_string (struct ucl_parser *parser,
					ucl_chunk_skipc (chunk, p);
					for (i = 0; i < 4 && p < chunk->end; i ++) {
						if (!isxdigit (*p)) {
-
							ucl_set_err (chunk, UCL_ESYNTAX, "invalid utf escape", &parser->err);
+
							ucl_set_err (parser, UCL_ESYNTAX, "invalid utf escape",
+
									&parser->err);
							return false;
						}
						ucl_chunk_skipc (chunk, p);
					}
					if (p >= chunk->end) {
-
						ucl_set_err (chunk, UCL_ESYNTAX, "unfinished escape character", &parser->err);
+
						ucl_set_err (parser, UCL_ESYNTAX, "unfinished escape character",
+
								&parser->err);
						return false;
					}
				}
@@ -917,7 +949,8 @@ ucl_lex_json_string (struct ucl_parser *parser,
		ucl_chunk_skipc (chunk, p);
	}

-
	ucl_set_err (chunk, UCL_ESYNTAX, "no quote at the end of json string", &parser->err);
+
	ucl_set_err (parser, UCL_ESYNTAX, "no quote at the end of json string",
+
			&parser->err);
	return false;
}

@@ -988,7 +1021,8 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke
			}
			else {
				/* Invalid identifier */
-
				ucl_set_err (chunk, UCL_ESYNTAX, "key must begin with a letter", &parser->err);
+
				ucl_set_err (parser, UCL_ESYNTAX, "key must begin with a letter",
+
						&parser->err);
				return false;
			}
		}
@@ -1004,7 +1038,8 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke
					break;
				}
				else {
-
					ucl_set_err (chunk, UCL_ESYNTAX, "invalid character in a key", &parser->err);
+
					ucl_set_err (parser, UCL_ESYNTAX, "invalid character in a key",
+
							&parser->err);
					return false;
				}
			}
@@ -1022,7 +1057,7 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke
	}

	if (p >= chunk->end && got_content) {
-
		ucl_set_err (chunk, UCL_ESYNTAX, "unfinished key", &parser->err);
+
		ucl_set_err (parser, UCL_ESYNTAX, "unfinished key", &parser->err);
		return false;
	}
	else if (!got_content) {
@@ -1040,7 +1075,8 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke
				got_eq = true;
			}
			else {
-
				ucl_set_err (chunk, UCL_ESYNTAX, "unexpected '=' character", &parser->err);
+
				ucl_set_err (parser, UCL_ESYNTAX, "unexpected '=' character",
+
						&parser->err);
				return false;
			}
		}
@@ -1050,7 +1086,8 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke
				got_semicolon = true;
			}
			else {
-
				ucl_set_err (chunk, UCL_ESYNTAX, "unexpected ':' character", &parser->err);
+
				ucl_set_err (parser, UCL_ESYNTAX, "unexpected ':' character",
+
						&parser->err);
				return false;
			}
		}
@@ -1068,7 +1105,7 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke
	}

	if (p >= chunk->end && got_content) {
-
		ucl_set_err (chunk, UCL_ESYNTAX, "unfinished key", &parser->err);
+
		ucl_set_err (parser, UCL_ESYNTAX, "unfinished key", &parser->err);
		return false;
	}

@@ -1111,7 +1148,7 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke
		return false;
	}
	else if (keylen == 0) {
-
		ucl_set_err (chunk, UCL_ESYNTAX, "empty keys are not allowed", &parser->err);
+
		ucl_set_err (parser, UCL_ESYNTAX, "empty keys are not allowed", &parser->err);
		ucl_object_unref (nobj);
		return false;
	}
@@ -1205,7 +1242,7 @@ ucl_parse_string_value (struct ucl_parser *parser,
	}

	if (p >= chunk->end) {
-
		ucl_set_err (chunk, UCL_ESYNTAX, "unfinished value", &parser->err);
+
		ucl_set_err (parser, UCL_ESYNTAX, "unfinished value", &parser->err);
		return false;
	}

@@ -1385,7 +1422,8 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
						chunk->line ++;
						if ((str_len = ucl_parse_multiline_string (parser, chunk, c,
								p - c, &c, &var_expand)) == 0) {
-
							ucl_set_err (chunk, UCL_ESYNTAX, "unterminated multiline value", &parser->err);
+
							ucl_set_err (parser, UCL_ESYNTAX,
+
									"unterminated multiline value", &parser->err);
							return false;
						}
						obj->type = UCL_STRING;
@@ -1430,7 +1468,8 @@ parse_string:
			}
			str_len = chunk->pos - c - stripped_spaces;
			if (str_len <= 0) {
-
				ucl_set_err (chunk, 0, "string value must not be empty", &parser->err);
+
				ucl_set_err (parser, 0, "string value must not be empty",
+
						&parser->err);
				return false;
			}
			else if (str_len == 4 && memcmp (c, "null", 4) == 0) {
@@ -1489,7 +1528,9 @@ ucl_parse_after_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
		else if (ucl_test_character (*p, UCL_CHARACTER_VALUE_END)) {
			if (*p == '}' || *p == ']') {
				if (parser->stack == NULL) {
-
					ucl_set_err (chunk, UCL_ESYNTAX, "end of array or object detected without corresponding start", &parser->err);
+
					ucl_set_err (parser, UCL_ESYNTAX,
+
							"end of array or object detected without corresponding start",
+
							&parser->err);
					return false;
				}
				if ((*p == '}' && parser->stack->obj->type == UCL_OBJECT) ||
@@ -1510,7 +1551,9 @@ ucl_parse_after_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
					}
				}
				else {
-
					ucl_set_err (chunk, UCL_ESYNTAX, "unexpected terminating symbol detected", &parser->err);
+
					ucl_set_err (parser, UCL_ESYNTAX,
+
							"unexpected terminating symbol detected",
+
							&parser->err);
					return false;
				}

@@ -1532,7 +1575,8 @@ ucl_parse_after_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
		else {
			/* Anything else */
			if (!got_sep) {
-
				ucl_set_err (chunk, UCL_ESYNTAX, "delimiter is missing", &parser->err);
+
				ucl_set_err (parser, UCL_ESYNTAX, "delimiter is missing",
+
						&parser->err);
				return false;
			}
			return true;
@@ -1698,7 +1742,7 @@ ucl_state_machine (struct ucl_parser *parser)
			}
			if (parser->stack == NULL) {
				/* No objects are on stack, but we want to parse a key */
-
				ucl_set_err (chunk, UCL_ESYNTAX, "top object is finished but the parser "
+
				ucl_set_err (parser, UCL_ESYNTAX, "top object is finished but the parser "
						"expects a key", &parser->err);
				parser->prev_state = parser->state;
				parser->state = UCL_STATE_ERROR;
@@ -1820,7 +1864,8 @@ ucl_state_machine (struct ucl_parser *parser)
			break;
		default:
			/* TODO: add all states */
-
			ucl_set_err (chunk, UCL_EINTERNAL, "internal error: parser is in an unknown state", &parser->err);
+
			ucl_set_err (parser, UCL_EINTERNAL,
+
					"internal error: parser is in an unknown state", &parser->err);
			parser->state = UCL_STATE_ERROR;
			return false;
		}
modified external/libucl/src/ucl_util.c
@@ -129,11 +129,6 @@ static char* ucl_realpath(const char *path, char *resolved_path) {
#define ucl_realpath realpath
#endif

-
/**
-
 * @file rcl_util.c
-
 * Utilities for rcl parsing
-
 */
-

typedef void (*ucl_object_dtor) (ucl_object_t *obj);
static void ucl_object_free_internal (ucl_object_t *obj, bool allow_rec,
		ucl_object_dtor dtor);
@@ -148,7 +143,16 @@ ucl_object_dtor_free (ucl_object_t *obj)
	if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) {
		UCL_FREE (obj->len, obj->trash_stack[UCL_TRASH_VALUE]);
	}
-
	UCL_FREE (sizeof (ucl_object_t), obj);
+
	if (obj->type != UCL_USERDATA) {
+
		UCL_FREE (sizeof (ucl_object_t), obj);
+
	}
+
	else {
+
		struct ucl_object_userdata *ud = (struct ucl_object_userdata *)obj;
+
		if (ud->dtor) {
+
			ud->dtor (obj->value.ud);
+
		}
+
		UCL_FREE (sizeof (*ud), obj);
+
	}
}

/*
@@ -818,6 +822,7 @@ ucl_include_file (const unsigned char *data, size_t len,
#endif
	}

+
	parser->cur_file = realbuf;
	ucl_parser_set_filevars (parser, realbuf, false);

	prev_state = parser->state;
@@ -832,6 +837,7 @@ ucl_include_file (const unsigned char *data, size_t len,
			UCL_FREE (sizeof (struct ucl_chunk), chunk);
		}
	}
+
	parser->cur_file = NULL;

	parser->state = prev_state;

@@ -947,12 +953,14 @@ ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
		return false;
	}

+
	parser->cur_file = realbuf;
	ucl_parser_set_filevars (parser, realbuf, false);
	ret = ucl_parser_add_chunk (parser, buf, len);

	if (len > 0) {
		ucl_munmap (buf, len);
	}
+
	parser->cur_file = NULL;

	return ret;
}
@@ -1194,9 +1202,8 @@ ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt,

	found = __DECONST (ucl_object_t *, ucl_hash_search_obj (top->value.ov, elt));

-
	if (!found) {
+
	if (found == NULL) {
		top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
-
		DL_APPEND (found, elt);
		top->len ++;
		if (replace) {
			ret = false;
@@ -1204,11 +1211,8 @@ ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt,
	}
	else {
		if (replace) {
-
			ucl_hash_delete (top->value.ov, found);
+
			ucl_hash_replace (top->value.ov, found, elt);
			ucl_object_unref (found);
-
			top->value.ov = ucl_hash_insert_object (top->value.ov, elt);
-
			found = NULL;
-
			DL_APPEND (found, elt);
		}
		else if (merge) {
			if (found->type != UCL_OBJECT && elt->type == UCL_OBJECT) {
@@ -1451,29 +1455,51 @@ ucl_lookup_path (const ucl_object_t *top, const char *path_in) {
ucl_object_t *
ucl_object_new (void)
{
-
	ucl_object_t *new;
-
	new = malloc (sizeof (ucl_object_t));
-
	if (new != NULL) {
-
		memset (new, 0, sizeof (ucl_object_t));
-
		new->ref = 1;
-
		new->type = UCL_NULL;
-
	}
-
	return new;
+
	return ucl_object_typed_new (UCL_NULL);
}

ucl_object_t *
ucl_object_typed_new (ucl_type_t type)
{
	ucl_object_t *new;
-
	new = malloc (sizeof (ucl_object_t));
-
	if (new != NULL) {
-
		memset (new, 0, sizeof (ucl_object_t));
-
		new->ref = 1;
-
		new->type = (type <= UCL_NULL ? type : UCL_NULL);
+

+
	if (type != UCL_USERDATA) {
+
		new = UCL_ALLOC (sizeof (ucl_object_t));
+
		if (new != NULL) {
+
			memset (new, 0, sizeof (ucl_object_t));
+
			new->ref = 1;
+
			new->type = (type <= UCL_NULL ? type : UCL_NULL);
+
			new->next = NULL;
+
			new->prev = new;
+
		}
	}
+
	else {
+
		new = ucl_object_new_userdata (NULL, NULL);
+
	}
+

	return new;
}

+
ucl_object_t*
+
ucl_object_new_userdata (ucl_userdata_dtor dtor, ucl_userdata_emitter emitter)
+
{
+
	struct ucl_object_userdata *new;
+
	size_t nsize = sizeof (*new);
+

+
	new = UCL_ALLOC (nsize);
+
	if (new != NULL) {
+
		memset (new, 0, nsize);
+
		new->obj.ref = 1;
+
		new->obj.type = UCL_USERDATA;
+
		new->obj.next = NULL;
+
		new->obj.prev = (ucl_object_t *)new;
+
		new->dtor = dtor;
+
		new->emitter = emitter;
+
	}
+

+
	return (ucl_object_t *)new;
+
}
+

ucl_type_t
ucl_object_type (const ucl_object_t *obj)
{
modified external/libucl/tests/generate.res
@@ -1,3 +1,4 @@
+
key0 = 0.100000;
key1 = "test string";
key2 = "test \\nstring";
key3 = "  test string    \n";
modified external/libucl/tests/test_generate.c
@@ -54,6 +54,13 @@ main (int argc, char **argv)
	}

	obj = ucl_object_typed_new (UCL_OBJECT);
+

+
	/* Keys replacing */
+
	cur = ucl_object_fromstring_common ("value1", 0, UCL_STRING_TRIM);
+
	ucl_object_insert_key (obj, cur, "key0", 0, false);
+
	cur = ucl_object_fromdouble (0.1);
+
	ucl_object_replace_key (obj, cur, "key0", 0, false);
+

	/* Create some strings */
	cur = ucl_object_fromstring_common ("  test string    ", 0, UCL_STRING_TRIM);
	ucl_object_insert_key (obj, cur, "key1", 0, false);
deleted external/libucl/tests/test_streamline
@@ -1,210 +0,0 @@
-
#! /bin/sh
-

-
# test_streamline - temporary wrapper script for .libs/test_streamline
-
# Generated by libtool (GNU libtool) 2.4.2
-
#
-
# The test_streamline program cannot be directly executed until all the libtool
-
# libraries that it depends on are installed.
-
#
-
# This wrapper script should never be moved out of the build directory.
-
# If it is, it will not operate correctly.
-

-
# Sed substitution that helps us do robust quoting.  It backslashifies
-
# metacharacters that are still active within double-quoted strings.
-
sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
-

-
# Be Bourne compatible
-
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
-
  emulate sh
-
  NULLCMD=:
-
  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
-
  # is contrary to our usage.  Disable this feature.
-
  alias -g '${1+"$@"}'='"$@"'
-
  setopt NO_GLOB_SUBST
-
else
-
  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
-
fi
-
BIN_SH=xpg4; export BIN_SH # for Tru64
-
DUALCASE=1; export DUALCASE # for MKS sh
-

-
# The HP-UX ksh and POSIX shell print the target directory to stdout
-
# if CDPATH is set.
-
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-

-
relink_command=""
-

-
# This environment variable determines our operation mode.
-
if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then
-
  # install mode needs the following variables:
-
  generated_by_libtool_version='2.4.2'
-
  notinst_deplibs=' ../src/libucl.la'
-
else
-
  # When we are sourced in execute mode, $file and $ECHO are already set.
-
  if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
-
    file="$0"
-

-
# A function that is used when there is no print builtin or printf.
-
func_fallback_echo ()
-
{
-
  eval 'cat <<_LTECHO_EOF
-
$1
-
_LTECHO_EOF'
-
}
-
    ECHO="printf %s\\n"
-
  fi
-

-
# Very basic option parsing. These options are (a) specific to
-
# the libtool wrapper, (b) are identical between the wrapper
-
# /script/ and the wrapper /executable/ which is used only on
-
# windows platforms, and (c) all begin with the string --lt-
-
# (application programs are unlikely to have options which match
-
# this pattern).
-
#
-
# There are only two supported options: --lt-debug and
-
# --lt-dump-script. There is, deliberately, no --lt-help.
-
#
-
# The first argument to this parsing function should be the
-
# script's ../libtool value, followed by no.
-
lt_option_debug=
-
func_parse_lt_options ()
-
{
-
  lt_script_arg0=$0
-
  shift
-
  for lt_opt
-
  do
-
    case "$lt_opt" in
-
    --lt-debug) lt_option_debug=1 ;;
-
    --lt-dump-script)
-
        lt_dump_D=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%/[^/]*$%%'`
-
        test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=.
-
        lt_dump_F=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%^.*/%%'`
-
        cat "$lt_dump_D/$lt_dump_F"
-
        exit 0
-
      ;;
-
    --lt-*)
-
        $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2
-
        exit 1
-
      ;;
-
    esac
-
  done
-

-
  # Print the debug banner immediately:
-
  if test -n "$lt_option_debug"; then
-
    echo "test_streamline:test_streamline:${LINENO}: libtool wrapper (GNU libtool) 2.4.2" 1>&2
-
  fi
-
}
-

-
# Used when --lt-debug. Prints its arguments to stdout
-
# (redirection is the responsibility of the caller)
-
func_lt_dump_args ()
-
{
-
  lt_dump_args_N=1;
-
  for lt_arg
-
  do
-
    $ECHO "test_streamline:test_streamline:${LINENO}: newargv[$lt_dump_args_N]: $lt_arg"
-
    lt_dump_args_N=`expr $lt_dump_args_N + 1`
-
  done
-
}
-

-
# Core function for launching the target application
-
func_exec_program_core ()
-
{
-

-
      if test -n "$lt_option_debug"; then
-
        $ECHO "test_streamline:test_streamline:${LINENO}: newargv[0]: $progdir/$program" 1>&2
-
        func_lt_dump_args ${1+"$@"} 1>&2
-
      fi
-
      exec "$progdir/$program" ${1+"$@"}
-

-
      $ECHO "$0: cannot exec $program $*" 1>&2
-
      exit 1
-
}
-

-
# A function to encapsulate launching the target application
-
# Strips options in the --lt-* namespace from $@ and
-
# launches target application with the remaining arguments.
-
func_exec_program ()
-
{
-
  case " $* " in
-
  *\ --lt-*)
-
    for lt_wr_arg
-
    do
-
      case $lt_wr_arg in
-
      --lt-*) ;;
-
      *) set x "$@" "$lt_wr_arg"; shift;;
-
      esac
-
      shift
-
    done ;;
-
  esac
-
  func_exec_program_core ${1+"$@"}
-
}
-

-
  # Parse options
-
  func_parse_lt_options "$0" ${1+"$@"}
-

-
  # Find the directory that this script lives in.
-
  thisdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'`
-
  test "x$thisdir" = "x$file" && thisdir=.
-

-
  # Follow symbolic links until we get to the real thisdir.
-
  file=`ls -ld "$file" | /usr/bin/sed -n 's/.*-> //p'`
-
  while test -n "$file"; do
-
    destdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'`
-

-
    # If there was a directory component, then change thisdir.
-
    if test "x$destdir" != "x$file"; then
-
      case "$destdir" in
-
      [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;;
-
      *) thisdir="$thisdir/$destdir" ;;
-
      esac
-
    fi
-

-
    file=`$ECHO "$file" | /usr/bin/sed 's%^.*/%%'`
-
    file=`ls -ld "$thisdir/$file" | /usr/bin/sed -n 's/.*-> //p'`
-
  done
-

-
  # Usually 'no', except on cygwin/mingw when embedded into
-
  # the cwrapper.
-
  WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no
-
  if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then
-
    # special case for '.'
-
    if test "$thisdir" = "."; then
-
      thisdir=`pwd`
-
    fi
-
    # remove .libs from thisdir
-
    case "$thisdir" in
-
    *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /usr/bin/sed 's%[\\/][^\\/]*$%%'` ;;
-
    .libs )   thisdir=. ;;
-
    esac
-
  fi
-

-
  # Try to get the absolute directory name.
-
  absdir=`cd "$thisdir" && pwd`
-
  test -n "$absdir" && thisdir="$absdir"
-

-
  program='test_streamline'
-
  progdir="$thisdir/.libs"
-

-

-
  if test -f "$progdir/$program"; then
-
    # Add our own library path to LD_LIBRARY_PATH
-
    LD_LIBRARY_PATH="/home/bapt/dev/libucl/src/.libs:$LD_LIBRARY_PATH"
-

-
    # Some systems cannot cope with colon-terminated LD_LIBRARY_PATH
-
    # The second colon is a workaround for a bug in BeOS R4 sed
-
    LD_LIBRARY_PATH=`$ECHO "$LD_LIBRARY_PATH" | /usr/bin/sed 's/::*$//'`
-

-
    export LD_LIBRARY_PATH
-

-
    if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
-
      # Run the actual program with our arguments.
-
      func_exec_program ${1+"$@"}
-
    fi
-
  else
-
    # The program doesn't exist.
-
    $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2
-
    $ECHO "This script is just a wrapper for $program." 1>&2
-
    $ECHO "See the libtool documentation for more information." 1>&2
-
    exit 1
-
  fi
-
fi