changeset 186:d4b8416e9ab1

Move C
author David Demelier <markand@malikania.fr>
date Sat, 23 Nov 2013 16:14:05 +0100
parents 523156bb3af5
children 600754c27c88
files C/array.c C/array.h C/buf.c C/buf.h C/directory.c C/directory.h C/ini.c C/ini.h C/nsock.c C/nsock.h C/pack.c C/pack.h C/parray.c C/parray.h array.c array.h buf.c buf.h directory.c directory.h ini.c ini.h nsock.c nsock.h pack.c pack.h parray.c parray.h
diffstat 28 files changed, 3620 insertions(+), 3620 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C/array.c	Sat Nov 23 16:14:05 2013 +0100
@@ -0,0 +1,382 @@
+/*
+ * array.c -- manipulate dynamic arrays
+ *
+ * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "array.h"
+
+#define OFFSET(x)	(arr->unit * (x))
+
+static int		grow(struct array *);
+
+int
+array_init(struct array *arr, size_t unit)
+{
+	if (unit == 0)
+		return -1;
+
+	arr->unit	= unit;
+	arr->size	= OFFSET(arr->chksize);
+
+	/* Set defaults if needed */
+	arr->chksize	= (arr->chksize <= 0) ? ARRAY_DEFAULT_CHKSIZE : arr->chksize;
+	arr->malloc	= (arr->malloc == NULL) ? &malloc : arr->malloc;
+	arr->realloc	= (arr->realloc == NULL) ? &realloc : arr->realloc;
+
+	if ((arr->data = arr->malloc(arr->size)) == NULL)
+		return -1;
+
+	if (arr->flags & ARRAY_CLEARBITS)
+		memset(arr->data, 0, arr->size);
+
+	return 0;
+}
+
+/*
+ * Valid options that can be set for an array :
+ * l -> optional array block size of type int
+ * m -> malloc function that must matches void * (*malloc)(size_t)
+ * r -> realloc function that must matches void * (*realloc)(void *, size_t)
+ * f -> array flags of type int
+ */
+void
+array_set(struct array *arr, const char *fmt, ...)
+{
+	va_list ap;
+	const char *p;
+
+	va_start(ap, fmt);
+	for (p = fmt; *p != '\0'; ++p)
+		switch (*p) {
+		case 'l':
+			arr->chksize = va_arg(ap, int);
+			break;
+		case 'm':
+			arr->malloc = va_arg(ap, void *(*)(size_t));
+			break;
+		case 'r':
+			arr->realloc = va_arg(ap, void *(*)(void *, size_t));
+			break;
+		case 'f':
+			arr->flags = va_arg(ap, int);
+			break;
+		default:
+			break;
+		}
+}
+
+/*
+ * Add to the head of array. NOTE: this may be very slow when adding a lot
+ * of object (about 100000). If you need to add a lot of data please consider
+ * using linked list instead. Returns -1 on failure or 0 on success.
+ */
+int
+array_push(struct array *arr, const void *data)
+{
+	if (grow(arr) < 0)
+		return -1;
+
+	memmove((char *)arr->data + arr->unit, arr->data, OFFSET(arr->length++));
+	memcpy((char *)arr->data, data, arr->unit);
+
+	return 0;
+}
+
+/*
+ * Insert the data at the specified index. The function returns -1 on
+ * allocation failure or the position of the added element.
+ */
+int
+array_insert(struct array *arr, const void *data, int index)
+{
+	if (arr->flags & ARRAY_INSERTSAFE)
+		if (index < 0 || index > arr->length)
+			return -1;
+
+	if (index < 0)
+		return array_push(arr, data);
+	if (index >= arr->length)
+		return array_append(arr, data);
+
+	/* Good place */
+	memmove((char *)arr->data + OFFSET(index + 1),
+	    (char *)arr->data + OFFSET(index), OFFSET(arr->length++ - index));
+	memcpy((char *)arr->data + OFFSET(index), data, arr->unit);
+
+	return index;
+}
+
+/*
+ * Append the data to the end of array. Returns -1 on failure or the position
+ * of the added element.
+ */
+int
+array_append(struct array *arr, const void *data)
+{
+	if (grow(arr) < 0)
+		return -1;
+
+	memcpy((char *)arr->data + OFFSET(arr->length++), data, arr->unit);
+
+	return (arr->length - 1);
+}
+
+/*
+ * Remove the array's head.
+ */
+void
+array_pop(struct array *arr)
+{
+	array_iremove(arr, 0);
+}
+
+/*
+ * Remove the array's tail.
+ */
+void
+array_unqueue(struct array *arr)
+{
+	array_iremove(arr, arr->length - 1);
+}
+
+/*
+ * Remove the data at the specified index. Bounds are checked.
+ */
+void
+array_iremove(struct array *arr, int index)
+{
+	if (arr->length > 0 && index >= 0 && index < arr->length) {
+		if (arr->flags & ARRAY_FASTREMOVE)
+			memmove((char *)arr->data + OFFSET(index),
+			    (char *)arr->data + OFFSET(--arr->length),
+			    arr->unit);
+		else
+			memmove((char *)arr->data + OFFSET(index),
+			    (char *)arr->data + OFFSET(index + 1),
+			    OFFSET(arr->length-- - index - 1));
+	}
+
+	if (arr->flags & ARRAY_CLEARBITS)
+		memset((char *)arr->data + OFFSET(arr->length), 0, arr->unit);
+}
+
+/*
+ * Remove the object referenced by the `data' argument. Useful when you
+ * don't know the index.
+ */
+void
+array_premove(struct array *arr, const void *data)
+{
+	void *elm;
+	int i;
+
+	for (i = 0; i < arr->length; ++i) {
+		elm = (char *)arr->data + OFFSET(i);
+
+		if (memcmp(elm, data, arr->unit) == 0) {
+			array_iremove(arr, i);
+			break;
+		}
+	}
+}
+
+/*
+ * Swap the two elements referenced by index `i1' and `i2'. This function needs
+ * to allocate data to swap elements thus if the functions fails it returns -1
+ * otherwise 0 is returned.
+ */
+int
+array_iswap(struct array *arr, int i1, int i2)
+{
+	void *tmp;
+
+	/* Out of bounds */
+	if (i1 >= arr->length || i1 < 0 || i2 >= arr->length || i2 < 0)
+		return -1;
+
+	if ((tmp = arr->malloc(arr->unit)) == NULL)
+		return -1;
+
+	memcpy((char *)tmp, (char *)arr->data + OFFSET(i1), arr->unit);
+	memcpy((char *)arr->data + OFFSET(i1), (char *)arr->data + OFFSET(i2),
+	    arr->unit);
+	memcpy((char *)arr->data + OFFSET(i2), (char *)tmp, arr->unit);
+
+	/*
+	 * Clear bytes for safety you probably don't want a password or
+	 * secure data to be left somewhere in the memory.
+	 */
+
+	if (arr->flags & ARRAY_CLEARBITS)
+		memset(tmp, 0, arr->unit);
+	free(tmp);
+
+	return 0;
+}
+
+/*
+ * Swap the two elements referenced by data `o1' and `o2'. This function
+ * may be slow on large arrays since it must travel all the object
+ * to find the indexes.
+ */
+int
+array_pswap(struct array *arr, const void *o1, const void *o2)
+{
+	int found, i1, i2;
+
+	for (i1 = found = 0; !found && i1 < arr->length; ++i1)
+		found = memcmp((char *)arr->data + OFFSET(i1), o1, arr->unit) == 0;
+
+	if (!found)
+		return -1;
+
+	for (i2 = found = 0; !found && i2 < arr->length; ++i2)
+		found = memcmp((char *)arr->data + OFFSET(i2), o2, arr->unit) == 0;
+
+	if (!found)
+		return -1;
+
+	return array_iswap(arr, --i1, --i2);
+}
+
+/*
+ * Apply the function `fn' on each object and give the optional `udata'
+ * argument to the function too.
+ */
+void
+array_map(const struct array *arr, array_map_t fn, void *udata)
+{
+	int i;
+
+	for (i = 0; i < arr->length; ++i)
+		fn((char *)arr->data + OFFSET(i), udata);
+}
+
+/*
+ * Call qsort function to sort the array.
+ */
+void
+array_sort(struct array *arr, array_cmp_t fn)
+{
+	qsort(arr->data, arr->length, arr->unit, fn);
+}
+
+/*
+ * Compare each object with the user supplied function. If the `fn' function
+ * returns 1, 1 is returned and dst points to the correct object, dst should
+ * be a pointer to a pointer of object, like (int **) for a array of int.
+ */
+int
+array_find(const struct array *arr, array_cmp_t fn, void *dst, void *u)
+{
+	int st, i;
+
+	for (i = st = 0; i < arr->length && st != 1; ++i)
+		st = fn((char *)arr->data + OFFSET(i), u);
+
+	if (st && dst)
+		*(char **)dst = (char *)arr->data + OFFSET(i - 1);
+
+	return (st) ? i - 1 : -1;
+}
+
+void *
+array_first(const struct array *arr)
+{
+	return arr->data;
+}
+
+void *
+array_last(const struct array *arr)
+{
+	if (arr->length == 0)
+		return array_first(arr);
+
+	return (char *)arr->data + OFFSET(arr->length - 1);
+
+}
+
+void *
+array_get(const struct array *arr, int idx)
+{
+	if (idx < 0)
+		return array_first(arr);
+	if (idx >= arr->length)
+		return array_last(arr);
+
+	return (char *)arr->data + OFFSET(idx);
+}
+
+/*
+ * Erase every bytes and set the length to 0.
+ */
+void
+array_clear(struct array *arr)
+{
+	memset(arr->data, 0, arr->size);
+	arr->length = 0;
+}
+
+/*
+ * Same as array_clear except it also free the array object.
+ */
+void
+array_free(struct array *arr)
+{
+	array_clear(arr);
+	free(arr->data);
+
+	arr->data	= NULL;
+	arr->size	= 0;
+}
+
+/*
+ * Trim down the array to the correct size.
+ */
+void *
+array_trim(struct array *arr)
+{
+	return arr->realloc(arr->data, arr->length * arr->unit);
+}
+
+/*
+ * Increate the array storage when it is full. If the buffer is fixed size
+ * it returns -1 on full buffer otherwise 0 is returned if allocation
+ * succeeded.
+ */
+static int
+grow(struct array *arr)
+{
+	if ((arr->size / arr->unit) > (size_t)arr->length)
+		return 0;
+
+	if (!(arr->flags & ARRAY_FIXED)) {
+		if ((arr->data = arr->realloc(arr->data, arr->size +
+		    OFFSET(arr->chksize))) == NULL) {
+			arr->size = arr->length = 0;
+			return -1;
+		}
+
+		arr->size += OFFSET(arr->chksize);
+	} else
+		return -1;
+
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C/array.h	Sat Nov 23 16:14:05 2013 +0100
@@ -0,0 +1,125 @@
+/*
+ * array.h -- manipulate dynamic arrays
+ *
+ * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _ARRAY_H_
+#define _ARRAY_H_
+
+#include <stdarg.h>
+
+#ifndef ARRAY_DEFAULT_CHKSIZE
+#define ARRAY_DEFAULT_CHKSIZE	128
+#endif
+
+enum array_flags {
+	ARRAY_AUTO		= 0,		/* array grows automatically */
+	ARRAY_FIXED		= (1 << 0),	/* fixed size length */
+	ARRAY_FASTREMOVE	= (1 << 1),	/* use last object when removing */
+	ARRAY_CLEARBITS		= (1 << 2),	/* clear data when inserting/removing */
+	ARRAY_INSERTSAFE	= (1 << 3)	/* insertion must have valid indexes */
+};
+
+struct array {
+	int			flags;		/* (ro) array flags (default AUTO) */
+	void			*data;		/* (rw) array of data */
+	int			length;		/* (ro) number of element inside */
+	size_t			size;		/* (ro) current buffer size (allocated memory) */
+	size_t			unit;		/* (ro) unit size (sizeof the object) */
+	int			chksize;	/* (rw) chunk size (used when growing array) */
+
+	/* Own allocation functions */
+	void * (*malloc)(size_t);
+	void * (*realloc)(void *, size_t);
+};
+
+typedef void	(*array_map_t)(void *, void *);
+typedef int	(*array_cmp_t)(const void *, const void *);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int
+array_init(struct array *, size_t);
+
+void
+array_set(struct array *, const char *, ...);
+
+int
+array_push(struct array *, const void *);
+
+int
+array_insert(struct array *, const void *, int);
+
+int
+array_append(struct array *, const void *);
+
+void
+array_pop(struct array *);
+
+void
+array_unqueue(struct array *);
+
+void
+array_iremove(struct array *, int);
+
+void
+array_premove(struct array *, const void *);
+
+int
+array_iswap(struct array *, int, int);
+
+int
+array_pswap(struct array *, const void *, const void *);
+
+void
+array_map(const struct array *, array_map_t, void *);
+
+void
+array_sort(struct array *, array_cmp_t);
+
+int
+array_find(const struct array *, array_cmp_t, void *, void *);
+
+void *
+array_first(const struct array *);
+
+void *
+array_get(const struct array *, int);
+
+void *
+array_last(const struct array *);
+
+void
+array_clear(struct array *);
+
+void
+array_free(struct array *);
+
+void *
+array_trim(struct array *);
+	
+#define ARRAY_FOREACH(a, var, i)					\
+	for (i = 0, (var) = array_first((a));				\
+		i < (a)->length;					\
+		(var) = array_get(a, ++i))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ARRAY_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C/buf.c	Sat Nov 23 16:14:05 2013 +0100
@@ -0,0 +1,268 @@
+/*
+ * buf.c -- easy way to manipulate strings
+ *
+ * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "buf.h"
+
+#define BUF_AVAIL(buf)	((buf)->alsize - (buf)->length)
+#define BUF_SAFE(buf)	(!((buf)->flags & BUF_UNSAFE))
+#define BUF_FIXED(buf)	((buf)->flags & BUF_FIXED)
+#define BUF_AUTO(buf)	(buf->flags == 0)
+
+static void		copy(struct buf *, const void *, size_t);
+static int		grow(struct buf *, size_t);
+
+int
+buf_init(struct buf *buf, const char *txt)
+{
+	/* Set defaults if needed */
+	buf->chksize	= (buf->chksize <= 0) ? 128 : buf->chksize;
+	buf->alsize	= buf->chksize + 1;
+	buf->malloc	= (buf->malloc == NULL) ? &malloc : buf->malloc;
+	buf->realloc	= (buf->realloc == NULL) ? &realloc : buf->realloc;
+
+	if ((buf->text = buf->malloc(buf->alsize)) == NULL)
+		return -1;
+
+	if (txt != NULL)
+		buf_cat(buf, txt);
+
+	memset(buf->text, 0, buf->alsize);
+
+	return 0;
+}
+
+void
+buf_set(struct buf *buf, const char *fmt, ...)
+{
+	va_list ap;
+	const char *p;
+
+	va_start(ap, fmt);
+	for (p = fmt; *p != '\0'; ++p)
+		switch (*p) {
+		case 'l':
+			buf->chksize = va_arg(ap, int);
+			break;
+		case 'm':
+			buf->malloc = va_arg(ap, void *(*)(size_t));
+			break;
+		case 'r':
+			buf->realloc = va_arg(ap, void *(*)(void *, size_t));
+			break;
+		case 'f':
+		case 't':
+			buf->flags = va_arg(ap, int);
+			break;
+		default:
+			break;
+		}
+}
+
+/*
+ * This function appends not more than max characters from str.
+ */
+int
+buf_ncat(struct buf *buf, const char *str, size_t max)
+{
+	size_t tocopy = max;
+
+	for (tocopy = 0; str[tocopy] != '\0' && tocopy < max; ++tocopy)
+		continue;
+
+	if (BUF_AVAIL(buf) <= tocopy) {
+		/* Can't add more */
+		if (BUF_SAFE(buf) && BUF_FIXED(buf))
+			return -1;
+
+		if (BUF_AUTO(buf)) {
+			if (grow(buf, tocopy) < 0)
+				return -1;
+		} else {
+			/* String is unsafe, truncate to the available size */
+			tocopy = BUF_AVAIL(buf) - 1;
+		}
+	}
+
+	copy(buf, str, tocopy);
+	
+	return 0;
+}
+
+/*
+ * Append the string str to the end of the string buffer.
+ */
+int
+buf_cat(struct buf *buf, const char *str)
+{
+	return buf_ncat(buf, str, strlen(str));
+}
+
+/*
+ * Append the caracter c to the end of buffer
+ */
+int
+buf_putc(struct buf *buf, int c)
+{
+	char str[2] = { c, '\0' };
+
+	return buf_ncat(buf, str, 1);
+}
+
+/*
+ * Concatenate the printf(3) like call to the string buffer, this function
+ * returns -1 on fixed safe buffer, otherwise 0 is returned if there
+ * is no allocation failure.
+ */
+int
+buf_vprintf(struct buf *buf, const char *fmt, va_list ap)
+{
+	int copied, rv = 0, done = 0;
+
+	if (BUF_FIXED(buf) && BUF_SAFE(buf))
+		return -1;
+
+	do {
+		copied = vsnprintf(&buf->text[buf->length],
+		    BUF_AVAIL(buf), fmt, ap);
+
+		if (copied >= (signed int)BUF_AVAIL(buf) || copied == -1) {
+			if (BUF_FIXED(buf))
+				done = 1;
+
+			/*
+			 * vsnprintf returns -1 on windows, we need to grow
+			 * the buffer by block size.
+			 */
+			if (grow(buf, buf->alsize + buf->chksize) < 0) {
+				done = 1;
+				rv = -1;
+			}
+		} else {
+			done = 1;
+		}
+	} while (!done);
+
+	buf->length = strlen(buf->text);
+
+	return rv;
+}
+
+int
+buf_printf(struct buf *buf, const char *fmt, ...)
+{
+	va_list ap;
+	int rv;
+
+	va_start(ap, fmt);
+	rv = buf_vprintf(buf, fmt, ap);
+	va_end(ap);
+
+	return rv;
+}
+
+/*
+ * Realloc the string to it's size and remove useless bytes.
+ */
+int
+buf_trim(struct buf *buf)
+{
+	if ((buf->text = realloc(buf->text, buf->length + 1)) == NULL) {
+		buf->alsize = 0;
+		return -1;
+	}
+
+	buf->alsize = buf->length + 1;
+
+	return 0;
+}
+
+/*
+ * Remove `n' characters from the buffer, a positive value will cut the string
+ * from beginning, negative value will cut from end.
+ */
+void
+buf_cut(struct buf *buf, int start)
+{
+	if ((start > 0 && start >= buf->length) ||
+	    (start < 0 && (int)buf->length + start < 0))
+		return;
+
+	if (start < 0 && (int)buf->length + start >= 0)
+		start = buf->length + start;
+
+	buf->text[start]	= '\0';
+	buf->length		-= buf->length - start;
+}
+
+/*
+ * Clear the string buffer.
+ */
+void
+buf_clear(struct buf *buf)
+{
+	memset(buf->text, 0, buf->alsize);
+
+	buf->length = 0;
+}
+
+void
+buf_free(struct buf *buf)
+{
+	if (buf != NULL) {
+		buf_clear(buf);
+		free(buf->text);
+
+		buf->text = NULL;
+		buf->alsize = 0;
+	}
+}
+
+/*
+ * Append to the end of buffer the void ptr of count size.
+ */
+static void
+copy(struct buf *buf, const void *ptr, size_t count)
+{
+	memcpy(buf->text + buf->length, ptr, count);
+
+	buf->text[buf->length + count] = '\0';
+	buf->length += count;
+}
+
+/*
+ * Grow the text buffer until the available size fit the needed
+ * size. This function may return -1 on allocation failure.
+ */
+static int
+grow(struct buf *buf, size_t needed)
+{
+	while (BUF_AVAIL(buf) <= needed) {
+		buf->text = buf->realloc(buf->text, buf->alsize + buf->chksize);
+	
+		if (buf->text == NULL)
+			return -1;
+
+		buf->alsize += buf->chksize;
+	}
+
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C/buf.h	Sat Nov 23 16:14:05 2013 +0100
@@ -0,0 +1,88 @@
+/*
+ * buf.h -- easy way to manipulate strings
+ *
+ * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BUF_H_
+#define _BUF_H_
+
+#include <stdarg.h>
+
+#ifdef __GNUC__
+#  define _buf_at_printf(i1, i2)	__attribute__ ((format (printf, i1, i2)))
+#else
+#  define _buf_at_printf(i1, i2)
+#endif
+
+enum buf_flags {
+	BUF_UNSAFE	= (1 << 0),	/* string may be truncated */
+	BUF_FIXED	= (1 << 1),	/* string has fixed length */
+};
+
+struct buf {
+	enum buf_flags	flags;		/* string flags */
+	char		*text;		/* string text */
+	size_t		length;		/* string length */
+	size_t		alsize;		/* allocated size */
+	int		chksize;	/* chunk size */
+	int		maxsize;	/* max fixed length size */
+
+	void * (*malloc)(size_t);		/* alternate malloc */
+	void * (*realloc)(void *, size_t);	/* alternate realloc */
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int
+buf_init(struct buf *, const char *);
+
+void
+buf_set(struct buf *, const char *, ...);
+
+int
+buf_ncat(struct buf *, const char *, size_t);
+
+int
+buf_cat(struct buf *, const char *);
+
+int
+buf_putc(struct buf *, int);
+
+int
+buf_vprintf(struct buf *, const char *, va_list);
+
+int
+buf_printf(struct buf *, const char *, ...)	_buf_at_printf(2, 3);
+
+int
+buf_trim(struct buf *);
+
+void
+buf_cut(struct buf *, int);
+
+void
+buf_clear(struct buf *);
+
+void
+buf_free(struct buf *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _BUF_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C/directory.c	Sat Nov 23 16:14:05 2013 +0100
@@ -0,0 +1,144 @@
+/*
+ * directory.c -- portable way to open directories
+ *
+ * Copyright (c) 2011, 2012 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "directory.h"
+
+#if defined(_WIN32)	/* WINDOWS */
+
+struct directory *
+directory_open(const char *path)
+{
+	WIN32_FIND_DATA fdata;
+	HANDLE h;
+	struct directory *res;
+	char respath[FILENAME_MAX + 1];
+
+	if (!(res = calloc(1, sizeof (struct directory))))
+		return NULL;
+
+	snprintf(respath, sizeof (respath), "%s/*", path);
+
+	if ((h = FindFirstFile(respath, &fdata)) == INVALID_HANDLE_VALUE) {
+		free(res);
+		return NULL;
+	}
+
+	do {
+		res->ents = realloc(res->ents,
+			        sizeof (*res->ents) * (res->nents + 1));
+
+		/* Fail to reallocate */
+		if (!res->ents) {
+			free(res);
+			res = NULL;
+			break;
+		}
+
+		res->ents[res->nents].name	= strdup(fdata.cFileName);
+		res->ents[res->nents].type	= fdata.dwFileAttributes;
+		res->ents[res->nents++].length	= strlen(fdata.cFileName);
+	} while (FindNextFile(h, &fdata) != 0);
+
+	return res;
+}
+
+const char *
+directory_error(void)
+{
+	static char msg[1024];
+	DWORD num;
+
+	num = GetLastError();
+
+	FormatMessage(
+	    FORMAT_MESSAGE_FROM_SYSTEM |
+	    FORMAT_MESSAGE_IGNORE_INSERTS,
+	    NULL,
+	    num,
+	    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+	    msg,
+	    sizeof (msg),
+	    NULL
+	);
+
+	return msg;
+}
+
+#else			/* UNIX */
+
+#  include <errno.h>
+
+struct directory *
+directory_open(const char *path)
+{
+	DIR *dp;
+	struct dirent *ent;
+	struct directory *res;
+
+	if (!(res = calloc(1, sizeof (struct directory))))
+		return NULL;
+
+	if (!(dp = opendir(path))) {
+		free(res);
+		return NULL;
+	}
+
+	while ((ent = readdir(dp))) {
+		res->ents = realloc(res->ents,
+			        sizeof (*res->ents) * (res->nents + 1));
+
+		/* Fail to reallocate */
+		if (!res->ents) {
+			free(res);
+			res = NULL;
+			break;
+		}
+
+		res->ents[res->nents].name	= strdup(ent->d_name);
+		res->ents[res->nents].type	= ent->d_type;
+		res->ents[res->nents++].length	= ent->d_namlen;
+	}
+
+	(void)closedir(dp);
+
+	return res;
+}
+
+const char *
+directory_error(void)
+{
+	return strerror(errno);
+}
+
+#endif
+
+void
+directory_free(struct directory *dir)
+{
+	int i;
+
+	for (i = 0; i < dir->nents; ++i)
+		free(dir->ents[i].name);
+
+	free(dir->ents);
+	free(dir);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C/directory.h	Sat Nov 23 16:14:05 2013 +0100
@@ -0,0 +1,61 @@
+/*
+ * directory.h -- portable way to open directories
+ *
+ * Copyright (c) 2011, 2012 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _DIRECTORY_H_
+#define _DIRECTORY_H_
+
+struct directory {
+	int		nents;		/* number of entries */
+
+	struct {
+		char	*name;		/* entry name */
+		int	length;		/* length of entry */
+		int	type;		/* type of entry */
+	} *ents;
+};
+
+#if defined(_WIN32)
+
+#  include <windows.h>
+
+enum {
+	DIRECTORY_DIR	= FILE_ATTRIBUTE_DIRECTORY,
+	DIRECTORY_FILE	= FILE_ATTRIBUTE_NORMAL
+};
+
+#else
+
+#  include <dirent.h>
+
+enum {
+	DIRECTORY_DIR	= DT_DIR,
+	DIRECTORY_FILE	= DT_REG
+};
+
+#endif
+
+struct directory *
+directory_open(const char *);
+
+const char *
+directory_error(void);
+
+void
+directory_free(struct directory *);
+
+#endif /* _DIRECTORY_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C/ini.c	Sat Nov 23 16:14:05 2013 +0100
@@ -0,0 +1,555 @@
+/*
+ * ini.c -- parse .ini like files
+ *
+ * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "ini.h"
+
+/*
+ * sys/queue.h bits.
+ */
+
+#if !defined(TAILQ_FIRST)
+#define	TAILQ_FIRST(head)	((head)->tqh_first)
+#endif
+
+#if !defined(TAILQ_FOREACH)
+#define	TAILQ_FOREACH(var, head, field)					\
+	for ((var) = TAILQ_FIRST((head));				\
+	    (var);							\
+	    (var) = TAILQ_NEXT((var), field))
+#endif
+
+#if !defined(TAILQ_FOREACH_SAFE)
+#define	TAILQ_FOREACH_SAFE(var, head, field, tvar)			\
+	for ((var) = TAILQ_FIRST((head));				\
+	    (var) && ((tvar) = TAILQ_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+#endif
+
+#if !defined(TAILQ_INIT)
+#define	TAILQ_INIT(head) do {						\
+	TAILQ_FIRST((head)) = NULL;					\
+	(head)->tqh_last = &TAILQ_FIRST((head));			\
+} while (0)
+#endif
+
+#if !defined(TAILQ_INSERT_TAIL)
+#define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
+	TAILQ_NEXT((elm), field) = NULL;				\
+	(elm)->field.tqe_prev = (head)->tqh_last;			\
+	*(head)->tqh_last = (elm);					\
+	(head)->tqh_last = &TAILQ_NEXT((elm), field);			\
+} while (0)
+#endif
+
+#if !defined(TAILQ_NEXT)
+#define	TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+#endif
+
+#if !defined(TAILQ_REMOVE)
+#define	TAILQ_REMOVE(head, elm, field) do {				\
+	if ((TAILQ_NEXT((elm), field)) != NULL)				\
+		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
+		    (elm)->field.tqe_prev;				\
+	else {								\
+		(head)->tqh_last = (elm)->field.tqe_prev;		\
+	}								\
+	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\
+} while (0)
+#endif
+
+/* --------------------------------------------------------
+ * Structure definitions
+ * -------------------------------------------------------- */
+
+struct ini_private {
+	struct ini_section	*current;	/* current working section */
+	int			ignore;		/* must ignore (no redefine) */
+	FILE			*fp;		/* file pointer to read */
+
+	/* Line buffer */
+	char			*line;		/* line data */
+	int			linesize;	/* line allocated size */
+	int			lineno;		/* number of line in file */
+
+	/* Error reporting */
+	char			error[1024];
+};
+
+/* --------------------------------------------------------
+ * Prototypes
+ * -------------------------------------------------------- */
+
+#define F_VERBOSE(cg)		((cg)->flags & INI_VERBOSE)
+#define F_NOREDEFINE(cg)	((cg)->flags & INI_NOREDEFINE)
+#define F_FAILERROR(cg)		((cg)->flags & INI_FAILERROR)
+
+static char *
+sstrndup(const char *src, size_t max)
+{
+	char *res;
+	size_t length;
+
+	for (length = 0; length < max && src[length] != '\0'; ++length)
+		continue;
+
+	if ((res = malloc(length + 1)) == NULL)
+		return NULL;
+
+	memcpy(res, src, length);
+	res[length] = '\0';
+
+	return res;
+}
+
+static void
+sskip(char **lp)
+{
+	while (isspace (**lp) && **lp != '\0')
+		++(*lp);
+}
+
+static void
+sseek(char **lp)
+{
+	while (!isspace(**lp) && **lp != '\0')
+		++(*lp);
+}
+
+static void
+ini_set_error(struct ini_config *cg, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	if (cg->pv->error)
+		vsnprintf(cg->pv->error, sizeof (cg->pv->error), fmt, ap);
+	va_end(ap);
+}
+
+static void
+ini_warn(struct ini_config *cg, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	if (F_VERBOSE(cg)) {
+		vprintf(fmt, ap);
+		fputc('\n', stdout);
+	}
+
+	if (F_FAILERROR(cg)) {
+		va_start(ap, fmt);
+		vsnprintf(cg->pv->error, sizeof (cg->pv->error), fmt, ap);
+		va_end(ap);
+	}
+
+	va_end(ap);
+}
+
+/*
+ * Add a new section, this function only returns -1 on fatal error that may
+ * be impossible to continue parsing for the current line.
+ */
+
+static int
+ini_add_section(struct ini_config *cg, char **lp)
+{
+	char *begin = *lp, *end;
+	size_t length;
+	struct ini_section *section = NULL;
+
+	if (!(end = strchr(begin, ']'))) {
+		ini_warn(cg, "line %d: syntax error after [", cg->pv->lineno);
+		goto bad;
+	}
+
+	length = end - begin;
+
+	/* May not redefine? */
+	if (cg->pv->current && F_NOREDEFINE(cg))
+		if (strncmp(cg->pv->current->key, begin, length) == 0) {
+			ini_warn(cg, "line %d: redefining %s", cg->pv->lineno,
+			    cg->pv->current->key);
+			goto bad;
+		}
+
+	/* Allocate a new section and add it */
+	if (!(section = calloc(1, sizeof (*section))))
+		goto bad;
+
+	if (!(section->key = sstrndup(begin, length)))
+		goto bad;
+
+	TAILQ_INIT(&section->options);
+	TAILQ_INSERT_TAIL(&cg->sections, section, link);
+	cg->pv->current	= section;
+	cg->pv->ignore	= 0;
+
+	/* Trigger an event for the new section */
+	if (cg->open)
+		cg->open(cg->data, section->key);
+
+	*lp = &end[1];
+
+	return 0;
+
+bad:	if (section)
+		free(section->key);
+	free(section);
+
+	cg->pv->ignore = 1;
+	*lp = strchr(*lp, '\0');
+
+	return F_FAILERROR(cg) ? -1 : 0;
+}
+
+/*
+ * Add a new option, the returns value is same as ini_add_section.
+ */
+
+static int
+ini_add_option(struct ini_config *cg, char **lp)
+{
+	char *begin = *lp, *equal, *end;
+	struct ini_option *option = NULL;
+
+	if (!cg->pv->current) {
+		ini_warn(cg, "line %d: option within no section", cg->pv->lineno);
+		goto bad;
+	}
+
+	if (cg->pv->ignore ||
+	    !(option = calloc(1, sizeof (*option))))
+		goto bad;
+
+	/* Not valid */
+	if (!(equal = strchr(begin, '='))) {
+		ini_warn(cg, "line %d: missing =", cg->pv->lineno);
+		goto bad;
+	}
+
+	/* End of option */
+	end = begin;
+	sskip(&end);
+	sseek(&end);
+
+	option->key = sstrndup(begin, end - begin);
+
+	/* End of value */
+	begin = &equal[1];
+	sskip(&begin);
+	end = begin;
+
+	if (*end == '\'' || *end == '"') {
+		for (++end; *end != *begin && *end != '\0'; ++end)
+			continue;
+		if (*end != *begin) {
+			ini_warn(cg, "line %d: missing %c",
+			    cg->pv->lineno, *begin);
+			*lp = end;
+			goto bad;
+		} else
+			++ begin;
+	} else
+		sseek(&end);
+
+	option->value = sstrndup(begin, end - begin);
+
+	if (!option->key || !option->value) {
+		ini_warn(cg, "line %d: syntax error", cg->pv->lineno);
+		goto bad;
+	}
+
+	TAILQ_INSERT_TAIL(&cg->pv->current->options, option, link);
+
+	/* Trigger an event for the new section */
+	if (cg->get)
+		cg->get(cg->data, cg->pv->current->key, option);
+
+	*lp = &end[1];
+
+	return 0;
+
+bad:	if (option) {
+		free(option->key);
+		free(option->value);
+	}
+	free(option);
+
+	*lp = strchr(*lp, '\0');
+
+	return F_FAILERROR(cg) ? -1 : 0;
+}
+
+static int
+ini_read_line(struct ini_config *cg)
+{
+	char *lp = cg->pv->line;
+	int rv;
+
+	/* Ignore empty line */	
+	if (*lp == '\0' || *lp == '#' || *lp == ';')
+		return 0;
+
+	while (*lp != '\0') {
+		sskip(&lp);
+
+		if (*lp == '\0' || *lp == '#' || *lp == ';')
+			return 0;
+
+		/* Begin of section */
+		if (*lp == '[') {
+			++ lp;
+			rv = ini_add_section(cg, &lp);
+		/* Begin of option */
+		} else {
+			rv = ini_add_option(cg, &lp);
+		}
+
+		if (rv < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * Read the next line until the next '\n' character is found. Returns 0
+ * if the system had enough memory or -1 on allocation failure or on
+ * end of file. Only for mode == INI_LINEAR
+ */
+
+static int
+ini_get_line(struct ini_config *cg)
+{
+	int ch, pos;
+
+	memset(cg->pv->line, 0, cg->pv->linesize);
+	pos = 0;
+
+	while ((ch = fgetc(cg->pv->fp)) != '\n') {
+		if (feof(cg->pv->fp) || ferror(cg->pv->fp))
+			return -1;
+
+		/* End of buffer, realloc */
+		if (pos == cg->pv->linesize) {
+			cg->pv->line = realloc(cg->pv->line, cg->pv->linesize + 512);
+			if (!cg->pv->line)
+				return -1;
+
+			cg->pv->linesize += 512;
+		}
+
+		cg->pv->line[pos++] = ch;
+	}
+
+	return 0;
+}
+
+static int
+ini_open_file(struct ini_config *cg)
+{
+	if (!(cg->pv->fp = fopen(cg->path, "r"))) {
+		ini_set_error(cg, "open: %s", cg->path);
+		return -1;
+	}
+
+	cg->pv->linesize = INI_DEFAULT_LINESIZE;
+	cg->pv->line = calloc(sizeof (char), cg->pv->linesize);
+
+	if (!cg->pv->line) {
+		ini_set_error(cg, "malloc: %s", strerror(errno));
+		return -1;
+	}
+
+	return 0;
+}
+
+/* --------------------------------------------------------
+ * Public functions
+ * -------------------------------------------------------- */
+
+struct ini_config *
+ini_create(const char *path, enum ini_flags flags)
+{
+	struct ini_config *cg;	
+
+	cg = calloc(1, sizeof (*cg));
+	if (!cg)
+		return NULL;
+
+	cg->pv = calloc(1, sizeof (struct ini_private));
+	if (!cg->pv)
+		return NULL;
+
+	cg->path	= path;
+	cg->flags	= flags;
+
+	return cg;
+}
+
+void
+ini_set_handlers(struct ini_config *cg, void *data, ini_open_t open,
+		 ini_get_t get)
+{
+	if (!cg)
+		return;
+
+	cg->data	= data;
+	cg->open	= open;
+	cg->get		= get;
+}
+
+int
+ini_open(struct ini_config *cg)
+{
+	int rv = 0;
+
+	/* Open the file and prepare data for reading */
+	if (ini_open_file(cg) < 0)
+		return -1;
+
+	cg->pv->ignore	= 1;
+	cg->pv->lineno	= 1;
+
+	TAILQ_INIT(&cg->sections);
+
+	while (ini_get_line(cg) != -1 && !rv) {
+		rv = ini_read_line(cg);
+		++ cg->pv->lineno;
+	}
+
+	fclose(cg->pv->fp);
+
+	return rv;
+}
+
+/*
+ * Search the section `sectname' in the config structure. If the section
+ * is not found, this function returns NULL.
+ */
+
+struct ini_section *
+ini_select_section(const struct ini_config *cg, const char *sectname)
+{
+	struct ini_section *s;
+
+	TAILQ_FOREACH(s, &cg->sections, link)
+		if (strcmp(s->key, sectname) == 0)
+			return s;
+
+	return NULL;
+}
+
+/*
+ * Search the option `optname' in the section structure, argument
+ * section mustn't be NULL. If the option is not found, this function
+ * returns NULL.
+ */
+
+struct ini_option *
+ini_select_option(const struct ini_section *sc, const char *name)
+{
+	struct ini_option *o;
+
+	TAILQ_FOREACH(o, &sc->options, link)
+		if (strcmp(o->key, name) == 0)
+			return o;
+
+	return NULL;
+}
+
+/*
+ * Find an option from the config, by section and option names.
+ * Returns the option or NULL if not found.
+ */
+
+struct ini_option *
+ini_find(const struct ini_config *cg, const char *scname, const char *optname)
+{
+	struct ini_section *sc;
+
+	if ((sc = ini_select_section(cg, scname)))
+		return ini_select_option(sc, optname);
+
+	return NULL;
+}
+
+/*
+ * Return the last error or "No error" if there is no error.
+ */
+
+const char *
+ini_get_error(const struct ini_config *cg)
+{
+	if (!cg && errno != 0)
+		return strerror(errno);
+
+	if (cg->pv->error[0] == '\0') {
+		if (errno != 0)
+			return strerror(errno);
+
+		return "No error";
+	}
+
+	return cg->pv->error;
+}
+
+/*
+ * Free everything, level may be set like this:
+ * 0, only free parser and private resources.
+ * 1, free all sections and their keys,
+ * 2, free all sections and options keys and values.
+ */
+
+void
+ini_free(struct ini_config *cg, int level)
+{
+	struct ini_section *s, *stmp;
+	struct ini_option *o, *otmp;
+
+	if (level >= 1) {
+		TAILQ_FOREACH_SAFE(s, &cg->sections, link, stmp) {
+			if (level >= 2) {
+				TAILQ_FOREACH_SAFE(o, &s->options, link, otmp) {
+					TAILQ_REMOVE(&s->options, o, link);
+					free(o->key);
+					free(o->value);
+					free(o);
+				}
+			}
+
+			TAILQ_REMOVE(&cg->sections, s, link);
+			free(s->key);
+			free(s);
+		}
+	}
+
+	if (level >= 0) {
+		free(cg->pv->line);
+		free(cg->pv);
+		free(cg);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C/ini.h	Sat Nov 23 16:14:05 2013 +0100
@@ -0,0 +1,131 @@
+/*
+ * ini.h -- parse .ini like files
+ *
+ * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _INI_H_
+#define _INI_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(INI_DEFAULT_LINESIZE)
+#  define INI_DEFAULT_LINESIZE		1024
+#endif
+
+/*
+ * sys/queue.h bits.
+ */
+
+#if !defined(TAILQ_ENTRY)
+#define	TAILQ_ENTRY(type)						\
+struct {								\
+	struct type *tqe_next;	/* next element */			\
+	struct type **tqe_prev;	/* address of previous next element */	\
+}
+#endif
+
+#if !defined(TAILQ_HEAD)
+#define	TAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *tqh_first;	/* first element */			\
+	struct type **tqh_last;	/* addr of last next element */		\
+}
+#endif
+
+enum ini_flags {
+	INI_VERBOSE		= (1 << 0),	/* be verbose */
+	INI_NOREDEFINE		= (1 << 1),	/* do not allow redefinitions */
+	INI_FAILERROR		= (1 << 2)	/* abort parsing on first error */
+};
+
+typedef struct ini_config	ini_config_t;
+typedef struct ini_section	ini_section_t;
+typedef struct ini_option	ini_option_t;
+typedef struct ini_handler	ini_handler_t;
+
+typedef void (*ini_open_t)(void *, const char *);
+typedef void (*ini_get_t)(void *, const char *, const ini_option_t *);
+
+/* --------------------------------------------------------
+ * Structure definitions
+ * -------------------------------------------------------- */
+
+struct ini_private;
+
+struct ini_config {
+	const char		*path;		/* (ro) file path */
+	enum ini_flags		flags;		/* (ro) optional flags */
+	void			*data;		/* (rw) user data */
+
+	TAILQ_HEAD(, ini_section) sections;	/* (ro) linked-list of sections */
+
+	/* Event driven method */
+	void (*open)(void *, const char *);
+	void (*get)(void *, const char *, const struct ini_option *);
+
+	/* Private data */
+	struct ini_private	*pv;
+};
+
+struct ini_option {
+	char			*key;		/* (rw) option name */
+	char			*value;		/* (rw) option value */
+
+	TAILQ_ENTRY(ini_option)	link;
+};
+
+struct ini_section {
+	char			*key;		/* (rw) section key */	
+	TAILQ_HEAD(, ini_option) options;	/* (rw) list of options */
+
+	TAILQ_ENTRY(ini_section) link;
+};
+
+/* --------------------------------------------------------
+ * Main functions
+ * -------------------------------------------------------- */
+
+struct ini_config *
+ini_create(const char *, enum ini_flags);
+
+void
+ini_set_handlers(struct ini_config *, void *, ini_open_t, ini_get_t);
+
+int
+ini_open(struct ini_config *);
+
+struct ini_section *
+ini_select_section(const struct ini_config *, const char *);
+
+struct ini_option *
+ini_select_option(const struct ini_section *, const char *);
+
+struct ini_option *
+ini_find(const struct ini_config *, const char *, const char *);
+
+const char *
+ini_get_error(const struct ini_config *);
+
+void
+ini_free(struct ini_config *, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _INI_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C/nsock.c	Sat Nov 23 16:14:05 2013 +0100
@@ -0,0 +1,661 @@
+/*
+ * nsock.c -- portable BSD sockets wrapper
+ *
+ * Copyright (c) 2013 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#  include <stdio.h>
+#  include <stdlib.h>
+
+#if defined(_WIN32)
+
+  typedef SOCKET		nsock_socket_t;
+  typedef const char *		nsock_carg_t;
+  typedef char *		nsock_arg_t;
+
+#else
+#  include <errno.h>
+#  include <string.h>
+
+#  define ioctlsocket(s)	ioctl(s)
+#  define closesocket(s)	close(s)
+
+#  define gai_strerrorA		gai_strerror
+
+#  define INVALID_SOCKET	-1
+#  define SOCKET_ERROR		-1
+
+  typedef int			nsock_socket_t;
+  typedef const void *		nsock_carg_t;
+  typedef void *		nsock_arg_t;
+
+#endif
+
+#include "nsock.h"
+
+#define	TAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *tqh_first;	/* first element */			\
+	struct type **tqh_last;	/* addr of last next element */		\
+	size_t noclients;						\
+}
+
+#define	TAILQ_ENTRY(type)						\
+struct {								\
+	struct type *tqe_next;	/* next element */			\
+	struct type **tqe_prev;	/* address of previous next element */	\
+}
+
+#define	TAILQ_EMPTY(head)	((head)->tqh_first == NULL)
+
+#define	TAILQ_FIRST(head)	((head)->tqh_first)
+
+#define	TAILQ_FOREACH(var, head, field)					\
+	for ((var) = TAILQ_FIRST((head));				\
+	    (var);							\
+	    (var) = TAILQ_NEXT((var), field))
+
+#define	TAILQ_FOREACH_SAFE(var, head, field, tvar)			\
+	for ((var) = TAILQ_FIRST((head));				\
+	    (var) && ((tvar) = TAILQ_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define	TAILQ_INIT(head) do {						\
+	TAILQ_FIRST((head)) = NULL;					\
+	(head)->tqh_last = &TAILQ_FIRST((head));			\
+} while (0)
+
+#define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)	\
+		TAILQ_FIRST((head))->field.tqe_prev =			\
+		    &TAILQ_NEXT((elm), field);				\
+	else								\
+		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
+	TAILQ_FIRST((head)) = (elm);					\
+	(elm)->field.tqe_prev = &TAILQ_FIRST((head));			\
+	(head)->noclients ++;						\
+} while (0)
+
+#define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
+	TAILQ_NEXT((elm), field) = NULL;				\
+	(elm)->field.tqe_prev = (head)->tqh_last;			\
+	*(head)->tqh_last = (elm);					\
+	(head)->tqh_last = &TAILQ_NEXT((elm), field);			\
+	(head)->noclients ++;						\
+} while (0)
+
+#define	TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define	TAILQ_REMOVE(head, elm, field) do {				\
+	if ((TAILQ_NEXT((elm), field)) != NULL)				\
+		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
+		    (elm)->field.tqe_prev;				\
+	else {								\
+		(head)->tqh_last = (elm)->field.tqe_prev;		\
+	}								\
+	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\
+	(head)->noclients --;						\
+} while (0)
+
+struct nsock {
+	nsock_socket_t		fd;
+	char			error[128];
+};
+
+struct nsock_address {
+	struct sockaddr_storage	addr;
+	socklen_t		addrlen;
+	char			error[128];
+};
+
+struct nsock_listener {
+	const struct nsock	*sock;
+	char			error[128];
+	TAILQ_HEAD(, nsock_clt)	head;
+};
+
+struct nsock_clt {
+	const struct nsock	*sock;
+	TAILQ_ENTRY(nsock_clt)	link;
+};
+
+/* --------------------------------------------------------
+ * Private helpers
+ * -------------------------------------------------------- */
+
+static void
+nsock_set_error(char *buffer, size_t bufsize)
+{
+	memset(buffer, 0, bufsize);
+
+#if defined(_WIN32)
+	LPSTR str;
+
+	FormatMessageA(
+		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+		NULL,
+		WSAGetLastError(),
+		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+		(LPSTR)&str, 0, NULL);
+
+	if (str) {
+		strncpy(buffer, str, bufsize);
+		LocalFree(str);
+	}
+#else
+	strncpy(buffer, strerror(errno), bufsize);
+#endif
+}
+
+static void
+nsock_set_errno(char *buffer, size_t bufsize, int no)
+{
+	memset(buffer, 0, bufsize);
+	strncpy(buffer, strerror(no), bufsize - 1);
+}
+
+static struct nsock_clt *
+nsock_clt_new(const struct nsock *ns)
+{
+	struct nsock_clt *clt;
+
+	if ((clt = malloc(sizeof (struct nsock_clt))) == NULL)
+		return NULL;
+
+	clt->sock = ns;
+
+	return clt;
+}
+
+/* --------------------------------------------------------
+ * Sockets functions
+ * -------------------------------------------------------- */
+
+void
+nsock_init(void)
+{
+#if defined(_WIN32)
+	WSADATA wsa;
+	WSAStartup(MAKEWORD(2, 2), &wsa);
+#endif
+}
+
+struct nsock *
+nsock_new(void)
+{
+	struct nsock *ns;
+
+	if ((ns = malloc(sizeof (struct nsock))) == NULL)
+		return NULL;
+
+	return ns;
+}
+
+int
+nsock_create(struct nsock *ns, int domain, int type, int protocol)
+{
+	ns->fd = socket(domain, type, protocol);
+
+	if (ns->fd == INVALID_SOCKET)
+		nsock_set_error(ns->error, sizeof (ns->error));
+
+	return ns->fd == INVALID_SOCKET ? -1 : 0;
+}
+
+const char *
+nsock_error(struct nsock *ns)
+{
+	if (ns == NULL)
+		return strerror(ENOMEM);
+
+	return ns->error;
+}
+
+int
+nsock_bind(struct nsock *ns, const struct nsock_address *ep)
+{
+	int ret;
+
+	ret = bind(ns->fd, (const struct sockaddr *)&ep->addr, ep->addrlen);
+
+	if (ret == SOCKET_ERROR)
+		nsock_set_error(ns->error, sizeof (ns->error));
+
+	return ret == SOCKET_ERROR ? -1 : 0;
+}
+
+int
+nsock_listen(struct nsock *ns, int max)
+{
+	int ret;
+
+	ret = listen(ns->fd, max);
+
+	if (ret == SOCKET_ERROR)
+		nsock_set_error(ns->error, sizeof (ns->error));
+
+	return ret == SOCKET_ERROR ? -1 : 0;
+}
+
+int
+nsock_accept(struct nsock *ns, struct nsock **client, struct nsock_address **clientinfo)
+{
+	struct sockaddr_storage *st = NULL;
+	socklen_t *len = NULL;
+	int ret;
+
+	if ((*client = malloc(sizeof (struct nsock))) == NULL) {
+		nsock_set_errno(ns->error, sizeof (ns->error), ENOMEM);
+		return -1;
+	}
+
+	if (clientinfo != NULL) {
+		if ((*clientinfo = malloc(sizeof (struct nsock_address))) == NULL) {
+			free(client);
+			nsock_set_errno(ns->error, sizeof (ns->error), ENOMEM);
+			return -1;
+		}
+
+		st = &(*clientinfo)->addr;
+		len = &(*clientinfo)->addrlen;
+
+		/* Set the addrlen to sockaddr_storage first */
+		*len = sizeof (struct sockaddr_storage);
+	}
+
+	/* Prepare client */
+	memset((*client)->error, 0, sizeof ((*client)->error));
+	(*client)->fd = accept(ns->fd, (struct sockaddr *)st, len);
+
+	if ((*client)->fd == INVALID_SOCKET) {
+		nsock_set_error(ns->error, sizeof (ns->error));
+
+		/* free clients and set to NULL so user will not use it */
+		free(*client);
+		*client = NULL;
+
+		if (clientinfo != NULL) {
+			free(*clientinfo);
+			*clientinfo = NULL;
+		}
+
+		ret = -1;
+	} else
+		ret = 0;
+
+	return ret;
+}
+
+int
+nsock_connect(struct nsock *ns, const struct nsock_address *ep)
+{
+	int ret;
+
+	ret = connect(ns->fd, (const struct sockaddr *)&ep->addr, ep->addrlen);
+
+	if (ret == SOCKET_ERROR)
+		nsock_set_error(ns->error, sizeof (ns->error));
+
+	return ret == SOCKET_ERROR ? -1 : 0;
+}
+
+int
+nsock_set(struct nsock *ns, int level, int name, const void *arg, unsigned arglen)
+{
+	int ret;
+
+	ret = setsockopt(ns->fd, level, name, (nsock_carg_t)arg, arglen);
+
+	if (ret == SOCKET_ERROR)
+		nsock_set_error(ns->error, sizeof (ns->error));
+
+	return ret == SOCKET_ERROR ? -1 : 0;
+}
+
+long
+nsock_recv(struct nsock *ns, void *data, size_t datasz, int flags)
+{
+	long nbread;
+
+	nbread = recv(ns->fd, data, datasz, flags);
+
+	if (nbread == -1)
+		nsock_set_error(ns->error, sizeof (ns->error));
+
+	return nbread;
+}
+
+long
+nsock_recvfrom(struct nsock *ns, struct nsock_address *ep, void *data, size_t datasz, int flags)
+{
+	struct sockaddr_storage *st = NULL;
+	socklen_t *len = NULL;
+	long nbread;
+
+	if (ep != NULL) {
+		st = &ep->addr;
+		len = &ep->addrlen;
+
+		/* Set the addrlen to sockaddr_storage first */
+		*len = sizeof (struct sockaddr_storage);
+	}
+
+	nbread = recvfrom(ns->fd, data, datasz, flags,
+	    (struct sockaddr *)st, len);
+
+	if (nbread == SOCKET_ERROR)
+		nsock_set_error(ns->error, sizeof (ns->error));
+
+	return nbread;
+}
+
+long
+nsock_send(struct nsock *ns, const void *data, size_t datasz, int flags)
+{
+	long nbsent;
+
+	nbsent = send(ns->fd, data, datasz, flags);
+
+	if (nbsent == -1)
+		nsock_set_error(ns->error, sizeof (ns->error));
+
+	return nbsent;
+}
+
+long
+nsock_sendto(struct nsock *ns, const struct nsock_address *ep, const void *data, size_t datasz, int flags)
+{
+	long nbsent;
+
+	nbsent = sendto(ns->fd, data, datasz, flags,
+	    (const struct sockaddr *)&ep->addr, ep->addrlen);
+
+	if (nbsent == SOCKET_ERROR)
+		nsock_set_error(ns->error, sizeof (ns->error));
+
+	return nbsent;
+}
+
+void
+nsock_close(struct nsock *ns)
+{
+	closesocket(ns->fd);
+}
+
+void
+nsock_free(struct nsock *ns)
+{
+	free(ns);
+}
+
+void
+nsock_finish(void)
+{
+#if defined(_WIN32)
+	WSACleanup();
+#endif
+}
+
+/* --------------------------------------------------------
+ * End point functions
+ * -------------------------------------------------------- */
+
+struct nsock_address *
+nsock_addr_new(void)
+{
+	struct nsock_address *ep;
+
+	if ((ep = calloc(1, sizeof (struct nsock_address))) == NULL)
+		return NULL;
+
+	return ep;
+}
+
+const char *
+nsock_addr_error(struct nsock_address *ep)
+{
+	if (ep == NULL)
+		return strerror(ENOMEM);
+
+	return ep->error;
+}
+
+int
+nsock_addr_bind_ip(struct nsock_address *ep, const char *iface, unsigned port, int family)
+{
+	if (family == AF_INET6) {
+		struct sockaddr_in6 *ptr = (struct sockaddr_in6 *)&ep->addr;
+
+		memset(ptr, 0, sizeof (struct sockaddr_in6));
+		ptr->sin6_family = AF_INET6;
+		ptr->sin6_port = htons(port);
+
+		if (iface == NULL || strcmp(iface, "*") == 0)
+			ptr->sin6_addr = in6addr_any;
+		else if (inet_pton(AF_INET6, iface, &ptr->sin6_addr) <= 0) {
+			nsock_set_error(ep->error, sizeof (ep->error));
+			return -1;
+		}
+
+		ep->addrlen = sizeof (struct sockaddr_in6);
+	} else {
+		struct sockaddr_in *ptr = (struct sockaddr_in *)&ep->addr;
+
+		memset(ptr, 0, sizeof (struct sockaddr_in));
+		ptr->sin_family = AF_INET;
+		ptr->sin_port = htons(port);
+
+		if (iface == NULL || strcmp(iface, "*") == 0)
+			ptr->sin_addr.s_addr = INADDR_ANY;
+		else if (inet_pton(AF_INET, iface, &ptr->sin_addr) <= 0) {
+			nsock_set_error(ep->error, sizeof (ep->error));
+			return -1;
+		}
+
+		ep->addrlen = sizeof (struct sockaddr_in);
+	}
+	
+	return 0;
+}
+
+int
+nsock_addr_connect_ip(struct nsock_address *ep, const char *host, unsigned port, int family)
+{
+	struct addrinfo hints, *res;
+	char portstr[32];
+	int error;
+
+	memset(&hints, 0, sizeof (hints));
+	hints.ai_family = family;
+	hints.ai_socktype = SOCK_STREAM;
+
+	memset(portstr, 0, sizeof (portstr));
+	sprintf(portstr, "%u", port);
+
+	error = getaddrinfo(host, portstr, &hints, &res);
+	if (error) {
+		memset(ep->error, 0, sizeof (ep->error));
+		strncpy(ep->error, gai_strerrorA(error), sizeof (ep->error) - 1);
+		return -1;
+	}
+
+	memcpy(&ep->addr, res->ai_addr, res->ai_addrlen);
+	ep->addrlen = res->ai_addrlen;
+
+	freeaddrinfo(res);
+
+	return 0;
+}
+
+#if !defined(_WIN32)
+
+void
+nsock_addr_unix(struct nsock_address *ep, const char *path)
+{
+	struct sockaddr_un *ptr= (struct sockaddr_un *)&ep->addr;
+
+	/* Path */
+	memset(ptr, 0, sizeof (struct sockaddr_un));
+	strncpy(ptr->sun_path, path, sizeof (ptr->sun_path) - 1);
+	ptr->sun_family = AF_UNIX;
+
+	/* Len is computed with SUN_LEN */
+	ep->addrlen = SUN_LEN(ptr);
+}
+
+#endif
+
+struct sockaddr *
+nsock_addr_getaddr(struct nsock_address *ep)
+{
+	return (struct sockaddr *)&ep->addr;
+}
+
+socklen_t
+nsock_addr_getaddrlen(const struct nsock_address *ep)
+{
+	return ep->addrlen;
+}
+
+void
+nsock_addr_free(struct nsock_address *ep)
+{
+	free(ep);
+}
+
+/* --------------------------------------------------------
+ * listener functions
+ * -------------------------------------------------------- */
+
+struct nsock_listener *
+nsock_lst_new(const struct nsock *ns)
+{
+	struct nsock_listener *ls;	
+
+	if ((ls = malloc(sizeof (struct nsock_listener))) == NULL)
+		return NULL;
+
+	ls->sock = ns;	
+	TAILQ_INIT(&ls->head);
+
+	return ls;
+}
+
+const char *
+nsock_lst_error(struct nsock_listener *ls)
+{
+	if (ls == NULL)
+		return strerror(ENOMEM);
+
+	return ls->error;
+}
+
+int
+nsock_lst_push(struct nsock_listener *ls, struct nsock *ns)
+{
+	struct nsock_clt *clt;
+
+	if ((clt = nsock_clt_new(ns)) == NULL)
+		return -1;
+
+	TAILQ_INSERT_HEAD(&ls->head, clt, link);
+
+	return 0;
+}
+
+int
+nsock_lst_append(struct nsock_listener *ls, struct nsock *ns)
+{
+	struct nsock_clt *clt;
+
+	if ((clt = nsock_clt_new(ns)) == NULL)
+		return -1;
+
+	TAILQ_INSERT_TAIL(&ls->head, clt, link);
+
+	return 0;
+}
+
+size_t
+nsock_lst_count(const struct nsock_listener *ls)
+{
+	return ls->head.noclients;
+}
+
+void
+nsock_lst_remove(struct nsock_listener *ls, const struct nsock *ns)
+{
+	struct nsock_clt *clt, *tmp;
+
+	TAILQ_FOREACH_SAFE(clt, &ls->head, link, tmp) {
+		if (clt->sock == ns) {
+			TAILQ_REMOVE(&ls->head, clt, link);
+			free(clt);
+			break;
+		}
+	}
+}
+
+struct nsock *
+nsock_lst_select(struct nsock_listener *ls, long sec, long usec)
+{
+	fd_set fds;
+	struct timeval maxwait, *towait;
+	int error;
+	int fdmax;
+	struct nsock_clt *clt;
+
+	fdmax = TAILQ_FIRST(&ls->head)->sock->fd;
+
+	FD_ZERO(&fds);
+	TAILQ_FOREACH(clt, &ls->head, link) {
+		FD_SET(clt->sock->fd, &fds);
+		if ((int)clt->sock->fd > fdmax)
+			fdmax = clt->sock->fd;
+	}
+
+	maxwait.tv_sec = sec;
+	maxwait.tv_usec = usec;
+
+        // Set to NULL for infinite timeout.
+	towait = (sec == 0 && usec == 0) ? NULL : &maxwait;
+	error = select(fdmax + 1, &fds, NULL, NULL, towait);
+
+	TAILQ_FOREACH(clt, &ls->head, link)
+		if (FD_ISSET(clt->sock->fd, &fds))
+			return (struct nsock *)clt->sock;
+
+	return NULL;
+}
+
+void
+nsock_lst_map(struct nsock_listener *ls, nsock_lst_map_t map, void *data)
+{
+	const struct nsock_clt *clt;
+
+	TAILQ_FOREACH(clt, &ls->head, link)
+		map(clt->sock, data);
+}
+
+void
+nsock_lst_free(struct nsock_listener *ls)
+{
+	struct nsock_clt *clt, *tmp;
+
+	TAILQ_FOREACH_SAFE(clt, &ls->head, link, tmp)
+		free(clt);
+
+	free(ls);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C/nsock.h	Sat Nov 23 16:14:05 2013 +0100
@@ -0,0 +1,161 @@
+/*
+ * nsock.h -- portable BSD sockets wrapper
+ *
+ * Copyright (c) 2013 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _NSOCK_H_
+#define _NSOCK_H_
+
+#if !defined(NSOCK_NOINCLUDES)
+#  if defined(_WIN32)
+#    include <WinSock2.h>
+#    include <WS2tcpip.h>
+#  else
+#    include <sys/types.h>
+#    include <sys/socket.h>
+#    include <sys/un.h>
+
+#    include <arpa/inet.h>
+
+#    include <netinet/in.h>
+
+#    include <netdb.h>
+#    include <unistd.h>
+#  endif
+#endif
+
+struct nsock;
+struct nsock_address;
+struct nsock_listener;
+
+/* --------------------------------------------------------
+ * Sockets functions
+ * -------------------------------------------------------- */
+
+void
+nsock_init(void);
+
+struct nsock *
+nsock_new(void);
+
+int
+nsock_create(struct nsock *, int, int, int);
+
+const char *
+nsock_error(struct nsock *);
+
+int
+nsock_bind(struct nsock *, const struct nsock_address *);
+
+int
+nsock_listen(struct nsock *, int);
+
+int
+nsock_accept(struct nsock *, struct nsock **, struct nsock_address **);
+
+int
+nsock_connect(struct nsock *, const struct nsock_address *);
+
+int
+nsock_set(struct nsock *, int, int, const void *, unsigned);
+
+long
+nsock_recv(struct nsock *, void *, size_t, int);
+
+long
+nsock_recvfrom(struct nsock *, struct nsock_address *, void *, size_t, int);
+
+long
+nsock_send(struct nsock *, const void *, size_t, int);
+
+long
+nsock_sendto(struct nsock *, const struct nsock_address *, const void *, size_t, int);
+
+void
+nsock_close(struct nsock *);
+
+void
+nsock_free(struct nsock *);
+
+void
+nsock_finish(void);
+
+/* --------------------------------------------------------
+ * End point functions
+ * -------------------------------------------------------- */
+
+struct nsock_address *
+nsock_addr_new(void);
+
+const char *
+nsock_addr_error(struct nsock_address *);
+
+int
+nsock_addr_bind_ip(struct nsock_address *, const char *, unsigned, int);
+
+int
+nsock_addr_connect_ip(struct nsock_address *, const char *, unsigned, int);
+
+#if !defined(_WIN32)
+
+void
+nsock_addr_unix(struct nsock_address *, const char *);
+
+#endif
+
+struct sockaddr *
+nsock_addr_getaddr(struct nsock_address *);
+
+socklen_t
+nsock_addr_getaddrlen(const struct nsock_address *);
+
+void
+nsock_addr_free(struct nsock_address *);
+
+/* --------------------------------------------------------
+ * listener functions
+ * -------------------------------------------------------- */
+
+typedef void (*nsock_lst_map_t)(const struct nsock *, void *);
+
+struct nsock_listener *
+nsock_lst_new(const struct nsock *);
+
+const char *
+nsock_lst_error(struct nsock_listener *);
+
+int
+nsock_lst_push(struct nsock_listener *, struct nsock *);
+
+int
+nsock_lst_append(struct nsock_listener *, struct nsock *);
+
+size_t
+nsock_lst_count(const struct nsock_listener *);
+
+void
+nsock_lst_remove(struct nsock_listener *, const struct nsock *);
+
+struct nsock *
+nsock_lst_select(struct nsock_listener *, long, long);
+
+void
+nsock_lst_map(struct nsock_listener *, nsock_lst_map_t, void *);
+
+void
+nsock_lst_free(struct nsock_listener *);
+
+#endif /* !_NSOCK_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C/pack.c	Sat Nov 23 16:14:05 2013 +0100
@@ -0,0 +1,477 @@
+/*
+ * pack.c -- endian dependant binary file reader
+ *
+ * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "pack.h"
+
+/* Compilation tunables */
+#if !defined(PACK_CHKSIZE)
+#  define PACK_CHKSIZE	(256)		/* default chunk size */
+#endif
+
+/* Type */
+enum pack_type {
+	TYPE_FP,
+	TYPE_FIXEDBUF,
+	TYPE_AUTOBUF
+};
+
+struct pack_sc {
+	enum pack_type	type;		/* which kind of work */
+	short		endian;		/* endian */
+
+	/* if TYPE_FP */
+	FILE *		fp;		/* file to write */
+
+	/* else */
+	char *		buf;		/* bytes converted */
+	size_t		size;		/* current length */
+	size_t		allocated;	/* allocated size */
+
+	/* for reading */
+	unsigned int	position;	/* position where to read */
+};
+
+struct pack_value {
+	/* for writing */
+	int		nelem;		/* number of element */
+	int		size;		/* size of elements */
+	uint64_t	value;		/* direct value */
+	char *		array;		/* array of values */
+
+	/* for reading */
+	char *		dst;		/* destination */
+};
+
+#define SC_SET(s, tp, ed, f, b, al) do {				\
+	memset((s), 0, sizeof (struct pack_sc));			\
+	(s)->type	= tp;						\
+	(s)->endian	= ed;						\
+	(s)->fp		= f;						\
+	(s)->buf	= b;						\
+	(s)->allocated	= al;						\
+} while (/* CONSTCOND */ 0)
+
+#define TOKNARG(tok, nelem) do {					\
+	if (p[1] == '[') {						\
+		char *end;						\
+									\
+		/* Can statically write the number, or pass it */	\
+		if (p[2] != ']') {					\
+			nelem = (int)strtol(&p[2], &end, 10);		\
+			p = end;					\
+		} else {						\
+			nelem = va_arg(ap, int);			\
+			while (!isspace(*p) && *p != ']' && *p != '\0')	\
+				++p;					\
+		}							\
+	} else								\
+		nelem = 1;						\
+} while (/* CONSTCOND */ 0)
+
+#define TOKSIZE(tok, size) do {						\
+	switch (tok) {							\
+	case 'c':							\
+		size = sizeof (uint8_t);				\
+		break;							\
+	case 's':							\
+		size = sizeof (uint16_t);				\
+		break;							\
+	case 'i':							\
+		size = sizeof (uint32_t);				\
+		break;							\
+	case 'l':							\
+		size = sizeof (uint64_t);				\
+		break;							\
+	default:							\
+		size = 0;						\
+		break;							\
+	}								\
+} while (/* CONSTCOND */ 0)
+
+#define TOKGETARG(serv, tok, val, ap) do {				\
+	if ((val)->nelem == 1 && serv == writeto) {			\
+		uint64_t item;						\
+		switch (tok) {						\
+		case 'c': case 's': case 'i':				\
+			item = va_arg(ap, int);				\
+			break;						\
+		case 'l':						\
+			item = va_arg(ap, uint64_t);			\
+			break;						\
+		default:						\
+			item = 0;					\
+			break;						\
+		}							\
+									\
+		memset(&(val)->value, 0, sizeof (uint64_t));		\
+		memcpy(&(val)->value, &item, (val)->size);		\
+		(val)->array = (char *)&(val)->value;			\
+	} else { /* read is always a pointer */				\
+		(val)->array = va_arg(ap, void *);			\
+		(val)->dst = (val)->array;				\
+	}								\
+} while (/* CONSTCOND */ 0)
+
+#define GETCONV(ed, size, conv) do {					\
+	if (ed != PACK_HOST_BYTEORDER) {				\
+		switch ((size)) {					\
+		case (sizeof (uint16_t)):				\
+			conv = conv16; break;				\
+		case (sizeof (uint32_t)):				\
+			conv = conv32; break;				\
+		case (sizeof (uint64_t)):				\
+			conv = conv64; break;				\
+		default:						\
+			conv = NULL;					\
+		}							\
+	} else								\
+		conv = NULL;						\
+} while (/* CONSTCOND */ 0)
+
+static void
+conv16(void *item)
+{
+	*(uint16_t *)item = pack_swap16(*(uint16_t *)item);
+}
+
+static void
+conv32(void *item)
+{
+	*(uint32_t *)item = pack_swap32(*(uint32_t *)item);
+}
+
+static void
+conv64(void *item)
+{
+	*(uint64_t *)item = pack_swap64(*(uint64_t *)item);
+}
+
+/*
+ * Function that write content into the buffer or file depending
+ * on the calling function. Returns the number of bytes written
+ * or -1 on failure.
+ */
+static long
+writeto(struct pack_sc *sc, struct pack_value *val)
+{
+	void (*conv)(void *);
+	int i;
+	uint64_t item;
+	long nbytes = 0;
+
+	/* Get converter */
+	GETCONV(sc->endian, val->size, conv);
+
+	for (i = 0; i < val->nelem; ++i) {
+		item = 0;
+		memcpy(&item, &val->array[i * val->size], val->size);
+
+		if (conv != NULL)
+			conv(&item);
+
+		switch (sc->type) {
+		case TYPE_FP:
+			fwrite(&item, val->size, 1, sc->fp);
+			break;
+		case TYPE_AUTOBUF:
+			if (sc->size + val->size >= sc->allocated) {
+				sc->allocated += PACK_CHKSIZE;
+				sc->buf = realloc(sc->buf, sc->allocated);
+
+				if (sc->buf == NULL)
+					return -1;
+			}
+			/* FALLTHROUGH */
+		case TYPE_FIXEDBUF:
+			if (sc->size + val->size <= sc->allocated) {
+				memcpy(&sc->buf[sc->size], &item, val->size);
+				sc->size += val->size;
+			} else
+				continue;
+		default:
+			break;
+		}
+
+		nbytes += val->size;
+	}
+
+	return nbytes;
+}
+
+/*
+ * Function that read the file or buffer and fill array.
+ */
+static long
+readfrom(struct pack_sc *sc, struct pack_value *val)
+{
+	void (*conv)(void *);
+	int i, oktoread;
+	uint64_t item;
+	long nbytes = 0;
+
+	/* Get converter */
+	GETCONV(sc->endian, val->size, conv);
+
+	for (i = 0; i < val->nelem; ++i) {
+		item = oktoread = 0;
+
+		switch (sc->type) {
+		case TYPE_FP:
+			fread(&item, val->size, 1, sc->fp);
+			oktoread = 1;
+			break;
+		case TYPE_FIXEDBUF:
+			if (sc->position + val->size <= sc->allocated) {
+				memcpy(&item, &sc->buf[sc->position], val->size);
+				sc->position += val->size;
+				oktoread = 1;
+			}
+			break;
+		default:
+			break;
+		}
+
+		if (conv != NULL)
+			conv(&item);
+
+		if (oktoread) {
+			memcpy(&val->dst[i * val->size], &item, val->size);
+			nbytes += val->size;
+		}
+	}
+
+	return nbytes;
+}
+
+/*
+ * Function that analyses the format, write or read the values depending
+ * on the calling functions.
+ */
+static long
+packit(struct pack_sc *sc, long (*func)(struct pack_sc *, struct pack_value *),
+       const char *fmt, va_list ap)
+{
+	struct pack_value val;
+	const char *p;
+	int tok;
+	long nbytes = 0, rv;
+
+	for (p = fmt; *p != '\0'; ++p) {
+		tok = *p;
+
+		if (isspace(*p))
+			continue;
+
+		TOKNARG(tok, val.nelem);
+		TOKSIZE(tok, val.size);
+
+		if (val.size == 0 || val.nelem == 0)
+			continue;
+
+		TOKGETARG(func, tok, &val, ap);
+		if ((rv = func(sc, &val)) == -1)
+			return -1;
+
+		nbytes += rv;
+	}
+
+	return nbytes;
+}
+
+long
+pack_write(short ed, const char *path, const char *fmt, ...)
+{
+	va_list ap;
+	long rv;
+
+	va_start(ap, fmt);
+	rv = pack_vwrite(ed, path, fmt, ap);
+	va_end(ap);
+
+	return rv;
+}
+
+long
+pack_vwrite(short ed, const char *path, const char *fmt, va_list ap)
+{
+	FILE *fp;
+	long rv;
+
+	if ((fp = fopen(path, "wb")) == NULL)
+		return -1;
+
+	rv = pack_vfwrite(ed, fp, fmt, ap);
+	fclose(fp);
+
+	return rv;
+}
+
+long
+pack_fwrite(short ed, FILE *fp, const char *fmt, ...)
+{
+	va_list ap;
+	long rv;
+
+	va_start(ap, fmt);
+	rv = pack_vfwrite(ed, fp, fmt, ap);
+	va_end(ap);
+
+	return rv;
+}
+
+long
+pack_vfwrite(short ed, FILE *fp, const char *fmt, va_list ap)
+{
+	struct pack_sc sc;
+
+	SC_SET(&sc, TYPE_FP, ed, fp, NULL, 0);
+
+	return packit(&sc, writeto, fmt, ap);
+}
+
+long
+pack_swrite(short ed, char *buf, size_t max, const char *fmt, ...)
+{
+	va_list ap;	
+	long rv;
+
+	va_start(ap, fmt);
+	rv = pack_vswrite(ed, buf, max, fmt, ap);
+	va_end(ap);
+
+	return rv;
+}
+
+long
+pack_vswrite(short ed, char *buf, size_t max, const char *fmt, va_list ap)
+{
+	struct pack_sc sc;
+
+	SC_SET(&sc, TYPE_FIXEDBUF, ed, NULL, buf, max);
+
+	return packit(&sc, writeto, fmt, ap);
+}
+
+long
+pack_aswrite(short ed, char **bufp, const char *fmt, ...)
+{
+	va_list ap;	
+	long rv;
+
+	va_start(ap, fmt);
+	rv = pack_vaswrite(ed, bufp, fmt, ap);
+	va_end(ap);
+
+	return rv;
+}
+
+long
+pack_vaswrite(short ed, char **bufp, const char *fmt, va_list ap)
+{
+	struct pack_sc sc;
+	int rv;
+
+	SC_SET(&sc, TYPE_AUTOBUF, ed, NULL, NULL, PACK_CHKSIZE);
+
+	if ((sc.buf = malloc(PACK_CHKSIZE)) == NULL)
+		return -1;
+
+	rv = packit(&sc, writeto, fmt, ap);
+	*bufp = sc.buf;
+
+	return rv;
+}
+
+long
+pack_read(short ed, const char *path, const char *fmt, ...)
+{
+	va_list ap;
+	long rv;
+
+	va_start(ap, fmt);
+	rv = pack_vread(ed, path, fmt, ap);
+	va_end(ap);
+
+	return rv;
+}
+
+long
+pack_vread(short ed, const char *path, const char *fmt, va_list ap)
+{
+	FILE *fp;
+	long rv;
+
+	if ((fp = fopen(path, "rb")) == NULL)
+		return -1;
+
+	rv = pack_vfread(ed, fp, fmt, ap);
+	fclose(fp);
+
+	return rv;
+}
+
+long
+pack_fread(short ed, FILE *fp, const char *fmt, ...)
+{
+	va_list ap;
+	long rv;
+
+	va_start(ap, fmt);
+	rv = pack_vfread(ed, fp, fmt, ap);
+	va_end(ap);
+
+	return rv;
+}
+
+long
+pack_vfread(short ed, FILE *fp, const char *fmt, va_list ap)
+{
+	struct pack_sc sc;
+
+	SC_SET(&sc, TYPE_FP, ed, fp, NULL, 0);
+
+	return packit(&sc, readfrom, fmt, ap);
+}
+
+long
+pack_sread(short ed, const char *buf, size_t max, const char *fmt, ...)
+{
+	va_list ap;	
+	long rv;
+
+	va_start(ap, fmt);
+	rv = pack_vsread(ed, buf, max, fmt, ap);
+	va_end(ap);
+
+	return rv;
+}
+
+long
+pack_vsread(short ed, const char *buf, size_t max, const char *fmt, va_list ap)
+{
+	struct pack_sc sc;
+
+	SC_SET(&sc, TYPE_FIXEDBUF, ed, NULL, (char *)buf, max);
+
+	return packit(&sc, readfrom, fmt, ap);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C/pack.h	Sat Nov 23 16:14:05 2013 +0100
@@ -0,0 +1,80 @@
+/*
+ * pack.h -- endian dependant binary file reader
+ *
+ * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _PACK_H_
+#define _PACK_H_
+
+#include <stdarg.h>
+#include <stdint.h>
+
+#define PACK_LE		1234
+#define PACK_BE		4321
+
+/*
+ * Endian detection based on SDL_endian.h
+ */
+
+#undef PACK_HOST_BYTEORDER
+
+#if defined(__hppa__) ||						\
+    defined(__m68k__) || defined(mc68000) || defined(_M_M68K) ||	\
+    (defined(__MIPS__) && defined(__MISPEB__)) ||			\
+    defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) ||	\
+    defined(__sparc__)
+#  define PACK_HOST_BYTEORDER	PACK_BE
+#else
+#  define PACK_HOST_BYTEORDER	PACK_LE
+#endif
+
+#define pack_swap16(x)							\
+	((((x) >> 8) & 0x00FFL) | (((x) << 8) & 0xFF00L))
+
+#define pack_swap32(x) ((((x) >> 24) & 0x000000FFL)			\
+	| (((x) >> 8)  & 0x0000FF00L)					\
+	| (((x) << 8)  & 0x00FF0000L)					\
+	| (((x) << 24) & 0xFF000000L))
+
+#define pack_swap64(x) (((long)					\
+	((int) pack_swap32((int) (((x) << 32) >> 32))) << 32)	\
+	    | (int) pack_swap32((int) ((x) >> 32)))
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+long	pack_write(short, const char *, const char *, ...);
+long	pack_vwrite(short, const char *, const char *, va_list);
+long	pack_fwrite(short, FILE *, const char *, ...);
+long	pack_vfwrite(short, FILE *, const char *, va_list);
+long	pack_swrite(short, char *, size_t, const char *, ...);
+long	pack_vswrite(short, char *, size_t, const char *, va_list);
+long	pack_aswrite(short, char **, const char *, ...);
+long	pack_vaswrite(short, char **, const char *, va_list);
+
+long	pack_read(short, const char *, const char *, ...);
+long	pack_vread(short, const char *, const char *, va_list);
+long	pack_fread(short, FILE *, const char *, ...);
+long	pack_vfread(short, FILE *, const char *, va_list);
+long	pack_sread(short, const char *, size_t, const char *, ...);
+long	pack_vsread(short, const char *, size_t, const char *, va_list);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PACK_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C/parray.c	Sat Nov 23 16:14:05 2013 +0100
@@ -0,0 +1,366 @@
+/*
+ * parray.c -- manipulate dynamic pointer arrays
+ *
+ * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "parray.h"
+
+#define LENGTH(x)	((x) * (sizeof (void *)))
+
+static int		grow(struct parray *);
+
+int
+parray_init(struct parray *arr)
+{
+	/* Set defaults if needed */
+	arr->bsize	= (arr->bsize <= 0) ? PARRAY_DEFAULT_BSIZE : arr->bsize;
+	arr->malloc	= (arr->malloc == NULL) ? &malloc : arr->malloc;
+	arr->realloc	= (arr->realloc == NULL) ? &realloc : arr->realloc;
+
+	arr->bsize	+= (arr->flags & PARRAY_NULLEND) ? 1 : 0;
+	arr->size	= LENGTH(arr->bsize);
+
+	if ((arr->data = arr->malloc(arr->size)) == NULL)
+		return -1;
+
+	memset(arr->data, 0, arr->size);
+
+	return 0;
+}
+
+/*
+ * Valid options that can be set for an array :
+ * l -> optional array block size of type int
+ * m -> malloc function that must matches void * (*malloc)(size_t)
+ * r -> realloc function that must matches void * (*realloc)(void *, size_t)
+ * f -> parray flags of type int
+ */
+void
+parray_set(struct parray *arr, const char *fmt, ...)
+{
+	va_list ap;
+	const char *p;
+
+	va_start(ap, fmt);
+	for (p = fmt; *p != '\0'; ++p)
+		switch (*p) {
+		case 'l':
+			arr->bsize = va_arg(ap, int);
+			break;
+		case 'm':
+			arr->malloc = va_arg(ap, void * (*)(size_t));
+			break;
+		case 'r':
+			arr->realloc = va_arg(ap, void * (*)(void *, size_t));
+			break;
+		case 'f':
+			arr->flags = va_arg(ap, int);
+			break;
+		default:
+			break;
+		}
+}
+
+/*
+ * Add to the head of array. NOTE: this may be very slow when adding a lot
+ * of object (about 100000). If you need to add a lot of data please consider
+ * using linked list instead. Returns -1 on failure or 0 on success.
+ */
+int
+parray_push(struct parray *arr, void *data)
+{
+	if (grow(arr) < 0)
+		return -1;
+
+	memmove(&arr->data[1], &arr->data[0], LENGTH(arr->length++));
+	arr->data[0] = data;
+
+	if (arr->flags & PARRAY_NULLEND)
+		arr->data[arr->length] = NULL;
+
+	return 0;
+}
+
+/*
+ * Insert the data at the specified index. The function returns -1 on
+ * allocation failure or the position of the added element.
+ */
+int
+parray_insert(struct parray *arr, void *data, int index)
+{
+	if (arr->flags & PARRAY_INSERTSAFE)
+		if (index < 0 || index > arr->length)
+			return -1;
+
+	if (index < 0)
+		return parray_push(arr, data);
+	if (index >= arr->length)
+		return parray_append(arr, data);
+
+	/* Good place */
+	memmove(&arr->data[index + 1], &arr->data[index],
+		LENGTH(arr->length++ - index));
+	arr->data[index] = data;
+
+	if (arr->flags & PARRAY_NULLEND)
+		arr->data[arr->length] = NULL;
+
+	return index;
+}
+
+/*
+ * Append the data to the end of array. Returns -1 on failure or the position
+ * of the added element.
+ */
+int
+parray_append(struct parray *arr, void *data)
+{
+	if (grow(arr) < 0)
+		return -1;
+
+	arr->data[arr->length++] = data;
+
+	if (arr->flags & PARRAY_NULLEND)
+		arr->data[arr->length] = NULL;
+
+	return (arr->length - 1);
+}
+
+/*
+ * Remove the array's head.
+ */
+void
+parray_pop(struct parray *arr)
+{
+	parray_iremove(arr, 0);
+}
+
+/*
+ * Remove the array's tail.
+ */
+void
+parray_unqueue(struct parray *arr)
+{
+	parray_iremove(arr, arr->length - 1);
+}
+
+/*
+ * Remove the data at the specified index. Bounds are checked.
+ */
+void
+parray_iremove(struct parray *arr, int index)
+{
+	if (arr->length > 0 && index >= 0 && index < arr->length) {
+		if (arr->flags & PARRAY_FASTREMOVE)
+			arr->data[index] = arr->data[--arr->length];
+		else
+			memmove(&arr->data[index], &arr->data[index + 1],
+			    LENGTH(arr->length-- - index - 1));
+	}
+
+	arr->data[arr->length] = NULL;
+}
+
+/*
+ * Remove the object referenced by the `data' argument. Useful when you
+ * don't know the index.
+ */
+void
+parray_premove(struct parray *arr, const void *data)
+{
+	void *elm;
+	int i;
+
+	PARRAY_FOREACH(arr, elm, i) {
+		if (elm == data) {
+			parray_iremove(arr, i);
+			break;
+		}
+	}
+}
+
+/*
+ * Swap the two elements referenced by index `i1' and `i2'. This function needs
+ * to allocate data to swap elements thus if the functions fails it returns -1
+ * otherwise 0 is returned.
+ */
+int
+parray_iswap(struct parray *arr, int i1, int i2)
+{
+	void *tmp;
+
+	/* Out of bounds */
+	if (i1 >= arr->length || i1 < 0 || i2 >= arr->length || i2 < 0)
+		return -1;
+
+	tmp = arr->data[i1];
+	arr->data[i1] = arr->data[i2];
+	arr->data[i2] = tmp;
+
+	return 0;
+}
+
+/*
+ * Swap the two elements referenced by data `o1' and `o2'. This function
+ * may be slow on large arrays since it must travel all the object
+ * to find the indexes.
+ */
+int
+parray_pswap(struct parray *arr, const void *o1, const void *o2)
+{
+	int found, i1, i2;
+
+	for (i1 = found = 0; !found && i1 < arr->length; ++i1)
+		found = arr->data[i1] == o1;
+
+	if (!found)
+		return -1;
+
+	for (i2 = found = 0; !found && i2 < arr->length; ++i2)
+		found = arr->data[i2] == o2;
+
+	if (!found)
+		return -1;
+
+	return parray_iswap(arr, --i1, --i2);
+}
+
+/*
+ * Apply the function `fn' on each object and give the optional `udata'
+ * argument to the function too.
+ */
+void
+parray_map(const struct parray *arr, parray_map_t fn, void *udata)
+{
+	int i;
+
+	for (i = 0; i < arr->length; ++i)
+		fn(arr->data[i], udata);
+}
+
+/*
+ * Compare each object with the user supplied function. If the `fn' function
+ * returns 1 then the index of the data position is returned and the parameter
+ * data points to the array data at the correct index. If the comparison
+ * function nevers returns 1, array_find returns -1.
+ */
+int
+parray_find(const struct parray *arr, parray_cmp_t fn, void *ptr, void *u)
+{
+	int st, i;
+
+	for (i = st = 0; i < arr->length && st != 1; ++i)
+		st = fn(arr->data[i], u);
+
+	if (st && ptr)
+		*(void **)ptr = arr->data[i - 1];
+
+	return (st) ? i - 1 : -1;
+}
+
+void *
+parray_first(const struct parray *arr)
+{
+	return arr->data[0];
+}
+
+void *
+parray_get(const struct parray *arr, int idx)
+{
+	if (idx < 0)
+		return parray_first(arr);
+	if (idx >= arr->length)
+		return parray_last(arr);
+
+	return arr->data[idx];
+}
+
+void *
+parray_last(const struct parray *arr)
+{
+	if (arr->length == 0)
+		return parray_first(arr);
+
+	return arr->data[arr->length - 1];
+}
+
+/*
+ * Reset the array by setting each pointer to NULL and the length to 0.
+ */
+void
+parray_clear(struct parray *arr)
+{
+	arr->data[0]	= NULL;
+	arr->length	= 0;
+}
+
+/*
+ * Same as parray_clear except it also free the array object.
+ */
+void
+parray_free(struct parray *arr)
+{
+	parray_clear(arr);
+	free(arr->data);
+
+	arr->data	= NULL;
+	arr->size	= 0;
+}
+
+/*
+ * Trim down the array to the correct size.
+ */
+void *
+parray_trim(struct parray *arr)
+{
+	int count = arr->length;
+
+	if (arr->flags & PARRAY_NULLEND)
+		++ count;
+
+	return arr->realloc(arr->data, count * sizeof (void *));
+}
+
+/*
+ * Increate the array storage when it is full. If the buffer is fixed size
+ * it returns -1 on full buffer otherwise 0 is returned if allocation
+ * succeeded.
+ */
+static int
+grow(struct parray *arr)
+{
+	unsigned int toadd = (arr->flags & PARRAY_NULLEND) ? 2 : 1;
+
+	if ((arr->size / sizeof (void *)) - arr->length >= toadd)
+		return 0;
+
+	if (!(arr->flags & PARRAY_FIXED)) {
+		if ((arr->data = arr->realloc(arr->data, arr->size +
+		    LENGTH(arr->bsize))) == NULL) {
+			arr->size = arr->length = 0;
+			return -1;
+		}
+
+		arr->size += LENGTH(arr->bsize);
+	} else
+		return -1;
+
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C/parray.h	Sat Nov 23 16:14:05 2013 +0100
@@ -0,0 +1,121 @@
+/*
+ * parray.h -- manipulate dynamic pointer arrays
+ *
+ * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _PARRAY_H_
+#define _PARRAY_H_
+
+#include <stdarg.h>
+
+#ifndef PARRAY_DEFAULT_BSIZE
+#define PARRAY_DEFAULT_BSIZE	128
+#endif
+
+enum parray_flags {
+	PARRAY_AUTO		= 0,		/* array grows automatically */
+	PARRAY_FIXED		= (1 << 0),	/* fixed size length */
+	PARRAY_FASTREMOVE	= (1 << 1),	/* use last object when removing */
+	PARRAY_NULLEND		= (1 << 2),	/* always has a NULL pointer at end */
+	PARRAY_INSERTSAFE	= (1 << 3)	/* insertion must have valid indexes */
+};
+
+struct parray {
+	enum parray_flags	flags;		/* (ro) array flags (default AUTO) */
+	void			**data;		/* (rw) array of data */
+	int			length;		/* (ro) number of element inside */
+	size_t			size;		/* (ro) current buffer size (allocated memory) */
+	int			bsize;		/* (rw) block size (used when growing array) */
+
+	/* Own allocation functions */
+	void * (*malloc)(size_t);
+	void * (*realloc)(void *, size_t);
+};
+
+typedef void (*parray_map_t)(void *, void *);
+typedef int (*parray_cmp_t)(void *, void *);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int
+parray_init(struct parray *);
+
+void
+parray_set(struct parray *, const char *, ...);
+
+int
+parray_push(struct parray *, void *);
+
+int
+parray_insert(struct parray *, void *, int);
+
+int
+parray_append(struct parray *, void *);
+
+void
+parray_pop(struct parray *);
+
+void
+parray_unqueue(struct parray *);
+
+void
+parray_iremove(struct parray *, int);
+
+void
+parray_premove(struct parray *, const void *);
+
+int
+parray_iswap(struct parray *, int, int);
+
+int
+parray_pswap(struct parray *, const void *, const void *);
+
+void
+parray_map(const struct parray *, parray_map_t, void *);
+
+int
+parray_find(const struct parray *, parray_cmp_t, void *, void *);
+
+void *
+parray_first(const struct parray *);
+
+void *
+parray_get(const struct parray *, int);
+
+void *
+parray_last(const struct parray *);
+
+void
+parray_clear(struct parray *);
+
+void
+parray_free(struct parray *);
+
+void *
+parray_trim(struct parray *);
+
+#define PARRAY_FOREACH(a, o, i)						\
+	for (i = 0, o = (a)->data[i];					\
+	    i < (a)->length;						\
+	    ++i, o = (a)->data[i])
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PARRAY_H_ */
--- a/array.c	Fri Nov 15 21:37:57 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,382 +0,0 @@
-/*
- * array.c -- manipulate dynamic arrays
- *
- * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "array.h"
-
-#define OFFSET(x)	(arr->unit * (x))
-
-static int		grow(struct array *);
-
-int
-array_init(struct array *arr, size_t unit)
-{
-	if (unit == 0)
-		return -1;
-
-	arr->unit	= unit;
-	arr->size	= OFFSET(arr->chksize);
-
-	/* Set defaults if needed */
-	arr->chksize	= (arr->chksize <= 0) ? ARRAY_DEFAULT_CHKSIZE : arr->chksize;
-	arr->malloc	= (arr->malloc == NULL) ? &malloc : arr->malloc;
-	arr->realloc	= (arr->realloc == NULL) ? &realloc : arr->realloc;
-
-	if ((arr->data = arr->malloc(arr->size)) == NULL)
-		return -1;
-
-	if (arr->flags & ARRAY_CLEARBITS)
-		memset(arr->data, 0, arr->size);
-
-	return 0;
-}
-
-/*
- * Valid options that can be set for an array :
- * l -> optional array block size of type int
- * m -> malloc function that must matches void * (*malloc)(size_t)
- * r -> realloc function that must matches void * (*realloc)(void *, size_t)
- * f -> array flags of type int
- */
-void
-array_set(struct array *arr, const char *fmt, ...)
-{
-	va_list ap;
-	const char *p;
-
-	va_start(ap, fmt);
-	for (p = fmt; *p != '\0'; ++p)
-		switch (*p) {
-		case 'l':
-			arr->chksize = va_arg(ap, int);
-			break;
-		case 'm':
-			arr->malloc = va_arg(ap, void *(*)(size_t));
-			break;
-		case 'r':
-			arr->realloc = va_arg(ap, void *(*)(void *, size_t));
-			break;
-		case 'f':
-			arr->flags = va_arg(ap, int);
-			break;
-		default:
-			break;
-		}
-}
-
-/*
- * Add to the head of array. NOTE: this may be very slow when adding a lot
- * of object (about 100000). If you need to add a lot of data please consider
- * using linked list instead. Returns -1 on failure or 0 on success.
- */
-int
-array_push(struct array *arr, const void *data)
-{
-	if (grow(arr) < 0)
-		return -1;
-
-	memmove((char *)arr->data + arr->unit, arr->data, OFFSET(arr->length++));
-	memcpy((char *)arr->data, data, arr->unit);
-
-	return 0;
-}
-
-/*
- * Insert the data at the specified index. The function returns -1 on
- * allocation failure or the position of the added element.
- */
-int
-array_insert(struct array *arr, const void *data, int index)
-{
-	if (arr->flags & ARRAY_INSERTSAFE)
-		if (index < 0 || index > arr->length)
-			return -1;
-
-	if (index < 0)
-		return array_push(arr, data);
-	if (index >= arr->length)
-		return array_append(arr, data);
-
-	/* Good place */
-	memmove((char *)arr->data + OFFSET(index + 1),
-	    (char *)arr->data + OFFSET(index), OFFSET(arr->length++ - index));
-	memcpy((char *)arr->data + OFFSET(index), data, arr->unit);
-
-	return index;
-}
-
-/*
- * Append the data to the end of array. Returns -1 on failure or the position
- * of the added element.
- */
-int
-array_append(struct array *arr, const void *data)
-{
-	if (grow(arr) < 0)
-		return -1;
-
-	memcpy((char *)arr->data + OFFSET(arr->length++), data, arr->unit);
-
-	return (arr->length - 1);
-}
-
-/*
- * Remove the array's head.
- */
-void
-array_pop(struct array *arr)
-{
-	array_iremove(arr, 0);
-}
-
-/*
- * Remove the array's tail.
- */
-void
-array_unqueue(struct array *arr)
-{
-	array_iremove(arr, arr->length - 1);
-}
-
-/*
- * Remove the data at the specified index. Bounds are checked.
- */
-void
-array_iremove(struct array *arr, int index)
-{
-	if (arr->length > 0 && index >= 0 && index < arr->length) {
-		if (arr->flags & ARRAY_FASTREMOVE)
-			memmove((char *)arr->data + OFFSET(index),
-			    (char *)arr->data + OFFSET(--arr->length),
-			    arr->unit);
-		else
-			memmove((char *)arr->data + OFFSET(index),
-			    (char *)arr->data + OFFSET(index + 1),
-			    OFFSET(arr->length-- - index - 1));
-	}
-
-	if (arr->flags & ARRAY_CLEARBITS)
-		memset((char *)arr->data + OFFSET(arr->length), 0, arr->unit);
-}
-
-/*
- * Remove the object referenced by the `data' argument. Useful when you
- * don't know the index.
- */
-void
-array_premove(struct array *arr, const void *data)
-{
-	void *elm;
-	int i;
-
-	for (i = 0; i < arr->length; ++i) {
-		elm = (char *)arr->data + OFFSET(i);
-
-		if (memcmp(elm, data, arr->unit) == 0) {
-			array_iremove(arr, i);
-			break;
-		}
-	}
-}
-
-/*
- * Swap the two elements referenced by index `i1' and `i2'. This function needs
- * to allocate data to swap elements thus if the functions fails it returns -1
- * otherwise 0 is returned.
- */
-int
-array_iswap(struct array *arr, int i1, int i2)
-{
-	void *tmp;
-
-	/* Out of bounds */
-	if (i1 >= arr->length || i1 < 0 || i2 >= arr->length || i2 < 0)
-		return -1;
-
-	if ((tmp = arr->malloc(arr->unit)) == NULL)
-		return -1;
-
-	memcpy((char *)tmp, (char *)arr->data + OFFSET(i1), arr->unit);
-	memcpy((char *)arr->data + OFFSET(i1), (char *)arr->data + OFFSET(i2),
-	    arr->unit);
-	memcpy((char *)arr->data + OFFSET(i2), (char *)tmp, arr->unit);
-
-	/*
-	 * Clear bytes for safety you probably don't want a password or
-	 * secure data to be left somewhere in the memory.
-	 */
-
-	if (arr->flags & ARRAY_CLEARBITS)
-		memset(tmp, 0, arr->unit);
-	free(tmp);
-
-	return 0;
-}
-
-/*
- * Swap the two elements referenced by data `o1' and `o2'. This function
- * may be slow on large arrays since it must travel all the object
- * to find the indexes.
- */
-int
-array_pswap(struct array *arr, const void *o1, const void *o2)
-{
-	int found, i1, i2;
-
-	for (i1 = found = 0; !found && i1 < arr->length; ++i1)
-		found = memcmp((char *)arr->data + OFFSET(i1), o1, arr->unit) == 0;
-
-	if (!found)
-		return -1;
-
-	for (i2 = found = 0; !found && i2 < arr->length; ++i2)
-		found = memcmp((char *)arr->data + OFFSET(i2), o2, arr->unit) == 0;
-
-	if (!found)
-		return -1;
-
-	return array_iswap(arr, --i1, --i2);
-}
-
-/*
- * Apply the function `fn' on each object and give the optional `udata'
- * argument to the function too.
- */
-void
-array_map(const struct array *arr, array_map_t fn, void *udata)
-{
-	int i;
-
-	for (i = 0; i < arr->length; ++i)
-		fn((char *)arr->data + OFFSET(i), udata);
-}
-
-/*
- * Call qsort function to sort the array.
- */
-void
-array_sort(struct array *arr, array_cmp_t fn)
-{
-	qsort(arr->data, arr->length, arr->unit, fn);
-}
-
-/*
- * Compare each object with the user supplied function. If the `fn' function
- * returns 1, 1 is returned and dst points to the correct object, dst should
- * be a pointer to a pointer of object, like (int **) for a array of int.
- */
-int
-array_find(const struct array *arr, array_cmp_t fn, void *dst, void *u)
-{
-	int st, i;
-
-	for (i = st = 0; i < arr->length && st != 1; ++i)
-		st = fn((char *)arr->data + OFFSET(i), u);
-
-	if (st && dst)
-		*(char **)dst = (char *)arr->data + OFFSET(i - 1);
-
-	return (st) ? i - 1 : -1;
-}
-
-void *
-array_first(const struct array *arr)
-{
-	return arr->data;
-}
-
-void *
-array_last(const struct array *arr)
-{
-	if (arr->length == 0)
-		return array_first(arr);
-
-	return (char *)arr->data + OFFSET(arr->length - 1);
-
-}
-
-void *
-array_get(const struct array *arr, int idx)
-{
-	if (idx < 0)
-		return array_first(arr);
-	if (idx >= arr->length)
-		return array_last(arr);
-
-	return (char *)arr->data + OFFSET(idx);
-}
-
-/*
- * Erase every bytes and set the length to 0.
- */
-void
-array_clear(struct array *arr)
-{
-	memset(arr->data, 0, arr->size);
-	arr->length = 0;
-}
-
-/*
- * Same as array_clear except it also free the array object.
- */
-void
-array_free(struct array *arr)
-{
-	array_clear(arr);
-	free(arr->data);
-
-	arr->data	= NULL;
-	arr->size	= 0;
-}
-
-/*
- * Trim down the array to the correct size.
- */
-void *
-array_trim(struct array *arr)
-{
-	return arr->realloc(arr->data, arr->length * arr->unit);
-}
-
-/*
- * Increate the array storage when it is full. If the buffer is fixed size
- * it returns -1 on full buffer otherwise 0 is returned if allocation
- * succeeded.
- */
-static int
-grow(struct array *arr)
-{
-	if ((arr->size / arr->unit) > (size_t)arr->length)
-		return 0;
-
-	if (!(arr->flags & ARRAY_FIXED)) {
-		if ((arr->data = arr->realloc(arr->data, arr->size +
-		    OFFSET(arr->chksize))) == NULL) {
-			arr->size = arr->length = 0;
-			return -1;
-		}
-
-		arr->size += OFFSET(arr->chksize);
-	} else
-		return -1;
-
-	return 0;
-}
--- a/array.h	Fri Nov 15 21:37:57 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*
- * array.h -- manipulate dynamic arrays
- *
- * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _ARRAY_H_
-#define _ARRAY_H_
-
-#include <stdarg.h>
-
-#ifndef ARRAY_DEFAULT_CHKSIZE
-#define ARRAY_DEFAULT_CHKSIZE	128
-#endif
-
-enum array_flags {
-	ARRAY_AUTO		= 0,		/* array grows automatically */
-	ARRAY_FIXED		= (1 << 0),	/* fixed size length */
-	ARRAY_FASTREMOVE	= (1 << 1),	/* use last object when removing */
-	ARRAY_CLEARBITS		= (1 << 2),	/* clear data when inserting/removing */
-	ARRAY_INSERTSAFE	= (1 << 3)	/* insertion must have valid indexes */
-};
-
-struct array {
-	int			flags;		/* (ro) array flags (default AUTO) */
-	void			*data;		/* (rw) array of data */
-	int			length;		/* (ro) number of element inside */
-	size_t			size;		/* (ro) current buffer size (allocated memory) */
-	size_t			unit;		/* (ro) unit size (sizeof the object) */
-	int			chksize;	/* (rw) chunk size (used when growing array) */
-
-	/* Own allocation functions */
-	void * (*malloc)(size_t);
-	void * (*realloc)(void *, size_t);
-};
-
-typedef void	(*array_map_t)(void *, void *);
-typedef int	(*array_cmp_t)(const void *, const void *);
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int
-array_init(struct array *, size_t);
-
-void
-array_set(struct array *, const char *, ...);
-
-int
-array_push(struct array *, const void *);
-
-int
-array_insert(struct array *, const void *, int);
-
-int
-array_append(struct array *, const void *);
-
-void
-array_pop(struct array *);
-
-void
-array_unqueue(struct array *);
-
-void
-array_iremove(struct array *, int);
-
-void
-array_premove(struct array *, const void *);
-
-int
-array_iswap(struct array *, int, int);
-
-int
-array_pswap(struct array *, const void *, const void *);
-
-void
-array_map(const struct array *, array_map_t, void *);
-
-void
-array_sort(struct array *, array_cmp_t);
-
-int
-array_find(const struct array *, array_cmp_t, void *, void *);
-
-void *
-array_first(const struct array *);
-
-void *
-array_get(const struct array *, int);
-
-void *
-array_last(const struct array *);
-
-void
-array_clear(struct array *);
-
-void
-array_free(struct array *);
-
-void *
-array_trim(struct array *);
-	
-#define ARRAY_FOREACH(a, var, i)					\
-	for (i = 0, (var) = array_first((a));				\
-		i < (a)->length;					\
-		(var) = array_get(a, ++i))
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _ARRAY_H_ */
--- a/buf.c	Fri Nov 15 21:37:57 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,268 +0,0 @@
-/*
- * buf.c -- easy way to manipulate strings
- *
- * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "buf.h"
-
-#define BUF_AVAIL(buf)	((buf)->alsize - (buf)->length)
-#define BUF_SAFE(buf)	(!((buf)->flags & BUF_UNSAFE))
-#define BUF_FIXED(buf)	((buf)->flags & BUF_FIXED)
-#define BUF_AUTO(buf)	(buf->flags == 0)
-
-static void		copy(struct buf *, const void *, size_t);
-static int		grow(struct buf *, size_t);
-
-int
-buf_init(struct buf *buf, const char *txt)
-{
-	/* Set defaults if needed */
-	buf->chksize	= (buf->chksize <= 0) ? 128 : buf->chksize;
-	buf->alsize	= buf->chksize + 1;
-	buf->malloc	= (buf->malloc == NULL) ? &malloc : buf->malloc;
-	buf->realloc	= (buf->realloc == NULL) ? &realloc : buf->realloc;
-
-	if ((buf->text = buf->malloc(buf->alsize)) == NULL)
-		return -1;
-
-	if (txt != NULL)
-		buf_cat(buf, txt);
-
-	memset(buf->text, 0, buf->alsize);
-
-	return 0;
-}
-
-void
-buf_set(struct buf *buf, const char *fmt, ...)
-{
-	va_list ap;
-	const char *p;
-
-	va_start(ap, fmt);
-	for (p = fmt; *p != '\0'; ++p)
-		switch (*p) {
-		case 'l':
-			buf->chksize = va_arg(ap, int);
-			break;
-		case 'm':
-			buf->malloc = va_arg(ap, void *(*)(size_t));
-			break;
-		case 'r':
-			buf->realloc = va_arg(ap, void *(*)(void *, size_t));
-			break;
-		case 'f':
-		case 't':
-			buf->flags = va_arg(ap, int);
-			break;
-		default:
-			break;
-		}
-}
-
-/*
- * This function appends not more than max characters from str.
- */
-int
-buf_ncat(struct buf *buf, const char *str, size_t max)
-{
-	size_t tocopy = max;
-
-	for (tocopy = 0; str[tocopy] != '\0' && tocopy < max; ++tocopy)
-		continue;
-
-	if (BUF_AVAIL(buf) <= tocopy) {
-		/* Can't add more */
-		if (BUF_SAFE(buf) && BUF_FIXED(buf))
-			return -1;
-
-		if (BUF_AUTO(buf)) {
-			if (grow(buf, tocopy) < 0)
-				return -1;
-		} else {
-			/* String is unsafe, truncate to the available size */
-			tocopy = BUF_AVAIL(buf) - 1;
-		}
-	}
-
-	copy(buf, str, tocopy);
-	
-	return 0;
-}
-
-/*
- * Append the string str to the end of the string buffer.
- */
-int
-buf_cat(struct buf *buf, const char *str)
-{
-	return buf_ncat(buf, str, strlen(str));
-}
-
-/*
- * Append the caracter c to the end of buffer
- */
-int
-buf_putc(struct buf *buf, int c)
-{
-	char str[2] = { c, '\0' };
-
-	return buf_ncat(buf, str, 1);
-}
-
-/*
- * Concatenate the printf(3) like call to the string buffer, this function
- * returns -1 on fixed safe buffer, otherwise 0 is returned if there
- * is no allocation failure.
- */
-int
-buf_vprintf(struct buf *buf, const char *fmt, va_list ap)
-{
-	int copied, rv = 0, done = 0;
-
-	if (BUF_FIXED(buf) && BUF_SAFE(buf))
-		return -1;
-
-	do {
-		copied = vsnprintf(&buf->text[buf->length],
-		    BUF_AVAIL(buf), fmt, ap);
-
-		if (copied >= (signed int)BUF_AVAIL(buf) || copied == -1) {
-			if (BUF_FIXED(buf))
-				done = 1;
-
-			/*
-			 * vsnprintf returns -1 on windows, we need to grow
-			 * the buffer by block size.
-			 */
-			if (grow(buf, buf->alsize + buf->chksize) < 0) {
-				done = 1;
-				rv = -1;
-			}
-		} else {
-			done = 1;
-		}
-	} while (!done);
-
-	buf->length = strlen(buf->text);
-
-	return rv;
-}
-
-int
-buf_printf(struct buf *buf, const char *fmt, ...)
-{
-	va_list ap;
-	int rv;
-
-	va_start(ap, fmt);
-	rv = buf_vprintf(buf, fmt, ap);
-	va_end(ap);
-
-	return rv;
-}
-
-/*
- * Realloc the string to it's size and remove useless bytes.
- */
-int
-buf_trim(struct buf *buf)
-{
-	if ((buf->text = realloc(buf->text, buf->length + 1)) == NULL) {
-		buf->alsize = 0;
-		return -1;
-	}
-
-	buf->alsize = buf->length + 1;
-
-	return 0;
-}
-
-/*
- * Remove `n' characters from the buffer, a positive value will cut the string
- * from beginning, negative value will cut from end.
- */
-void
-buf_cut(struct buf *buf, int start)
-{
-	if ((start > 0 && start >= buf->length) ||
-	    (start < 0 && (int)buf->length + start < 0))
-		return;
-
-	if (start < 0 && (int)buf->length + start >= 0)
-		start = buf->length + start;
-
-	buf->text[start]	= '\0';
-	buf->length		-= buf->length - start;
-}
-
-/*
- * Clear the string buffer.
- */
-void
-buf_clear(struct buf *buf)
-{
-	memset(buf->text, 0, buf->alsize);
-
-	buf->length = 0;
-}
-
-void
-buf_free(struct buf *buf)
-{
-	if (buf != NULL) {
-		buf_clear(buf);
-		free(buf->text);
-
-		buf->text = NULL;
-		buf->alsize = 0;
-	}
-}
-
-/*
- * Append to the end of buffer the void ptr of count size.
- */
-static void
-copy(struct buf *buf, const void *ptr, size_t count)
-{
-	memcpy(buf->text + buf->length, ptr, count);
-
-	buf->text[buf->length + count] = '\0';
-	buf->length += count;
-}
-
-/*
- * Grow the text buffer until the available size fit the needed
- * size. This function may return -1 on allocation failure.
- */
-static int
-grow(struct buf *buf, size_t needed)
-{
-	while (BUF_AVAIL(buf) <= needed) {
-		buf->text = buf->realloc(buf->text, buf->alsize + buf->chksize);
-	
-		if (buf->text == NULL)
-			return -1;
-
-		buf->alsize += buf->chksize;
-	}
-
-	return 0;
-}
--- a/buf.h	Fri Nov 15 21:37:57 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * buf.h -- easy way to manipulate strings
- *
- * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _BUF_H_
-#define _BUF_H_
-
-#include <stdarg.h>
-
-#ifdef __GNUC__
-#  define _buf_at_printf(i1, i2)	__attribute__ ((format (printf, i1, i2)))
-#else
-#  define _buf_at_printf(i1, i2)
-#endif
-
-enum buf_flags {
-	BUF_UNSAFE	= (1 << 0),	/* string may be truncated */
-	BUF_FIXED	= (1 << 1),	/* string has fixed length */
-};
-
-struct buf {
-	enum buf_flags	flags;		/* string flags */
-	char		*text;		/* string text */
-	size_t		length;		/* string length */
-	size_t		alsize;		/* allocated size */
-	int		chksize;	/* chunk size */
-	int		maxsize;	/* max fixed length size */
-
-	void * (*malloc)(size_t);		/* alternate malloc */
-	void * (*realloc)(void *, size_t);	/* alternate realloc */
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int
-buf_init(struct buf *, const char *);
-
-void
-buf_set(struct buf *, const char *, ...);
-
-int
-buf_ncat(struct buf *, const char *, size_t);
-
-int
-buf_cat(struct buf *, const char *);
-
-int
-buf_putc(struct buf *, int);
-
-int
-buf_vprintf(struct buf *, const char *, va_list);
-
-int
-buf_printf(struct buf *, const char *, ...)	_buf_at_printf(2, 3);
-
-int
-buf_trim(struct buf *);
-
-void
-buf_cut(struct buf *, int);
-
-void
-buf_clear(struct buf *);
-
-void
-buf_free(struct buf *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _BUF_H_ */
--- a/directory.c	Fri Nov 15 21:37:57 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-/*
- * directory.c -- portable way to open directories
- *
- * Copyright (c) 2011, 2012 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "directory.h"
-
-#if defined(_WIN32)	/* WINDOWS */
-
-struct directory *
-directory_open(const char *path)
-{
-	WIN32_FIND_DATA fdata;
-	HANDLE h;
-	struct directory *res;
-	char respath[FILENAME_MAX + 1];
-
-	if (!(res = calloc(1, sizeof (struct directory))))
-		return NULL;
-
-	snprintf(respath, sizeof (respath), "%s/*", path);
-
-	if ((h = FindFirstFile(respath, &fdata)) == INVALID_HANDLE_VALUE) {
-		free(res);
-		return NULL;
-	}
-
-	do {
-		res->ents = realloc(res->ents,
-			        sizeof (*res->ents) * (res->nents + 1));
-
-		/* Fail to reallocate */
-		if (!res->ents) {
-			free(res);
-			res = NULL;
-			break;
-		}
-
-		res->ents[res->nents].name	= strdup(fdata.cFileName);
-		res->ents[res->nents].type	= fdata.dwFileAttributes;
-		res->ents[res->nents++].length	= strlen(fdata.cFileName);
-	} while (FindNextFile(h, &fdata) != 0);
-
-	return res;
-}
-
-const char *
-directory_error(void)
-{
-	static char msg[1024];
-	DWORD num;
-
-	num = GetLastError();
-
-	FormatMessage(
-	    FORMAT_MESSAGE_FROM_SYSTEM |
-	    FORMAT_MESSAGE_IGNORE_INSERTS,
-	    NULL,
-	    num,
-	    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-	    msg,
-	    sizeof (msg),
-	    NULL
-	);
-
-	return msg;
-}
-
-#else			/* UNIX */
-
-#  include <errno.h>
-
-struct directory *
-directory_open(const char *path)
-{
-	DIR *dp;
-	struct dirent *ent;
-	struct directory *res;
-
-	if (!(res = calloc(1, sizeof (struct directory))))
-		return NULL;
-
-	if (!(dp = opendir(path))) {
-		free(res);
-		return NULL;
-	}
-
-	while ((ent = readdir(dp))) {
-		res->ents = realloc(res->ents,
-			        sizeof (*res->ents) * (res->nents + 1));
-
-		/* Fail to reallocate */
-		if (!res->ents) {
-			free(res);
-			res = NULL;
-			break;
-		}
-
-		res->ents[res->nents].name	= strdup(ent->d_name);
-		res->ents[res->nents].type	= ent->d_type;
-		res->ents[res->nents++].length	= ent->d_namlen;
-	}
-
-	(void)closedir(dp);
-
-	return res;
-}
-
-const char *
-directory_error(void)
-{
-	return strerror(errno);
-}
-
-#endif
-
-void
-directory_free(struct directory *dir)
-{
-	int i;
-
-	for (i = 0; i < dir->nents; ++i)
-		free(dir->ents[i].name);
-
-	free(dir->ents);
-	free(dir);
-}
--- a/directory.h	Fri Nov 15 21:37:57 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * directory.h -- portable way to open directories
- *
- * Copyright (c) 2011, 2012 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _DIRECTORY_H_
-#define _DIRECTORY_H_
-
-struct directory {
-	int		nents;		/* number of entries */
-
-	struct {
-		char	*name;		/* entry name */
-		int	length;		/* length of entry */
-		int	type;		/* type of entry */
-	} *ents;
-};
-
-#if defined(_WIN32)
-
-#  include <windows.h>
-
-enum {
-	DIRECTORY_DIR	= FILE_ATTRIBUTE_DIRECTORY,
-	DIRECTORY_FILE	= FILE_ATTRIBUTE_NORMAL
-};
-
-#else
-
-#  include <dirent.h>
-
-enum {
-	DIRECTORY_DIR	= DT_DIR,
-	DIRECTORY_FILE	= DT_REG
-};
-
-#endif
-
-struct directory *
-directory_open(const char *);
-
-const char *
-directory_error(void);
-
-void
-directory_free(struct directory *);
-
-#endif /* _DIRECTORY_H_ */
--- a/ini.c	Fri Nov 15 21:37:57 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,555 +0,0 @@
-/*
- * ini.c -- parse .ini like files
- *
- * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-
-#include "ini.h"
-
-/*
- * sys/queue.h bits.
- */
-
-#if !defined(TAILQ_FIRST)
-#define	TAILQ_FIRST(head)	((head)->tqh_first)
-#endif
-
-#if !defined(TAILQ_FOREACH)
-#define	TAILQ_FOREACH(var, head, field)					\
-	for ((var) = TAILQ_FIRST((head));				\
-	    (var);							\
-	    (var) = TAILQ_NEXT((var), field))
-#endif
-
-#if !defined(TAILQ_FOREACH_SAFE)
-#define	TAILQ_FOREACH_SAFE(var, head, field, tvar)			\
-	for ((var) = TAILQ_FIRST((head));				\
-	    (var) && ((tvar) = TAILQ_NEXT((var), field), 1);		\
-	    (var) = (tvar))
-#endif
-
-#if !defined(TAILQ_INIT)
-#define	TAILQ_INIT(head) do {						\
-	TAILQ_FIRST((head)) = NULL;					\
-	(head)->tqh_last = &TAILQ_FIRST((head));			\
-} while (0)
-#endif
-
-#if !defined(TAILQ_INSERT_TAIL)
-#define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
-	TAILQ_NEXT((elm), field) = NULL;				\
-	(elm)->field.tqe_prev = (head)->tqh_last;			\
-	*(head)->tqh_last = (elm);					\
-	(head)->tqh_last = &TAILQ_NEXT((elm), field);			\
-} while (0)
-#endif
-
-#if !defined(TAILQ_NEXT)
-#define	TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
-#endif
-
-#if !defined(TAILQ_REMOVE)
-#define	TAILQ_REMOVE(head, elm, field) do {				\
-	if ((TAILQ_NEXT((elm), field)) != NULL)				\
-		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
-		    (elm)->field.tqe_prev;				\
-	else {								\
-		(head)->tqh_last = (elm)->field.tqe_prev;		\
-	}								\
-	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\
-} while (0)
-#endif
-
-/* --------------------------------------------------------
- * Structure definitions
- * -------------------------------------------------------- */
-
-struct ini_private {
-	struct ini_section	*current;	/* current working section */
-	int			ignore;		/* must ignore (no redefine) */
-	FILE			*fp;		/* file pointer to read */
-
-	/* Line buffer */
-	char			*line;		/* line data */
-	int			linesize;	/* line allocated size */
-	int			lineno;		/* number of line in file */
-
-	/* Error reporting */
-	char			error[1024];
-};
-
-/* --------------------------------------------------------
- * Prototypes
- * -------------------------------------------------------- */
-
-#define F_VERBOSE(cg)		((cg)->flags & INI_VERBOSE)
-#define F_NOREDEFINE(cg)	((cg)->flags & INI_NOREDEFINE)
-#define F_FAILERROR(cg)		((cg)->flags & INI_FAILERROR)
-
-static char *
-sstrndup(const char *src, size_t max)
-{
-	char *res;
-	size_t length;
-
-	for (length = 0; length < max && src[length] != '\0'; ++length)
-		continue;
-
-	if ((res = malloc(length + 1)) == NULL)
-		return NULL;
-
-	memcpy(res, src, length);
-	res[length] = '\0';
-
-	return res;
-}
-
-static void
-sskip(char **lp)
-{
-	while (isspace (**lp) && **lp != '\0')
-		++(*lp);
-}
-
-static void
-sseek(char **lp)
-{
-	while (!isspace(**lp) && **lp != '\0')
-		++(*lp);
-}
-
-static void
-ini_set_error(struct ini_config *cg, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	if (cg->pv->error)
-		vsnprintf(cg->pv->error, sizeof (cg->pv->error), fmt, ap);
-	va_end(ap);
-}
-
-static void
-ini_warn(struct ini_config *cg, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	if (F_VERBOSE(cg)) {
-		vprintf(fmt, ap);
-		fputc('\n', stdout);
-	}
-
-	if (F_FAILERROR(cg)) {
-		va_start(ap, fmt);
-		vsnprintf(cg->pv->error, sizeof (cg->pv->error), fmt, ap);
-		va_end(ap);
-	}
-
-	va_end(ap);
-}
-
-/*
- * Add a new section, this function only returns -1 on fatal error that may
- * be impossible to continue parsing for the current line.
- */
-
-static int
-ini_add_section(struct ini_config *cg, char **lp)
-{
-	char *begin = *lp, *end;
-	size_t length;
-	struct ini_section *section = NULL;
-
-	if (!(end = strchr(begin, ']'))) {
-		ini_warn(cg, "line %d: syntax error after [", cg->pv->lineno);
-		goto bad;
-	}
-
-	length = end - begin;
-
-	/* May not redefine? */
-	if (cg->pv->current && F_NOREDEFINE(cg))
-		if (strncmp(cg->pv->current->key, begin, length) == 0) {
-			ini_warn(cg, "line %d: redefining %s", cg->pv->lineno,
-			    cg->pv->current->key);
-			goto bad;
-		}
-
-	/* Allocate a new section and add it */
-	if (!(section = calloc(1, sizeof (*section))))
-		goto bad;
-
-	if (!(section->key = sstrndup(begin, length)))
-		goto bad;
-
-	TAILQ_INIT(&section->options);
-	TAILQ_INSERT_TAIL(&cg->sections, section, link);
-	cg->pv->current	= section;
-	cg->pv->ignore	= 0;
-
-	/* Trigger an event for the new section */
-	if (cg->open)
-		cg->open(cg->data, section->key);
-
-	*lp = &end[1];
-
-	return 0;
-
-bad:	if (section)
-		free(section->key);
-	free(section);
-
-	cg->pv->ignore = 1;
-	*lp = strchr(*lp, '\0');
-
-	return F_FAILERROR(cg) ? -1 : 0;
-}
-
-/*
- * Add a new option, the returns value is same as ini_add_section.
- */
-
-static int
-ini_add_option(struct ini_config *cg, char **lp)
-{
-	char *begin = *lp, *equal, *end;
-	struct ini_option *option = NULL;
-
-	if (!cg->pv->current) {
-		ini_warn(cg, "line %d: option within no section", cg->pv->lineno);
-		goto bad;
-	}
-
-	if (cg->pv->ignore ||
-	    !(option = calloc(1, sizeof (*option))))
-		goto bad;
-
-	/* Not valid */
-	if (!(equal = strchr(begin, '='))) {
-		ini_warn(cg, "line %d: missing =", cg->pv->lineno);
-		goto bad;
-	}
-
-	/* End of option */
-	end = begin;
-	sskip(&end);
-	sseek(&end);
-
-	option->key = sstrndup(begin, end - begin);
-
-	/* End of value */
-	begin = &equal[1];
-	sskip(&begin);
-	end = begin;
-
-	if (*end == '\'' || *end == '"') {
-		for (++end; *end != *begin && *end != '\0'; ++end)
-			continue;
-		if (*end != *begin) {
-			ini_warn(cg, "line %d: missing %c",
-			    cg->pv->lineno, *begin);
-			*lp = end;
-			goto bad;
-		} else
-			++ begin;
-	} else
-		sseek(&end);
-
-	option->value = sstrndup(begin, end - begin);
-
-	if (!option->key || !option->value) {
-		ini_warn(cg, "line %d: syntax error", cg->pv->lineno);
-		goto bad;
-	}
-
-	TAILQ_INSERT_TAIL(&cg->pv->current->options, option, link);
-
-	/* Trigger an event for the new section */
-	if (cg->get)
-		cg->get(cg->data, cg->pv->current->key, option);
-
-	*lp = &end[1];
-
-	return 0;
-
-bad:	if (option) {
-		free(option->key);
-		free(option->value);
-	}
-	free(option);
-
-	*lp = strchr(*lp, '\0');
-
-	return F_FAILERROR(cg) ? -1 : 0;
-}
-
-static int
-ini_read_line(struct ini_config *cg)
-{
-	char *lp = cg->pv->line;
-	int rv;
-
-	/* Ignore empty line */	
-	if (*lp == '\0' || *lp == '#' || *lp == ';')
-		return 0;
-
-	while (*lp != '\0') {
-		sskip(&lp);
-
-		if (*lp == '\0' || *lp == '#' || *lp == ';')
-			return 0;
-
-		/* Begin of section */
-		if (*lp == '[') {
-			++ lp;
-			rv = ini_add_section(cg, &lp);
-		/* Begin of option */
-		} else {
-			rv = ini_add_option(cg, &lp);
-		}
-
-		if (rv < 0)
-			return -1;
-	}
-
-	return 0;
-}
-
-/*
- * Read the next line until the next '\n' character is found. Returns 0
- * if the system had enough memory or -1 on allocation failure or on
- * end of file. Only for mode == INI_LINEAR
- */
-
-static int
-ini_get_line(struct ini_config *cg)
-{
-	int ch, pos;
-
-	memset(cg->pv->line, 0, cg->pv->linesize);
-	pos = 0;
-
-	while ((ch = fgetc(cg->pv->fp)) != '\n') {
-		if (feof(cg->pv->fp) || ferror(cg->pv->fp))
-			return -1;
-
-		/* End of buffer, realloc */
-		if (pos == cg->pv->linesize) {
-			cg->pv->line = realloc(cg->pv->line, cg->pv->linesize + 512);
-			if (!cg->pv->line)
-				return -1;
-
-			cg->pv->linesize += 512;
-		}
-
-		cg->pv->line[pos++] = ch;
-	}
-
-	return 0;
-}
-
-static int
-ini_open_file(struct ini_config *cg)
-{
-	if (!(cg->pv->fp = fopen(cg->path, "r"))) {
-		ini_set_error(cg, "open: %s", cg->path);
-		return -1;
-	}
-
-	cg->pv->linesize = INI_DEFAULT_LINESIZE;
-	cg->pv->line = calloc(sizeof (char), cg->pv->linesize);
-
-	if (!cg->pv->line) {
-		ini_set_error(cg, "malloc: %s", strerror(errno));
-		return -1;
-	}
-
-	return 0;
-}
-
-/* --------------------------------------------------------
- * Public functions
- * -------------------------------------------------------- */
-
-struct ini_config *
-ini_create(const char *path, enum ini_flags flags)
-{
-	struct ini_config *cg;	
-
-	cg = calloc(1, sizeof (*cg));
-	if (!cg)
-		return NULL;
-
-	cg->pv = calloc(1, sizeof (struct ini_private));
-	if (!cg->pv)
-		return NULL;
-
-	cg->path	= path;
-	cg->flags	= flags;
-
-	return cg;
-}
-
-void
-ini_set_handlers(struct ini_config *cg, void *data, ini_open_t open,
-		 ini_get_t get)
-{
-	if (!cg)
-		return;
-
-	cg->data	= data;
-	cg->open	= open;
-	cg->get		= get;
-}
-
-int
-ini_open(struct ini_config *cg)
-{
-	int rv = 0;
-
-	/* Open the file and prepare data for reading */
-	if (ini_open_file(cg) < 0)
-		return -1;
-
-	cg->pv->ignore	= 1;
-	cg->pv->lineno	= 1;
-
-	TAILQ_INIT(&cg->sections);
-
-	while (ini_get_line(cg) != -1 && !rv) {
-		rv = ini_read_line(cg);
-		++ cg->pv->lineno;
-	}
-
-	fclose(cg->pv->fp);
-
-	return rv;
-}
-
-/*
- * Search the section `sectname' in the config structure. If the section
- * is not found, this function returns NULL.
- */
-
-struct ini_section *
-ini_select_section(const struct ini_config *cg, const char *sectname)
-{
-	struct ini_section *s;
-
-	TAILQ_FOREACH(s, &cg->sections, link)
-		if (strcmp(s->key, sectname) == 0)
-			return s;
-
-	return NULL;
-}
-
-/*
- * Search the option `optname' in the section structure, argument
- * section mustn't be NULL. If the option is not found, this function
- * returns NULL.
- */
-
-struct ini_option *
-ini_select_option(const struct ini_section *sc, const char *name)
-{
-	struct ini_option *o;
-
-	TAILQ_FOREACH(o, &sc->options, link)
-		if (strcmp(o->key, name) == 0)
-			return o;
-
-	return NULL;
-}
-
-/*
- * Find an option from the config, by section and option names.
- * Returns the option or NULL if not found.
- */
-
-struct ini_option *
-ini_find(const struct ini_config *cg, const char *scname, const char *optname)
-{
-	struct ini_section *sc;
-
-	if ((sc = ini_select_section(cg, scname)))
-		return ini_select_option(sc, optname);
-
-	return NULL;
-}
-
-/*
- * Return the last error or "No error" if there is no error.
- */
-
-const char *
-ini_get_error(const struct ini_config *cg)
-{
-	if (!cg && errno != 0)
-		return strerror(errno);
-
-	if (cg->pv->error[0] == '\0') {
-		if (errno != 0)
-			return strerror(errno);
-
-		return "No error";
-	}
-
-	return cg->pv->error;
-}
-
-/*
- * Free everything, level may be set like this:
- * 0, only free parser and private resources.
- * 1, free all sections and their keys,
- * 2, free all sections and options keys and values.
- */
-
-void
-ini_free(struct ini_config *cg, int level)
-{
-	struct ini_section *s, *stmp;
-	struct ini_option *o, *otmp;
-
-	if (level >= 1) {
-		TAILQ_FOREACH_SAFE(s, &cg->sections, link, stmp) {
-			if (level >= 2) {
-				TAILQ_FOREACH_SAFE(o, &s->options, link, otmp) {
-					TAILQ_REMOVE(&s->options, o, link);
-					free(o->key);
-					free(o->value);
-					free(o);
-				}
-			}
-
-			TAILQ_REMOVE(&cg->sections, s, link);
-			free(s->key);
-			free(s);
-		}
-	}
-
-	if (level >= 0) {
-		free(cg->pv->line);
-		free(cg->pv);
-		free(cg);
-	}
-}
--- a/ini.h	Fri Nov 15 21:37:57 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/*
- * ini.h -- parse .ini like files
- *
- * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _INI_H_
-#define _INI_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if !defined(INI_DEFAULT_LINESIZE)
-#  define INI_DEFAULT_LINESIZE		1024
-#endif
-
-/*
- * sys/queue.h bits.
- */
-
-#if !defined(TAILQ_ENTRY)
-#define	TAILQ_ENTRY(type)						\
-struct {								\
-	struct type *tqe_next;	/* next element */			\
-	struct type **tqe_prev;	/* address of previous next element */	\
-}
-#endif
-
-#if !defined(TAILQ_HEAD)
-#define	TAILQ_HEAD(name, type)						\
-struct name {								\
-	struct type *tqh_first;	/* first element */			\
-	struct type **tqh_last;	/* addr of last next element */		\
-}
-#endif
-
-enum ini_flags {
-	INI_VERBOSE		= (1 << 0),	/* be verbose */
-	INI_NOREDEFINE		= (1 << 1),	/* do not allow redefinitions */
-	INI_FAILERROR		= (1 << 2)	/* abort parsing on first error */
-};
-
-typedef struct ini_config	ini_config_t;
-typedef struct ini_section	ini_section_t;
-typedef struct ini_option	ini_option_t;
-typedef struct ini_handler	ini_handler_t;
-
-typedef void (*ini_open_t)(void *, const char *);
-typedef void (*ini_get_t)(void *, const char *, const ini_option_t *);
-
-/* --------------------------------------------------------
- * Structure definitions
- * -------------------------------------------------------- */
-
-struct ini_private;
-
-struct ini_config {
-	const char		*path;		/* (ro) file path */
-	enum ini_flags		flags;		/* (ro) optional flags */
-	void			*data;		/* (rw) user data */
-
-	TAILQ_HEAD(, ini_section) sections;	/* (ro) linked-list of sections */
-
-	/* Event driven method */
-	void (*open)(void *, const char *);
-	void (*get)(void *, const char *, const struct ini_option *);
-
-	/* Private data */
-	struct ini_private	*pv;
-};
-
-struct ini_option {
-	char			*key;		/* (rw) option name */
-	char			*value;		/* (rw) option value */
-
-	TAILQ_ENTRY(ini_option)	link;
-};
-
-struct ini_section {
-	char			*key;		/* (rw) section key */	
-	TAILQ_HEAD(, ini_option) options;	/* (rw) list of options */
-
-	TAILQ_ENTRY(ini_section) link;
-};
-
-/* --------------------------------------------------------
- * Main functions
- * -------------------------------------------------------- */
-
-struct ini_config *
-ini_create(const char *, enum ini_flags);
-
-void
-ini_set_handlers(struct ini_config *, void *, ini_open_t, ini_get_t);
-
-int
-ini_open(struct ini_config *);
-
-struct ini_section *
-ini_select_section(const struct ini_config *, const char *);
-
-struct ini_option *
-ini_select_option(const struct ini_section *, const char *);
-
-struct ini_option *
-ini_find(const struct ini_config *, const char *, const char *);
-
-const char *
-ini_get_error(const struct ini_config *);
-
-void
-ini_free(struct ini_config *, int);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _INI_H_ */
--- a/nsock.c	Fri Nov 15 21:37:57 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,661 +0,0 @@
-/*
- * nsock.c -- portable BSD sockets wrapper
- *
- * Copyright (c) 2013 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#  include <stdio.h>
-#  include <stdlib.h>
-
-#if defined(_WIN32)
-
-  typedef SOCKET		nsock_socket_t;
-  typedef const char *		nsock_carg_t;
-  typedef char *		nsock_arg_t;
-
-#else
-#  include <errno.h>
-#  include <string.h>
-
-#  define ioctlsocket(s)	ioctl(s)
-#  define closesocket(s)	close(s)
-
-#  define gai_strerrorA		gai_strerror
-
-#  define INVALID_SOCKET	-1
-#  define SOCKET_ERROR		-1
-
-  typedef int			nsock_socket_t;
-  typedef const void *		nsock_carg_t;
-  typedef void *		nsock_arg_t;
-
-#endif
-
-#include "nsock.h"
-
-#define	TAILQ_HEAD(name, type)						\
-struct name {								\
-	struct type *tqh_first;	/* first element */			\
-	struct type **tqh_last;	/* addr of last next element */		\
-	size_t noclients;						\
-}
-
-#define	TAILQ_ENTRY(type)						\
-struct {								\
-	struct type *tqe_next;	/* next element */			\
-	struct type **tqe_prev;	/* address of previous next element */	\
-}
-
-#define	TAILQ_EMPTY(head)	((head)->tqh_first == NULL)
-
-#define	TAILQ_FIRST(head)	((head)->tqh_first)
-
-#define	TAILQ_FOREACH(var, head, field)					\
-	for ((var) = TAILQ_FIRST((head));				\
-	    (var);							\
-	    (var) = TAILQ_NEXT((var), field))
-
-#define	TAILQ_FOREACH_SAFE(var, head, field, tvar)			\
-	for ((var) = TAILQ_FIRST((head));				\
-	    (var) && ((tvar) = TAILQ_NEXT((var), field), 1);		\
-	    (var) = (tvar))
-
-#define	TAILQ_INIT(head) do {						\
-	TAILQ_FIRST((head)) = NULL;					\
-	(head)->tqh_last = &TAILQ_FIRST((head));			\
-} while (0)
-
-#define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
-	if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)	\
-		TAILQ_FIRST((head))->field.tqe_prev =			\
-		    &TAILQ_NEXT((elm), field);				\
-	else								\
-		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
-	TAILQ_FIRST((head)) = (elm);					\
-	(elm)->field.tqe_prev = &TAILQ_FIRST((head));			\
-	(head)->noclients ++;						\
-} while (0)
-
-#define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
-	TAILQ_NEXT((elm), field) = NULL;				\
-	(elm)->field.tqe_prev = (head)->tqh_last;			\
-	*(head)->tqh_last = (elm);					\
-	(head)->tqh_last = &TAILQ_NEXT((elm), field);			\
-	(head)->noclients ++;						\
-} while (0)
-
-#define	TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
-
-#define	TAILQ_REMOVE(head, elm, field) do {				\
-	if ((TAILQ_NEXT((elm), field)) != NULL)				\
-		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
-		    (elm)->field.tqe_prev;				\
-	else {								\
-		(head)->tqh_last = (elm)->field.tqe_prev;		\
-	}								\
-	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\
-	(head)->noclients --;						\
-} while (0)
-
-struct nsock {
-	nsock_socket_t		fd;
-	char			error[128];
-};
-
-struct nsock_address {
-	struct sockaddr_storage	addr;
-	socklen_t		addrlen;
-	char			error[128];
-};
-
-struct nsock_listener {
-	const struct nsock	*sock;
-	char			error[128];
-	TAILQ_HEAD(, nsock_clt)	head;
-};
-
-struct nsock_clt {
-	const struct nsock	*sock;
-	TAILQ_ENTRY(nsock_clt)	link;
-};
-
-/* --------------------------------------------------------
- * Private helpers
- * -------------------------------------------------------- */
-
-static void
-nsock_set_error(char *buffer, size_t bufsize)
-{
-	memset(buffer, 0, bufsize);
-
-#if defined(_WIN32)
-	LPSTR str;
-
-	FormatMessageA(
-		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
-		NULL,
-		WSAGetLastError(),
-		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-		(LPSTR)&str, 0, NULL);
-
-	if (str) {
-		strncpy(buffer, str, bufsize);
-		LocalFree(str);
-	}
-#else
-	strncpy(buffer, strerror(errno), bufsize);
-#endif
-}
-
-static void
-nsock_set_errno(char *buffer, size_t bufsize, int no)
-{
-	memset(buffer, 0, bufsize);
-	strncpy(buffer, strerror(no), bufsize - 1);
-}
-
-static struct nsock_clt *
-nsock_clt_new(const struct nsock *ns)
-{
-	struct nsock_clt *clt;
-
-	if ((clt = malloc(sizeof (struct nsock_clt))) == NULL)
-		return NULL;
-
-	clt->sock = ns;
-
-	return clt;
-}
-
-/* --------------------------------------------------------
- * Sockets functions
- * -------------------------------------------------------- */
-
-void
-nsock_init(void)
-{
-#if defined(_WIN32)
-	WSADATA wsa;
-	WSAStartup(MAKEWORD(2, 2), &wsa);
-#endif
-}
-
-struct nsock *
-nsock_new(void)
-{
-	struct nsock *ns;
-
-	if ((ns = malloc(sizeof (struct nsock))) == NULL)
-		return NULL;
-
-	return ns;
-}
-
-int
-nsock_create(struct nsock *ns, int domain, int type, int protocol)
-{
-	ns->fd = socket(domain, type, protocol);
-
-	if (ns->fd == INVALID_SOCKET)
-		nsock_set_error(ns->error, sizeof (ns->error));
-
-	return ns->fd == INVALID_SOCKET ? -1 : 0;
-}
-
-const char *
-nsock_error(struct nsock *ns)
-{
-	if (ns == NULL)
-		return strerror(ENOMEM);
-
-	return ns->error;
-}
-
-int
-nsock_bind(struct nsock *ns, const struct nsock_address *ep)
-{
-	int ret;
-
-	ret = bind(ns->fd, (const struct sockaddr *)&ep->addr, ep->addrlen);
-
-	if (ret == SOCKET_ERROR)
-		nsock_set_error(ns->error, sizeof (ns->error));
-
-	return ret == SOCKET_ERROR ? -1 : 0;
-}
-
-int
-nsock_listen(struct nsock *ns, int max)
-{
-	int ret;
-
-	ret = listen(ns->fd, max);
-
-	if (ret == SOCKET_ERROR)
-		nsock_set_error(ns->error, sizeof (ns->error));
-
-	return ret == SOCKET_ERROR ? -1 : 0;
-}
-
-int
-nsock_accept(struct nsock *ns, struct nsock **client, struct nsock_address **clientinfo)
-{
-	struct sockaddr_storage *st = NULL;
-	socklen_t *len = NULL;
-	int ret;
-
-	if ((*client = malloc(sizeof (struct nsock))) == NULL) {
-		nsock_set_errno(ns->error, sizeof (ns->error), ENOMEM);
-		return -1;
-	}
-
-	if (clientinfo != NULL) {
-		if ((*clientinfo = malloc(sizeof (struct nsock_address))) == NULL) {
-			free(client);
-			nsock_set_errno(ns->error, sizeof (ns->error), ENOMEM);
-			return -1;
-		}
-
-		st = &(*clientinfo)->addr;
-		len = &(*clientinfo)->addrlen;
-
-		/* Set the addrlen to sockaddr_storage first */
-		*len = sizeof (struct sockaddr_storage);
-	}
-
-	/* Prepare client */
-	memset((*client)->error, 0, sizeof ((*client)->error));
-	(*client)->fd = accept(ns->fd, (struct sockaddr *)st, len);
-
-	if ((*client)->fd == INVALID_SOCKET) {
-		nsock_set_error(ns->error, sizeof (ns->error));
-
-		/* free clients and set to NULL so user will not use it */
-		free(*client);
-		*client = NULL;
-
-		if (clientinfo != NULL) {
-			free(*clientinfo);
-			*clientinfo = NULL;
-		}
-
-		ret = -1;
-	} else
-		ret = 0;
-
-	return ret;
-}
-
-int
-nsock_connect(struct nsock *ns, const struct nsock_address *ep)
-{
-	int ret;
-
-	ret = connect(ns->fd, (const struct sockaddr *)&ep->addr, ep->addrlen);
-
-	if (ret == SOCKET_ERROR)
-		nsock_set_error(ns->error, sizeof (ns->error));
-
-	return ret == SOCKET_ERROR ? -1 : 0;
-}
-
-int
-nsock_set(struct nsock *ns, int level, int name, const void *arg, unsigned arglen)
-{
-	int ret;
-
-	ret = setsockopt(ns->fd, level, name, (nsock_carg_t)arg, arglen);
-
-	if (ret == SOCKET_ERROR)
-		nsock_set_error(ns->error, sizeof (ns->error));
-
-	return ret == SOCKET_ERROR ? -1 : 0;
-}
-
-long
-nsock_recv(struct nsock *ns, void *data, size_t datasz, int flags)
-{
-	long nbread;
-
-	nbread = recv(ns->fd, data, datasz, flags);
-
-	if (nbread == -1)
-		nsock_set_error(ns->error, sizeof (ns->error));
-
-	return nbread;
-}
-
-long
-nsock_recvfrom(struct nsock *ns, struct nsock_address *ep, void *data, size_t datasz, int flags)
-{
-	struct sockaddr_storage *st = NULL;
-	socklen_t *len = NULL;
-	long nbread;
-
-	if (ep != NULL) {
-		st = &ep->addr;
-		len = &ep->addrlen;
-
-		/* Set the addrlen to sockaddr_storage first */
-		*len = sizeof (struct sockaddr_storage);
-	}
-
-	nbread = recvfrom(ns->fd, data, datasz, flags,
-	    (struct sockaddr *)st, len);
-
-	if (nbread == SOCKET_ERROR)
-		nsock_set_error(ns->error, sizeof (ns->error));
-
-	return nbread;
-}
-
-long
-nsock_send(struct nsock *ns, const void *data, size_t datasz, int flags)
-{
-	long nbsent;
-
-	nbsent = send(ns->fd, data, datasz, flags);
-
-	if (nbsent == -1)
-		nsock_set_error(ns->error, sizeof (ns->error));
-
-	return nbsent;
-}
-
-long
-nsock_sendto(struct nsock *ns, const struct nsock_address *ep, const void *data, size_t datasz, int flags)
-{
-	long nbsent;
-
-	nbsent = sendto(ns->fd, data, datasz, flags,
-	    (const struct sockaddr *)&ep->addr, ep->addrlen);
-
-	if (nbsent == SOCKET_ERROR)
-		nsock_set_error(ns->error, sizeof (ns->error));
-
-	return nbsent;
-}
-
-void
-nsock_close(struct nsock *ns)
-{
-	closesocket(ns->fd);
-}
-
-void
-nsock_free(struct nsock *ns)
-{
-	free(ns);
-}
-
-void
-nsock_finish(void)
-{
-#if defined(_WIN32)
-	WSACleanup();
-#endif
-}
-
-/* --------------------------------------------------------
- * End point functions
- * -------------------------------------------------------- */
-
-struct nsock_address *
-nsock_addr_new(void)
-{
-	struct nsock_address *ep;
-
-	if ((ep = calloc(1, sizeof (struct nsock_address))) == NULL)
-		return NULL;
-
-	return ep;
-}
-
-const char *
-nsock_addr_error(struct nsock_address *ep)
-{
-	if (ep == NULL)
-		return strerror(ENOMEM);
-
-	return ep->error;
-}
-
-int
-nsock_addr_bind_ip(struct nsock_address *ep, const char *iface, unsigned port, int family)
-{
-	if (family == AF_INET6) {
-		struct sockaddr_in6 *ptr = (struct sockaddr_in6 *)&ep->addr;
-
-		memset(ptr, 0, sizeof (struct sockaddr_in6));
-		ptr->sin6_family = AF_INET6;
-		ptr->sin6_port = htons(port);
-
-		if (iface == NULL || strcmp(iface, "*") == 0)
-			ptr->sin6_addr = in6addr_any;
-		else if (inet_pton(AF_INET6, iface, &ptr->sin6_addr) <= 0) {
-			nsock_set_error(ep->error, sizeof (ep->error));
-			return -1;
-		}
-
-		ep->addrlen = sizeof (struct sockaddr_in6);
-	} else {
-		struct sockaddr_in *ptr = (struct sockaddr_in *)&ep->addr;
-
-		memset(ptr, 0, sizeof (struct sockaddr_in));
-		ptr->sin_family = AF_INET;
-		ptr->sin_port = htons(port);
-
-		if (iface == NULL || strcmp(iface, "*") == 0)
-			ptr->sin_addr.s_addr = INADDR_ANY;
-		else if (inet_pton(AF_INET, iface, &ptr->sin_addr) <= 0) {
-			nsock_set_error(ep->error, sizeof (ep->error));
-			return -1;
-		}
-
-		ep->addrlen = sizeof (struct sockaddr_in);
-	}
-	
-	return 0;
-}
-
-int
-nsock_addr_connect_ip(struct nsock_address *ep, const char *host, unsigned port, int family)
-{
-	struct addrinfo hints, *res;
-	char portstr[32];
-	int error;
-
-	memset(&hints, 0, sizeof (hints));
-	hints.ai_family = family;
-	hints.ai_socktype = SOCK_STREAM;
-
-	memset(portstr, 0, sizeof (portstr));
-	sprintf(portstr, "%u", port);
-
-	error = getaddrinfo(host, portstr, &hints, &res);
-	if (error) {
-		memset(ep->error, 0, sizeof (ep->error));
-		strncpy(ep->error, gai_strerrorA(error), sizeof (ep->error) - 1);
-		return -1;
-	}
-
-	memcpy(&ep->addr, res->ai_addr, res->ai_addrlen);
-	ep->addrlen = res->ai_addrlen;
-
-	freeaddrinfo(res);
-
-	return 0;
-}
-
-#if !defined(_WIN32)
-
-void
-nsock_addr_unix(struct nsock_address *ep, const char *path)
-{
-	struct sockaddr_un *ptr= (struct sockaddr_un *)&ep->addr;
-
-	/* Path */
-	memset(ptr, 0, sizeof (struct sockaddr_un));
-	strncpy(ptr->sun_path, path, sizeof (ptr->sun_path) - 1);
-	ptr->sun_family = AF_UNIX;
-
-	/* Len is computed with SUN_LEN */
-	ep->addrlen = SUN_LEN(ptr);
-}
-
-#endif
-
-struct sockaddr *
-nsock_addr_getaddr(struct nsock_address *ep)
-{
-	return (struct sockaddr *)&ep->addr;
-}
-
-socklen_t
-nsock_addr_getaddrlen(const struct nsock_address *ep)
-{
-	return ep->addrlen;
-}
-
-void
-nsock_addr_free(struct nsock_address *ep)
-{
-	free(ep);
-}
-
-/* --------------------------------------------------------
- * listener functions
- * -------------------------------------------------------- */
-
-struct nsock_listener *
-nsock_lst_new(const struct nsock *ns)
-{
-	struct nsock_listener *ls;	
-
-	if ((ls = malloc(sizeof (struct nsock_listener))) == NULL)
-		return NULL;
-
-	ls->sock = ns;	
-	TAILQ_INIT(&ls->head);
-
-	return ls;
-}
-
-const char *
-nsock_lst_error(struct nsock_listener *ls)
-{
-	if (ls == NULL)
-		return strerror(ENOMEM);
-
-	return ls->error;
-}
-
-int
-nsock_lst_push(struct nsock_listener *ls, struct nsock *ns)
-{
-	struct nsock_clt *clt;
-
-	if ((clt = nsock_clt_new(ns)) == NULL)
-		return -1;
-
-	TAILQ_INSERT_HEAD(&ls->head, clt, link);
-
-	return 0;
-}
-
-int
-nsock_lst_append(struct nsock_listener *ls, struct nsock *ns)
-{
-	struct nsock_clt *clt;
-
-	if ((clt = nsock_clt_new(ns)) == NULL)
-		return -1;
-
-	TAILQ_INSERT_TAIL(&ls->head, clt, link);
-
-	return 0;
-}
-
-size_t
-nsock_lst_count(const struct nsock_listener *ls)
-{
-	return ls->head.noclients;
-}
-
-void
-nsock_lst_remove(struct nsock_listener *ls, const struct nsock *ns)
-{
-	struct nsock_clt *clt, *tmp;
-
-	TAILQ_FOREACH_SAFE(clt, &ls->head, link, tmp) {
-		if (clt->sock == ns) {
-			TAILQ_REMOVE(&ls->head, clt, link);
-			free(clt);
-			break;
-		}
-	}
-}
-
-struct nsock *
-nsock_lst_select(struct nsock_listener *ls, long sec, long usec)
-{
-	fd_set fds;
-	struct timeval maxwait, *towait;
-	int error;
-	int fdmax;
-	struct nsock_clt *clt;
-
-	fdmax = TAILQ_FIRST(&ls->head)->sock->fd;
-
-	FD_ZERO(&fds);
-	TAILQ_FOREACH(clt, &ls->head, link) {
-		FD_SET(clt->sock->fd, &fds);
-		if ((int)clt->sock->fd > fdmax)
-			fdmax = clt->sock->fd;
-	}
-
-	maxwait.tv_sec = sec;
-	maxwait.tv_usec = usec;
-
-        // Set to NULL for infinite timeout.
-	towait = (sec == 0 && usec == 0) ? NULL : &maxwait;
-	error = select(fdmax + 1, &fds, NULL, NULL, towait);
-
-	TAILQ_FOREACH(clt, &ls->head, link)
-		if (FD_ISSET(clt->sock->fd, &fds))
-			return (struct nsock *)clt->sock;
-
-	return NULL;
-}
-
-void
-nsock_lst_map(struct nsock_listener *ls, nsock_lst_map_t map, void *data)
-{
-	const struct nsock_clt *clt;
-
-	TAILQ_FOREACH(clt, &ls->head, link)
-		map(clt->sock, data);
-}
-
-void
-nsock_lst_free(struct nsock_listener *ls)
-{
-	struct nsock_clt *clt, *tmp;
-
-	TAILQ_FOREACH_SAFE(clt, &ls->head, link, tmp)
-		free(clt);
-
-	free(ls);
-}
--- a/nsock.h	Fri Nov 15 21:37:57 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-/*
- * nsock.h -- portable BSD sockets wrapper
- *
- * Copyright (c) 2013 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _NSOCK_H_
-#define _NSOCK_H_
-
-#if !defined(NSOCK_NOINCLUDES)
-#  if defined(_WIN32)
-#    include <WinSock2.h>
-#    include <WS2tcpip.h>
-#  else
-#    include <sys/types.h>
-#    include <sys/socket.h>
-#    include <sys/un.h>
-
-#    include <arpa/inet.h>
-
-#    include <netinet/in.h>
-
-#    include <netdb.h>
-#    include <unistd.h>
-#  endif
-#endif
-
-struct nsock;
-struct nsock_address;
-struct nsock_listener;
-
-/* --------------------------------------------------------
- * Sockets functions
- * -------------------------------------------------------- */
-
-void
-nsock_init(void);
-
-struct nsock *
-nsock_new(void);
-
-int
-nsock_create(struct nsock *, int, int, int);
-
-const char *
-nsock_error(struct nsock *);
-
-int
-nsock_bind(struct nsock *, const struct nsock_address *);
-
-int
-nsock_listen(struct nsock *, int);
-
-int
-nsock_accept(struct nsock *, struct nsock **, struct nsock_address **);
-
-int
-nsock_connect(struct nsock *, const struct nsock_address *);
-
-int
-nsock_set(struct nsock *, int, int, const void *, unsigned);
-
-long
-nsock_recv(struct nsock *, void *, size_t, int);
-
-long
-nsock_recvfrom(struct nsock *, struct nsock_address *, void *, size_t, int);
-
-long
-nsock_send(struct nsock *, const void *, size_t, int);
-
-long
-nsock_sendto(struct nsock *, const struct nsock_address *, const void *, size_t, int);
-
-void
-nsock_close(struct nsock *);
-
-void
-nsock_free(struct nsock *);
-
-void
-nsock_finish(void);
-
-/* --------------------------------------------------------
- * End point functions
- * -------------------------------------------------------- */
-
-struct nsock_address *
-nsock_addr_new(void);
-
-const char *
-nsock_addr_error(struct nsock_address *);
-
-int
-nsock_addr_bind_ip(struct nsock_address *, const char *, unsigned, int);
-
-int
-nsock_addr_connect_ip(struct nsock_address *, const char *, unsigned, int);
-
-#if !defined(_WIN32)
-
-void
-nsock_addr_unix(struct nsock_address *, const char *);
-
-#endif
-
-struct sockaddr *
-nsock_addr_getaddr(struct nsock_address *);
-
-socklen_t
-nsock_addr_getaddrlen(const struct nsock_address *);
-
-void
-nsock_addr_free(struct nsock_address *);
-
-/* --------------------------------------------------------
- * listener functions
- * -------------------------------------------------------- */
-
-typedef void (*nsock_lst_map_t)(const struct nsock *, void *);
-
-struct nsock_listener *
-nsock_lst_new(const struct nsock *);
-
-const char *
-nsock_lst_error(struct nsock_listener *);
-
-int
-nsock_lst_push(struct nsock_listener *, struct nsock *);
-
-int
-nsock_lst_append(struct nsock_listener *, struct nsock *);
-
-size_t
-nsock_lst_count(const struct nsock_listener *);
-
-void
-nsock_lst_remove(struct nsock_listener *, const struct nsock *);
-
-struct nsock *
-nsock_lst_select(struct nsock_listener *, long, long);
-
-void
-nsock_lst_map(struct nsock_listener *, nsock_lst_map_t, void *);
-
-void
-nsock_lst_free(struct nsock_listener *);
-
-#endif /* !_NSOCK_H_ */
--- a/pack.c	Fri Nov 15 21:37:57 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,477 +0,0 @@
-/*
- * pack.c -- endian dependant binary file reader
- *
- * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "pack.h"
-
-/* Compilation tunables */
-#if !defined(PACK_CHKSIZE)
-#  define PACK_CHKSIZE	(256)		/* default chunk size */
-#endif
-
-/* Type */
-enum pack_type {
-	TYPE_FP,
-	TYPE_FIXEDBUF,
-	TYPE_AUTOBUF
-};
-
-struct pack_sc {
-	enum pack_type	type;		/* which kind of work */
-	short		endian;		/* endian */
-
-	/* if TYPE_FP */
-	FILE *		fp;		/* file to write */
-
-	/* else */
-	char *		buf;		/* bytes converted */
-	size_t		size;		/* current length */
-	size_t		allocated;	/* allocated size */
-
-	/* for reading */
-	unsigned int	position;	/* position where to read */
-};
-
-struct pack_value {
-	/* for writing */
-	int		nelem;		/* number of element */
-	int		size;		/* size of elements */
-	uint64_t	value;		/* direct value */
-	char *		array;		/* array of values */
-
-	/* for reading */
-	char *		dst;		/* destination */
-};
-
-#define SC_SET(s, tp, ed, f, b, al) do {				\
-	memset((s), 0, sizeof (struct pack_sc));			\
-	(s)->type	= tp;						\
-	(s)->endian	= ed;						\
-	(s)->fp		= f;						\
-	(s)->buf	= b;						\
-	(s)->allocated	= al;						\
-} while (/* CONSTCOND */ 0)
-
-#define TOKNARG(tok, nelem) do {					\
-	if (p[1] == '[') {						\
-		char *end;						\
-									\
-		/* Can statically write the number, or pass it */	\
-		if (p[2] != ']') {					\
-			nelem = (int)strtol(&p[2], &end, 10);		\
-			p = end;					\
-		} else {						\
-			nelem = va_arg(ap, int);			\
-			while (!isspace(*p) && *p != ']' && *p != '\0')	\
-				++p;					\
-		}							\
-	} else								\
-		nelem = 1;						\
-} while (/* CONSTCOND */ 0)
-
-#define TOKSIZE(tok, size) do {						\
-	switch (tok) {							\
-	case 'c':							\
-		size = sizeof (uint8_t);				\
-		break;							\
-	case 's':							\
-		size = sizeof (uint16_t);				\
-		break;							\
-	case 'i':							\
-		size = sizeof (uint32_t);				\
-		break;							\
-	case 'l':							\
-		size = sizeof (uint64_t);				\
-		break;							\
-	default:							\
-		size = 0;						\
-		break;							\
-	}								\
-} while (/* CONSTCOND */ 0)
-
-#define TOKGETARG(serv, tok, val, ap) do {				\
-	if ((val)->nelem == 1 && serv == writeto) {			\
-		uint64_t item;						\
-		switch (tok) {						\
-		case 'c': case 's': case 'i':				\
-			item = va_arg(ap, int);				\
-			break;						\
-		case 'l':						\
-			item = va_arg(ap, uint64_t);			\
-			break;						\
-		default:						\
-			item = 0;					\
-			break;						\
-		}							\
-									\
-		memset(&(val)->value, 0, sizeof (uint64_t));		\
-		memcpy(&(val)->value, &item, (val)->size);		\
-		(val)->array = (char *)&(val)->value;			\
-	} else { /* read is always a pointer */				\
-		(val)->array = va_arg(ap, void *);			\
-		(val)->dst = (val)->array;				\
-	}								\
-} while (/* CONSTCOND */ 0)
-
-#define GETCONV(ed, size, conv) do {					\
-	if (ed != PACK_HOST_BYTEORDER) {				\
-		switch ((size)) {					\
-		case (sizeof (uint16_t)):				\
-			conv = conv16; break;				\
-		case (sizeof (uint32_t)):				\
-			conv = conv32; break;				\
-		case (sizeof (uint64_t)):				\
-			conv = conv64; break;				\
-		default:						\
-			conv = NULL;					\
-		}							\
-	} else								\
-		conv = NULL;						\
-} while (/* CONSTCOND */ 0)
-
-static void
-conv16(void *item)
-{
-	*(uint16_t *)item = pack_swap16(*(uint16_t *)item);
-}
-
-static void
-conv32(void *item)
-{
-	*(uint32_t *)item = pack_swap32(*(uint32_t *)item);
-}
-
-static void
-conv64(void *item)
-{
-	*(uint64_t *)item = pack_swap64(*(uint64_t *)item);
-}
-
-/*
- * Function that write content into the buffer or file depending
- * on the calling function. Returns the number of bytes written
- * or -1 on failure.
- */
-static long
-writeto(struct pack_sc *sc, struct pack_value *val)
-{
-	void (*conv)(void *);
-	int i;
-	uint64_t item;
-	long nbytes = 0;
-
-	/* Get converter */
-	GETCONV(sc->endian, val->size, conv);
-
-	for (i = 0; i < val->nelem; ++i) {
-		item = 0;
-		memcpy(&item, &val->array[i * val->size], val->size);
-
-		if (conv != NULL)
-			conv(&item);
-
-		switch (sc->type) {
-		case TYPE_FP:
-			fwrite(&item, val->size, 1, sc->fp);
-			break;
-		case TYPE_AUTOBUF:
-			if (sc->size + val->size >= sc->allocated) {
-				sc->allocated += PACK_CHKSIZE;
-				sc->buf = realloc(sc->buf, sc->allocated);
-
-				if (sc->buf == NULL)
-					return -1;
-			}
-			/* FALLTHROUGH */
-		case TYPE_FIXEDBUF:
-			if (sc->size + val->size <= sc->allocated) {
-				memcpy(&sc->buf[sc->size], &item, val->size);
-				sc->size += val->size;
-			} else
-				continue;
-		default:
-			break;
-		}
-
-		nbytes += val->size;
-	}
-
-	return nbytes;
-}
-
-/*
- * Function that read the file or buffer and fill array.
- */
-static long
-readfrom(struct pack_sc *sc, struct pack_value *val)
-{
-	void (*conv)(void *);
-	int i, oktoread;
-	uint64_t item;
-	long nbytes = 0;
-
-	/* Get converter */
-	GETCONV(sc->endian, val->size, conv);
-
-	for (i = 0; i < val->nelem; ++i) {
-		item = oktoread = 0;
-
-		switch (sc->type) {
-		case TYPE_FP:
-			fread(&item, val->size, 1, sc->fp);
-			oktoread = 1;
-			break;
-		case TYPE_FIXEDBUF:
-			if (sc->position + val->size <= sc->allocated) {
-				memcpy(&item, &sc->buf[sc->position], val->size);
-				sc->position += val->size;
-				oktoread = 1;
-			}
-			break;
-		default:
-			break;
-		}
-
-		if (conv != NULL)
-			conv(&item);
-
-		if (oktoread) {
-			memcpy(&val->dst[i * val->size], &item, val->size);
-			nbytes += val->size;
-		}
-	}
-
-	return nbytes;
-}
-
-/*
- * Function that analyses the format, write or read the values depending
- * on the calling functions.
- */
-static long
-packit(struct pack_sc *sc, long (*func)(struct pack_sc *, struct pack_value *),
-       const char *fmt, va_list ap)
-{
-	struct pack_value val;
-	const char *p;
-	int tok;
-	long nbytes = 0, rv;
-
-	for (p = fmt; *p != '\0'; ++p) {
-		tok = *p;
-
-		if (isspace(*p))
-			continue;
-
-		TOKNARG(tok, val.nelem);
-		TOKSIZE(tok, val.size);
-
-		if (val.size == 0 || val.nelem == 0)
-			continue;
-
-		TOKGETARG(func, tok, &val, ap);
-		if ((rv = func(sc, &val)) == -1)
-			return -1;
-
-		nbytes += rv;
-	}
-
-	return nbytes;
-}
-
-long
-pack_write(short ed, const char *path, const char *fmt, ...)
-{
-	va_list ap;
-	long rv;
-
-	va_start(ap, fmt);
-	rv = pack_vwrite(ed, path, fmt, ap);
-	va_end(ap);
-
-	return rv;
-}
-
-long
-pack_vwrite(short ed, const char *path, const char *fmt, va_list ap)
-{
-	FILE *fp;
-	long rv;
-
-	if ((fp = fopen(path, "wb")) == NULL)
-		return -1;
-
-	rv = pack_vfwrite(ed, fp, fmt, ap);
-	fclose(fp);
-
-	return rv;
-}
-
-long
-pack_fwrite(short ed, FILE *fp, const char *fmt, ...)
-{
-	va_list ap;
-	long rv;
-
-	va_start(ap, fmt);
-	rv = pack_vfwrite(ed, fp, fmt, ap);
-	va_end(ap);
-
-	return rv;
-}
-
-long
-pack_vfwrite(short ed, FILE *fp, const char *fmt, va_list ap)
-{
-	struct pack_sc sc;
-
-	SC_SET(&sc, TYPE_FP, ed, fp, NULL, 0);
-
-	return packit(&sc, writeto, fmt, ap);
-}
-
-long
-pack_swrite(short ed, char *buf, size_t max, const char *fmt, ...)
-{
-	va_list ap;	
-	long rv;
-
-	va_start(ap, fmt);
-	rv = pack_vswrite(ed, buf, max, fmt, ap);
-	va_end(ap);
-
-	return rv;
-}
-
-long
-pack_vswrite(short ed, char *buf, size_t max, const char *fmt, va_list ap)
-{
-	struct pack_sc sc;
-
-	SC_SET(&sc, TYPE_FIXEDBUF, ed, NULL, buf, max);
-
-	return packit(&sc, writeto, fmt, ap);
-}
-
-long
-pack_aswrite(short ed, char **bufp, const char *fmt, ...)
-{
-	va_list ap;	
-	long rv;
-
-	va_start(ap, fmt);
-	rv = pack_vaswrite(ed, bufp, fmt, ap);
-	va_end(ap);
-
-	return rv;
-}
-
-long
-pack_vaswrite(short ed, char **bufp, const char *fmt, va_list ap)
-{
-	struct pack_sc sc;
-	int rv;
-
-	SC_SET(&sc, TYPE_AUTOBUF, ed, NULL, NULL, PACK_CHKSIZE);
-
-	if ((sc.buf = malloc(PACK_CHKSIZE)) == NULL)
-		return -1;
-
-	rv = packit(&sc, writeto, fmt, ap);
-	*bufp = sc.buf;
-
-	return rv;
-}
-
-long
-pack_read(short ed, const char *path, const char *fmt, ...)
-{
-	va_list ap;
-	long rv;
-
-	va_start(ap, fmt);
-	rv = pack_vread(ed, path, fmt, ap);
-	va_end(ap);
-
-	return rv;
-}
-
-long
-pack_vread(short ed, const char *path, const char *fmt, va_list ap)
-{
-	FILE *fp;
-	long rv;
-
-	if ((fp = fopen(path, "rb")) == NULL)
-		return -1;
-
-	rv = pack_vfread(ed, fp, fmt, ap);
-	fclose(fp);
-
-	return rv;
-}
-
-long
-pack_fread(short ed, FILE *fp, const char *fmt, ...)
-{
-	va_list ap;
-	long rv;
-
-	va_start(ap, fmt);
-	rv = pack_vfread(ed, fp, fmt, ap);
-	va_end(ap);
-
-	return rv;
-}
-
-long
-pack_vfread(short ed, FILE *fp, const char *fmt, va_list ap)
-{
-	struct pack_sc sc;
-
-	SC_SET(&sc, TYPE_FP, ed, fp, NULL, 0);
-
-	return packit(&sc, readfrom, fmt, ap);
-}
-
-long
-pack_sread(short ed, const char *buf, size_t max, const char *fmt, ...)
-{
-	va_list ap;	
-	long rv;
-
-	va_start(ap, fmt);
-	rv = pack_vsread(ed, buf, max, fmt, ap);
-	va_end(ap);
-
-	return rv;
-}
-
-long
-pack_vsread(short ed, const char *buf, size_t max, const char *fmt, va_list ap)
-{
-	struct pack_sc sc;
-
-	SC_SET(&sc, TYPE_FIXEDBUF, ed, NULL, (char *)buf, max);
-
-	return packit(&sc, readfrom, fmt, ap);
-}
--- a/pack.h	Fri Nov 15 21:37:57 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
- * pack.h -- endian dependant binary file reader
- *
- * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _PACK_H_
-#define _PACK_H_
-
-#include <stdarg.h>
-#include <stdint.h>
-
-#define PACK_LE		1234
-#define PACK_BE		4321
-
-/*
- * Endian detection based on SDL_endian.h
- */
-
-#undef PACK_HOST_BYTEORDER
-
-#if defined(__hppa__) ||						\
-    defined(__m68k__) || defined(mc68000) || defined(_M_M68K) ||	\
-    (defined(__MIPS__) && defined(__MISPEB__)) ||			\
-    defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) ||	\
-    defined(__sparc__)
-#  define PACK_HOST_BYTEORDER	PACK_BE
-#else
-#  define PACK_HOST_BYTEORDER	PACK_LE
-#endif
-
-#define pack_swap16(x)							\
-	((((x) >> 8) & 0x00FFL) | (((x) << 8) & 0xFF00L))
-
-#define pack_swap32(x) ((((x) >> 24) & 0x000000FFL)			\
-	| (((x) >> 8)  & 0x0000FF00L)					\
-	| (((x) << 8)  & 0x00FF0000L)					\
-	| (((x) << 24) & 0xFF000000L))
-
-#define pack_swap64(x) (((long)					\
-	((int) pack_swap32((int) (((x) << 32) >> 32))) << 32)	\
-	    | (int) pack_swap32((int) ((x) >> 32)))
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-long	pack_write(short, const char *, const char *, ...);
-long	pack_vwrite(short, const char *, const char *, va_list);
-long	pack_fwrite(short, FILE *, const char *, ...);
-long	pack_vfwrite(short, FILE *, const char *, va_list);
-long	pack_swrite(short, char *, size_t, const char *, ...);
-long	pack_vswrite(short, char *, size_t, const char *, va_list);
-long	pack_aswrite(short, char **, const char *, ...);
-long	pack_vaswrite(short, char **, const char *, va_list);
-
-long	pack_read(short, const char *, const char *, ...);
-long	pack_vread(short, const char *, const char *, va_list);
-long	pack_fread(short, FILE *, const char *, ...);
-long	pack_vfread(short, FILE *, const char *, va_list);
-long	pack_sread(short, const char *, size_t, const char *, ...);
-long	pack_vsread(short, const char *, size_t, const char *, va_list);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PACK_H_ */
--- a/parray.c	Fri Nov 15 21:37:57 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,366 +0,0 @@
-/*
- * parray.c -- manipulate dynamic pointer arrays
- *
- * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "parray.h"
-
-#define LENGTH(x)	((x) * (sizeof (void *)))
-
-static int		grow(struct parray *);
-
-int
-parray_init(struct parray *arr)
-{
-	/* Set defaults if needed */
-	arr->bsize	= (arr->bsize <= 0) ? PARRAY_DEFAULT_BSIZE : arr->bsize;
-	arr->malloc	= (arr->malloc == NULL) ? &malloc : arr->malloc;
-	arr->realloc	= (arr->realloc == NULL) ? &realloc : arr->realloc;
-
-	arr->bsize	+= (arr->flags & PARRAY_NULLEND) ? 1 : 0;
-	arr->size	= LENGTH(arr->bsize);
-
-	if ((arr->data = arr->malloc(arr->size)) == NULL)
-		return -1;
-
-	memset(arr->data, 0, arr->size);
-
-	return 0;
-}
-
-/*
- * Valid options that can be set for an array :
- * l -> optional array block size of type int
- * m -> malloc function that must matches void * (*malloc)(size_t)
- * r -> realloc function that must matches void * (*realloc)(void *, size_t)
- * f -> parray flags of type int
- */
-void
-parray_set(struct parray *arr, const char *fmt, ...)
-{
-	va_list ap;
-	const char *p;
-
-	va_start(ap, fmt);
-	for (p = fmt; *p != '\0'; ++p)
-		switch (*p) {
-		case 'l':
-			arr->bsize = va_arg(ap, int);
-			break;
-		case 'm':
-			arr->malloc = va_arg(ap, void * (*)(size_t));
-			break;
-		case 'r':
-			arr->realloc = va_arg(ap, void * (*)(void *, size_t));
-			break;
-		case 'f':
-			arr->flags = va_arg(ap, int);
-			break;
-		default:
-			break;
-		}
-}
-
-/*
- * Add to the head of array. NOTE: this may be very slow when adding a lot
- * of object (about 100000). If you need to add a lot of data please consider
- * using linked list instead. Returns -1 on failure or 0 on success.
- */
-int
-parray_push(struct parray *arr, void *data)
-{
-	if (grow(arr) < 0)
-		return -1;
-
-	memmove(&arr->data[1], &arr->data[0], LENGTH(arr->length++));
-	arr->data[0] = data;
-
-	if (arr->flags & PARRAY_NULLEND)
-		arr->data[arr->length] = NULL;
-
-	return 0;
-}
-
-/*
- * Insert the data at the specified index. The function returns -1 on
- * allocation failure or the position of the added element.
- */
-int
-parray_insert(struct parray *arr, void *data, int index)
-{
-	if (arr->flags & PARRAY_INSERTSAFE)
-		if (index < 0 || index > arr->length)
-			return -1;
-
-	if (index < 0)
-		return parray_push(arr, data);
-	if (index >= arr->length)
-		return parray_append(arr, data);
-
-	/* Good place */
-	memmove(&arr->data[index + 1], &arr->data[index],
-		LENGTH(arr->length++ - index));
-	arr->data[index] = data;
-
-	if (arr->flags & PARRAY_NULLEND)
-		arr->data[arr->length] = NULL;
-
-	return index;
-}
-
-/*
- * Append the data to the end of array. Returns -1 on failure or the position
- * of the added element.
- */
-int
-parray_append(struct parray *arr, void *data)
-{
-	if (grow(arr) < 0)
-		return -1;
-
-	arr->data[arr->length++] = data;
-
-	if (arr->flags & PARRAY_NULLEND)
-		arr->data[arr->length] = NULL;
-
-	return (arr->length - 1);
-}
-
-/*
- * Remove the array's head.
- */
-void
-parray_pop(struct parray *arr)
-{
-	parray_iremove(arr, 0);
-}
-
-/*
- * Remove the array's tail.
- */
-void
-parray_unqueue(struct parray *arr)
-{
-	parray_iremove(arr, arr->length - 1);
-}
-
-/*
- * Remove the data at the specified index. Bounds are checked.
- */
-void
-parray_iremove(struct parray *arr, int index)
-{
-	if (arr->length > 0 && index >= 0 && index < arr->length) {
-		if (arr->flags & PARRAY_FASTREMOVE)
-			arr->data[index] = arr->data[--arr->length];
-		else
-			memmove(&arr->data[index], &arr->data[index + 1],
-			    LENGTH(arr->length-- - index - 1));
-	}
-
-	arr->data[arr->length] = NULL;
-}
-
-/*
- * Remove the object referenced by the `data' argument. Useful when you
- * don't know the index.
- */
-void
-parray_premove(struct parray *arr, const void *data)
-{
-	void *elm;
-	int i;
-
-	PARRAY_FOREACH(arr, elm, i) {
-		if (elm == data) {
-			parray_iremove(arr, i);
-			break;
-		}
-	}
-}
-
-/*
- * Swap the two elements referenced by index `i1' and `i2'. This function needs
- * to allocate data to swap elements thus if the functions fails it returns -1
- * otherwise 0 is returned.
- */
-int
-parray_iswap(struct parray *arr, int i1, int i2)
-{
-	void *tmp;
-
-	/* Out of bounds */
-	if (i1 >= arr->length || i1 < 0 || i2 >= arr->length || i2 < 0)
-		return -1;
-
-	tmp = arr->data[i1];
-	arr->data[i1] = arr->data[i2];
-	arr->data[i2] = tmp;
-
-	return 0;
-}
-
-/*
- * Swap the two elements referenced by data `o1' and `o2'. This function
- * may be slow on large arrays since it must travel all the object
- * to find the indexes.
- */
-int
-parray_pswap(struct parray *arr, const void *o1, const void *o2)
-{
-	int found, i1, i2;
-
-	for (i1 = found = 0; !found && i1 < arr->length; ++i1)
-		found = arr->data[i1] == o1;
-
-	if (!found)
-		return -1;
-
-	for (i2 = found = 0; !found && i2 < arr->length; ++i2)
-		found = arr->data[i2] == o2;
-
-	if (!found)
-		return -1;
-
-	return parray_iswap(arr, --i1, --i2);
-}
-
-/*
- * Apply the function `fn' on each object and give the optional `udata'
- * argument to the function too.
- */
-void
-parray_map(const struct parray *arr, parray_map_t fn, void *udata)
-{
-	int i;
-
-	for (i = 0; i < arr->length; ++i)
-		fn(arr->data[i], udata);
-}
-
-/*
- * Compare each object with the user supplied function. If the `fn' function
- * returns 1 then the index of the data position is returned and the parameter
- * data points to the array data at the correct index. If the comparison
- * function nevers returns 1, array_find returns -1.
- */
-int
-parray_find(const struct parray *arr, parray_cmp_t fn, void *ptr, void *u)
-{
-	int st, i;
-
-	for (i = st = 0; i < arr->length && st != 1; ++i)
-		st = fn(arr->data[i], u);
-
-	if (st && ptr)
-		*(void **)ptr = arr->data[i - 1];
-
-	return (st) ? i - 1 : -1;
-}
-
-void *
-parray_first(const struct parray *arr)
-{
-	return arr->data[0];
-}
-
-void *
-parray_get(const struct parray *arr, int idx)
-{
-	if (idx < 0)
-		return parray_first(arr);
-	if (idx >= arr->length)
-		return parray_last(arr);
-
-	return arr->data[idx];
-}
-
-void *
-parray_last(const struct parray *arr)
-{
-	if (arr->length == 0)
-		return parray_first(arr);
-
-	return arr->data[arr->length - 1];
-}
-
-/*
- * Reset the array by setting each pointer to NULL and the length to 0.
- */
-void
-parray_clear(struct parray *arr)
-{
-	arr->data[0]	= NULL;
-	arr->length	= 0;
-}
-
-/*
- * Same as parray_clear except it also free the array object.
- */
-void
-parray_free(struct parray *arr)
-{
-	parray_clear(arr);
-	free(arr->data);
-
-	arr->data	= NULL;
-	arr->size	= 0;
-}
-
-/*
- * Trim down the array to the correct size.
- */
-void *
-parray_trim(struct parray *arr)
-{
-	int count = arr->length;
-
-	if (arr->flags & PARRAY_NULLEND)
-		++ count;
-
-	return arr->realloc(arr->data, count * sizeof (void *));
-}
-
-/*
- * Increate the array storage when it is full. If the buffer is fixed size
- * it returns -1 on full buffer otherwise 0 is returned if allocation
- * succeeded.
- */
-static int
-grow(struct parray *arr)
-{
-	unsigned int toadd = (arr->flags & PARRAY_NULLEND) ? 2 : 1;
-
-	if ((arr->size / sizeof (void *)) - arr->length >= toadd)
-		return 0;
-
-	if (!(arr->flags & PARRAY_FIXED)) {
-		if ((arr->data = arr->realloc(arr->data, arr->size +
-		    LENGTH(arr->bsize))) == NULL) {
-			arr->size = arr->length = 0;
-			return -1;
-		}
-
-		arr->size += LENGTH(arr->bsize);
-	} else
-		return -1;
-
-	return 0;
-}
--- a/parray.h	Fri Nov 15 21:37:57 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/*
- * parray.h -- manipulate dynamic pointer arrays
- *
- * Copyright (c) 2011, 2012, David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _PARRAY_H_
-#define _PARRAY_H_
-
-#include <stdarg.h>
-
-#ifndef PARRAY_DEFAULT_BSIZE
-#define PARRAY_DEFAULT_BSIZE	128
-#endif
-
-enum parray_flags {
-	PARRAY_AUTO		= 0,		/* array grows automatically */
-	PARRAY_FIXED		= (1 << 0),	/* fixed size length */
-	PARRAY_FASTREMOVE	= (1 << 1),	/* use last object when removing */
-	PARRAY_NULLEND		= (1 << 2),	/* always has a NULL pointer at end */
-	PARRAY_INSERTSAFE	= (1 << 3)	/* insertion must have valid indexes */
-};
-
-struct parray {
-	enum parray_flags	flags;		/* (ro) array flags (default AUTO) */
-	void			**data;		/* (rw) array of data */
-	int			length;		/* (ro) number of element inside */
-	size_t			size;		/* (ro) current buffer size (allocated memory) */
-	int			bsize;		/* (rw) block size (used when growing array) */
-
-	/* Own allocation functions */
-	void * (*malloc)(size_t);
-	void * (*realloc)(void *, size_t);
-};
-
-typedef void (*parray_map_t)(void *, void *);
-typedef int (*parray_cmp_t)(void *, void *);
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int
-parray_init(struct parray *);
-
-void
-parray_set(struct parray *, const char *, ...);
-
-int
-parray_push(struct parray *, void *);
-
-int
-parray_insert(struct parray *, void *, int);
-
-int
-parray_append(struct parray *, void *);
-
-void
-parray_pop(struct parray *);
-
-void
-parray_unqueue(struct parray *);
-
-void
-parray_iremove(struct parray *, int);
-
-void
-parray_premove(struct parray *, const void *);
-
-int
-parray_iswap(struct parray *, int, int);
-
-int
-parray_pswap(struct parray *, const void *, const void *);
-
-void
-parray_map(const struct parray *, parray_map_t, void *);
-
-int
-parray_find(const struct parray *, parray_cmp_t, void *, void *);
-
-void *
-parray_first(const struct parray *);
-
-void *
-parray_get(const struct parray *, int);
-
-void *
-parray_last(const struct parray *);
-
-void
-parray_clear(struct parray *);
-
-void
-parray_free(struct parray *);
-
-void *
-parray_trim(struct parray *);
-
-#define PARRAY_FOREACH(a, o, i)						\
-	for (i = 0, o = (a)->data[i];					\
-	    i < (a)->length;						\
-	    ++i, o = (a)->data[i])
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PARRAY_H_ */