Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Import newer libucl which among other things improve the error message
Baptiste Daroussin committed 11 years ago
commit 6e2fd8efa5968d7b37292cd94babfbb25a72f218
parent 4c2d6c1
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