Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
libucl: import 0.9 version (+ fixes upstreamed)
Baptiste Daroussin committed 2 years ago
commit 825c2a3a04dbc67f404cd06a9b17bd8ea90228e8
parent accec28
20 files changed +787 -520
modified external/libucl/CMakeLists.txt
@@ -1,9 +1,9 @@
-
PROJECT(libucl C)
CMAKE_MINIMUM_REQUIRED(VERSION 3.1.0 FATAL_ERROR)
+
PROJECT(libucl C)

SET(LIBUCL_VERSION_MAJOR 0)
-
SET(LIBUCL_VERSION_MINOR 8)
-
SET(LIBUCL_VERSION_PATCH 3)
+
SET(LIBUCL_VERSION_MINOR 9)
+
SET(LIBUCL_VERSION_PATCH 0)

SET(LIBUCL_VERSION
        "${LIBUCL_VERSION_MAJOR}.${LIBUCL_VERSION_MINOR}.${LIBUCL_VERSION_PATCH}")
modified external/libucl/ChangeLog.md
@@ -1,5 +1,21 @@
# Version history

+
## Libucl 0.9.0
+

+
* 803b588 Breaking: Try to fix streamline embedding
+
* 9eddef0 Fix: set p to endptr before checking
+
* 25d3f51 Fix broken tests
+
* ac644e2 Update makefile.yml
+
* 0a5739e Create makefile.yml
+
* 987389a Merge branch 'master' into vstakhov-gh-actions
+
* 7433904 Import lua code from Rspamd
+
* 3912614 Create cmake-multi-platform.yml
+
* 3a04c92 lua: Push string with len
+
* 2fefed6 Use `_WIN32` instead of `_MSC_VER`
+
* aecf17e Avoid build failure trying to create setup.py link if it already exists.
+
* 4ef9e6d Add inttypes.h for PRId64
+
* dcb43f0 Fix excessive escaping when using ucl_object_fromstring()
+

## Libucl 0.5

- Streamline emitter has been added, so it is now possible to output partial `ucl` objects
modified external/libucl/Makefile.unix
@@ -3,8 +3,8 @@ DESTDIR ?= /usr/local
LD ?= gcc
C_COMMON_FLAGS ?= -fPIC -Wall -W -Wno-unused-parameter -Wno-pointer-sign -I./include -I./uthash -I./src -I./klib
MAJOR_VERSION = 0
-
MINOR_VERSION = 2
-
PATCH_VERSION = 9
+
MINOR_VERSION = 9
+
PATCH_VERSION = 0
VERSION = "$(MAJOR_VERSION).$(MINOR_VERSION).$(PATCH_VERSION)"
SONAME = libucl.so
SONAME_FULL = $(SONAME).$(MAJOR_VERSION)
modified external/libucl/README.md
@@ -1,4 +1,4 @@
-
# LIBUCL
+
# UCL - Universal Configuration Language

**Table of Contents**  *generated with [DocToc](http://doctoc.herokuapp.com/)*

@@ -22,15 +22,19 @@

## Introduction

-
This document describes the main features and principles of the configuration
-
language called `UCL` - universal configuration language.
+
This repository provides the `C` library for parsing configurations written in `UCL` - universal configuration language. It also provides functions to operate with other formats:
+

+
* `JSON`: read, write and pretty format
+
* `Messagepack`: read and write
+
* `S-Expressions`: read only (canonical form)
+
* `Yaml`: limited write support (mainly for compatibility)

If you are looking for the libucl API documentation you can find it at [this page](doc/api.md).

## Basic structure

-
UCL is heavily infused by `nginx` configuration as the example of a convenient configuration
-
system. However, UCL is fully compatible with `JSON` format and is able to parse json files.
+
`UCL` is heavily infused by `nginx` configuration as the example of a convenient configuration
+
system. However, `UCL` is fully compatible with `JSON` format and is able to parse json files.
For example, you can write the same configuration in the following ways:

* in nginx like:
@@ -230,7 +234,7 @@ UCL supports external macros both multiline and single line ones:
```

Moreover, each macro can accept an optional list of arguments in braces. These
-
arguments themselves are the UCL object that is parsed and passed to a macro as
+
arguments themselves are the `UCL` object that is parsed and passed to a macro as
options:

```nginx
modified external/libucl/configure.ac
@@ -1,7 +1,7 @@
m4_define([maj_ver], [0])
-
m4_define([med_ver], [8])
-
m4_define([min_ver], [3])
-
m4_define([so_version], [6:0:1])
+
m4_define([med_ver], [9])
+
m4_define([min_ver], [0])
+
m4_define([so_version], [9:0:0])
m4_define([ucl_version], [maj_ver.med_ver.min_ver])

AC_INIT([libucl],[ucl_version],[https://github.com/vstakhov/libucl],[libucl])
modified external/libucl/include/ucl.h
@@ -1411,13 +1411,13 @@ struct ucl_emitter_operations {
		const ucl_object_t *obj, bool first, bool print_key);
	/** Start ucl object */
	void (*ucl_emitter_start_object) (struct ucl_emitter_context *ctx,
-
		const ucl_object_t *obj, bool print_key);
+
		const ucl_object_t *obj, bool first, bool print_key);
	/** End ucl object */
	void (*ucl_emitter_end_object) (struct ucl_emitter_context *ctx,
		const ucl_object_t *obj);
	/** Start ucl array */
	void (*ucl_emitter_start_array) (struct ucl_emitter_context *ctx,
-
		const ucl_object_t *obj, bool print_key);
+
		const ucl_object_t *obj, bool first, bool print_key);
	void (*ucl_emitter_end_array) (struct ucl_emitter_context *ctx,
		const ucl_object_t *obj);
};
deleted external/libucl/libucl.pc.in
@@ -1,11 +0,0 @@
-
prefix=@prefix@
-
exec_prefix=@exec_prefix@
-
libdir=@libdir@
-
includedir=@includedir@
-

-
Name: LibUCL
-
Description: Universal configuration library
-
Version: @UCL_VERSION@
-
Libs: -L${libdir} -lucl
-
Libs.private: @LIBS_EXTRA@ @LUA_LIB@
-
Cflags: -I${includedir}/
modified external/libucl/lua/lua_ucl.c
@@ -82,6 +82,11 @@ static ucl_object_t* ucl_object_lua_fromelt (lua_State *L, int idx, ucl_string_f

static void *ucl_null;

+
struct _rspamd_lua_text {
+
	const char *start;
+
	unsigned int len;
+
	unsigned int flags;
+
};

enum lua_ucl_push_flags {
	LUA_UCL_DEFAULT_FLAGS = 0,
@@ -240,7 +245,7 @@ ucl_object_lua_push_scalar (lua_State *L, const ucl_object_t *obj,
		lua_pushboolean (L, ucl_obj_toboolean (obj));
		break;
	case UCL_STRING:
-
		lua_pushstring (L, ucl_obj_tostring (obj));
+
		lua_pushlstring (L, ucl_obj_tostring (obj), obj->len);
		break;
	case UCL_INT:
#if LUA_VERSION_NUM >= 501
@@ -510,6 +515,24 @@ ucl_object_lua_fromelt (lua_State *L, int idx, ucl_string_flags_t flags)
		if (lua_topointer (L, idx) == ucl_null) {
			obj = ucl_object_typed_new (UCL_NULL);
		}
+
		else {
+
			/* Assume it is a text like object */
+
			struct _rspamd_lua_text *t = lua_touserdata (L, idx);
+

+
			if (t) {
+
				if (t->len >0) {
+
					obj = ucl_object_fromstring_common(t->start, t->len, 0);
+
				}
+
				else {
+
					obj = ucl_object_fromstring_common("", 0, 0);
+
				}
+

+
				/* Binary text */
+
				if (t->flags & (1u << 5u)) {
+
					obj->flags |= UCL_OBJECT_BINARY;
+
				}
+
			}
+
		}
		break;
	case LUA_TTABLE:
	case LUA_TFUNCTION:
@@ -565,10 +588,10 @@ ucl_object_lua_import (lua_State *L, int idx)
	t = lua_type (L, idx);
	switch (t) {
	case LUA_TTABLE:
-
		obj = ucl_object_lua_fromtable (L, idx, 0);
+
		obj = ucl_object_lua_fromtable (L, idx, UCL_STRING_RAW);
		break;
	default:
-
		obj = ucl_object_lua_fromelt (L, idx, 0);
+
		obj = ucl_object_lua_fromelt (L, idx, UCL_STRING_RAW);
		break;
	}

@@ -593,10 +616,10 @@ ucl_object_lua_import_escape (lua_State *L, int idx)
	t = lua_type (L, idx);
	switch (t) {
	case LUA_TTABLE:
-
		obj = ucl_object_lua_fromtable (L, idx, UCL_STRING_RAW);
+
		obj = ucl_object_lua_fromtable (L, idx, UCL_STRING_ESCAPE);
		break;
	default:
-
		obj = ucl_object_lua_fromelt (L, idx, UCL_STRING_RAW);
+
		obj = ucl_object_lua_fromelt (L, idx, UCL_STRING_ESCAPE);
		break;
	}

@@ -607,11 +630,12 @@ static int
lua_ucl_to_string (lua_State *L, const ucl_object_t *obj, enum ucl_emitter type)
{
	unsigned char *result;
+
	size_t outlen;

-
	result = ucl_object_emit (obj, type);
+
	result = ucl_object_emit_len (obj, type, &outlen);

	if (result != NULL) {
-
		lua_pushstring (L, (const char *)result);
+
		lua_pushlstring (L, (const char *)result, outlen);
		free (result);
	}
	else {
@@ -634,7 +658,6 @@ lua_ucl_parser_init (lua_State *L)
	parser = ucl_parser_new (flags);
	if (parser == NULL) {
		lua_pushnil (L);
-
		return 1;
	}

	pparser = lua_newuserdata (L, sizeof (parser));
@@ -843,12 +866,6 @@ lua_ucl_parser_parse_string (lua_State *L)
	return ret;
}

-
struct _rspamd_lua_text {
-
	const char *start;
-
	unsigned int len;
-
	unsigned int flags;
-
};
-

/***
 * @method parser:parse_text(input)
 * Parse UCL object from text object (Rspamd specific).
@@ -864,7 +881,24 @@ lua_ucl_parser_parse_text (lua_State *L)
	int ret = 2;

	parser = lua_ucl_parser_get (L, 1);
-
	t = lua_touserdata (L, 2);
+

+
	if (lua_type (L, 2) == LUA_TUSERDATA) {
+
		t = lua_touserdata (L, 2);
+
	}
+
	else if (lua_type (L, 2) == LUA_TSTRING) {
+
		const gchar *s;
+
		gsize len;
+
		static struct _rspamd_lua_text st_t;
+

+
		s = lua_tolstring (L, 2, &len);
+
		st_t.start = s;
+
		st_t.len = len;
+

+
		t = &st_t;
+
	}
+
	else {
+
		return luaL_error(L, "invalid argument as input, expected userdata or a string");
+
	}

	if (lua_type (L, 3) == LUA_TSTRING) {
		type = lua_ucl_str_to_parse_type (lua_tostring (L, 3));
@@ -1435,10 +1469,11 @@ lua_ucl_to_format (lua_State *L)
				format = UCL_EMIT_YAML;
			}
			else if (strcasecmp (strtype, "config") == 0 ||
-
				strcasecmp (strtype, "ucl") == 0) {
+
					 strcasecmp (strtype, "ucl") == 0) {
				format = UCL_EMIT_CONFIG;
			}
-
			else if (strcasecmp (strtype, "msgpack") == 0) {
+
			else if (strcasecmp (strtype, "msgpack") == 0 ||
+
					 strcasecmp (strtype, "messagepack") == 0) {
				format = UCL_EMIT_MSGPACK;
			}
		}
modified external/libucl/src/mum.h
@@ -1,5 +1,4 @@
-
/* Copyright (c) 2016, 2017, 2018
-
   Vladimir Makarov <vmakarov@gcc.gnu.org>
+
/* Copyright (c) 2016 Vladimir Makarov <vmakarov@gcc.gnu.org>

   Permission is hereby granted, free of charge, to any person
   obtaining a copy of this software and associated documentation
@@ -36,7 +35,7 @@
   Random and Pseudorandom Number Generators for Cryptographic
   Applications (version 2.2.1) with 1000 bitstreams each containing
   1M bits.  MUM hashing is also faster Spooky64 and City64 on small
-
   strings (at least upto 512-bit) on Haswell and Power7.  The MUM bulk
+
   strings (at least up to 512-bit) on Haswell and Power7.  The MUM bulk
   speed (speed on very long data) is bigger than Spooky and City on
   Power7.  On Haswell the bulk speed is bigger than Spooky one and
   close to City speed.  */
@@ -57,16 +56,6 @@ typedef unsigned __int64 uint64_t;
#include <stdint.h>
#endif

-
#ifdef __GNUC__
-
#define _MUM_ATTRIBUTE_UNUSED  __attribute__((unused))
-
#define _MUM_OPTIMIZE(opts) __attribute__((__optimize__ (opts)))
-
#define _MUM_TARGET(opts) __attribute__((__target__ (opts)))
-
#else
-
#define _MUM_ATTRIBUTE_UNUSED
-
#define _MUM_OPTIMIZE(opts)
-
#define _MUM_TARGET(opts)
-
#endif
-

/* Macro saying to use 128-bit integers implemented by GCC for some
   targets.  */
#ifndef _MUM_USE_INT128
@@ -80,6 +69,21 @@ typedef unsigned __int64 uint64_t;
#endif
#endif

+
#if defined(__GNUC__) && ((__GNUC__ == 4) &&  (__GNUC_MINOR__ >= 9) || (__GNUC__ > 4))
+
#define _MUM_FRESH_GCC
+
#endif
+

+
#if defined(__GNUC__) && !defined(__llvm__) && defined(_MUM_FRESH_GCC)
+
#define _MUM_ATTRIBUTE_UNUSED  __attribute__((unused))
+
#define _MUM_OPTIMIZE(opts) __attribute__((__optimize__ (opts)))
+
#define _MUM_TARGET(opts) __attribute__((__target__ (opts)))
+
#else
+
#define _MUM_ATTRIBUTE_UNUSED
+
#define _MUM_OPTIMIZE(opts)
+
#define _MUM_TARGET(opts)
+
#endif
+

+

/* Here are different primes randomly generated with the equal
   probability of their bit values.  They are used to randomize input
   values.  */
@@ -90,7 +94,7 @@ static uint64_t _mum_unroll_prime = 0x7b51ec3d22f7096fULL;
static uint64_t _mum_tail_prime = 0xaf47d47c99b1461bULL;
static uint64_t _mum_finish_prime1 = 0xa9a7ae7ceff79f3fULL;
static uint64_t _mum_finish_prime2 = 0xaf47d47c99b1461bULL;
-
  
+

static uint64_t _mum_primes [] = {
  0X9ebdcae10d981691, 0X32b9b9b97a27ac7d, 0X29b5584d83d35bbd, 0X4b04e0e61401255f,
  0X25e8f7b1f1c9d027, 0X80d4c8c000f3e881, 0Xbd1255431904b9dd, 0X8a3bd4485eee6d81,
@@ -109,7 +113,7 @@ _mum (uint64_t v, uint64_t p) {
     multiplication.  If we use a generic code we actually call a
     function doing 128x128->128 bit multiplication.  The function is
     very slow.  */
-
  lo = v * p;
+
  lo = v * p, hi;
  asm ("umulh %0, %1, %2" : "=r" (hi) : "r" (v), "r" (p));
#else
  __uint128_t r = (__uint128_t) v * (__uint128_t) p;
@@ -126,7 +130,7 @@ _mum (uint64_t v, uint64_t p) {
  uint64_t rm_1 = hp * lv;
  uint64_t rl =  lv * lp;
  uint64_t t, carry = 0;
-
  
+

  /* We could ignore a carry bit here if we did not care about the
     same hash for 32-bit and 64-bit targets.  */
  t = rl + (rm_0 << 32);
@@ -168,7 +172,7 @@ _mum_le (uint64_t v) {
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  return _mum_bswap64 (v);
#else
-
#error "Unknown endianess"
+
#error "Unknown endianness"
#endif
}

@@ -179,18 +183,7 @@ _mum_le32 (uint32_t v) {
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  return _mum_bswap32 (v);
#else
-
#error "Unknown endianess"
-
#endif
-
}
-

-
static inline uint64_t
-
_mum_le16 (uint16_t v) {
-
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || !defined(MUM_TARGET_INDEPENDENT_HASH)
-
  return v;
-
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
-
  return (v >> 8) | ((v & 0xff) << 8);
-
#else
-
#error "Unknown endianess"
+
#error "Unknown endianness"
#endif
}

@@ -207,10 +200,8 @@ _mum_le16 (uint16_t v) {
#define _MUM_UNROLL_FACTOR_POWER 3
#elif defined(__aarch64__) && !defined(MUM_TARGET_INDEPENDENT_HASH)
#define _MUM_UNROLL_FACTOR_POWER 4
-
#elif defined (MUM_V1) || defined (MUM_V2)
-
#define _MUM_UNROLL_FACTOR_POWER 2
#else
-
#define _MUM_UNROLL_FACTOR_POWER 3
+
#define _MUM_UNROLL_FACTOR_POWER 2
#endif
#endif

@@ -222,35 +213,21 @@ _mum_le16 (uint16_t v) {

#define _MUM_UNROLL_FACTOR (1 << _MUM_UNROLL_FACTOR_POWER)

-
/* Rotate V left by SH.  */
-
static inline uint64_t _mum_rotl (uint64_t v, int sh) {
-
  return v << sh | v >> (64 - sh);
-
}
-

static inline uint64_t _MUM_OPTIMIZE("unroll-loops")
_mum_hash_aligned (uint64_t start, const void *key, size_t len) {
  uint64_t result = start;
  const unsigned char *str = (const unsigned char *) key;
  uint64_t u64;
-
  size_t i;
+
  int i;
  size_t n;
-
  
-
#ifndef MUM_V2
+

  result = _mum (result, _mum_block_start_prime);
-
#endif
  while  (len > _MUM_UNROLL_FACTOR * sizeof (uint64_t)) {
    /* This loop could be vectorized when we have vector insns for
-
       64x64->128-bit multiplication.  AVX2 currently only have vector
-
       insns for 4 32x32->64-bit multiplication and for 1
-
       64x64->128-bit multiplication (pclmulqdq).  */
-
#if defined (MUM_V1) || defined (MUM_V2)
+
       64x64->128-bit multiplication.  AVX2 currently only have a
+
       vector insn for 4 32x32->64-bit multiplication.  */
    for (i = 0; i < _MUM_UNROLL_FACTOR; i++)
      result ^= _mum (_mum_le (((uint64_t *) str)[i]), _mum_primes[i]);
-
#else
-
    for (i = 0; i < _MUM_UNROLL_FACTOR; i += 2)
-
      result ^= _mum (_mum_le (((uint64_t *) str)[i]) ^ _mum_primes[i],
-
		      _mum_le (((uint64_t *) str)[i + 1]) ^ _mum_primes[i + 1]);
-
#endif
    len -= _MUM_UNROLL_FACTOR * sizeof (uint64_t);
    str += _MUM_UNROLL_FACTOR * sizeof (uint64_t);
    /* We will use the same prime numbers on the next iterations --
@@ -258,18 +235,20 @@ _mum_hash_aligned (uint64_t start, const void *key, size_t len) {
    result = _mum (result, _mum_unroll_prime);
  }
  n = len / sizeof (uint64_t);
-
  for (i = 0; i < n; i++)
+
  for (i = 0; i < (int)n; i++)
    result ^= _mum (_mum_le (((uint64_t *) str)[i]), _mum_primes[i]);
  len -= n * sizeof (uint64_t); str += n * sizeof (uint64_t);
  switch (len) {
  case 7:
    u64 = _mum_le32 (*(uint32_t *) str);
-
    u64 |= _mum_le16 (*(uint16_t *) (str + 4)) << 32;
+
    u64 |= (uint64_t) str[4] << 32;
+
    u64 |= (uint64_t) str[5] << 40;
    u64 |= (uint64_t) str[6] << 48;
    return result ^ _mum (u64, _mum_tail_prime);
  case 6:
    u64 = _mum_le32 (*(uint32_t *) str);
-
    u64 |= _mum_le16 (*(uint16_t *) (str + 4)) << 32;
+
    u64 |= (uint64_t) str[4] << 32;
+
    u64 |= (uint64_t) str[5] << 40;
    return result ^ _mum (u64, _mum_tail_prime);
  case 5:
    u64 = _mum_le32 (*(uint32_t *) str);
@@ -279,11 +258,13 @@ _mum_hash_aligned (uint64_t start, const void *key, size_t len) {
    u64 = _mum_le32 (*(uint32_t *) str);
    return result ^ _mum (u64, _mum_tail_prime);
  case 3:
-
    u64 = _mum_le16 (*(uint16_t *) str);
+
    u64 = str[0];
+
    u64 |= (uint64_t) str[1] << 8;
    u64 |= (uint64_t) str[2] << 16;
    return result ^ _mum (u64, _mum_tail_prime);
  case 2:
-
    u64 = _mum_le16 (*(uint16_t *) str);
+
    u64 = str[0];
+
    u64 |= (uint64_t) str[1] << 8;
    return result ^ _mum (u64, _mum_tail_prime);
  case 1:
    u64 = str[0];
@@ -295,23 +276,28 @@ _mum_hash_aligned (uint64_t start, const void *key, size_t len) {
/* Final randomization of H.  */
static inline uint64_t
_mum_final (uint64_t h) {
-
#if defined (MUM_V1)
  h ^= _mum (h, _mum_finish_prime1);
  h ^= _mum (h, _mum_finish_prime2);
-
#elif defined (MUM_V2)
-
  h ^= _mum_rotl (h, 33);
-
  h ^= _mum (h, _mum_finish_prime1);
-
#else
-
  h = _mum (h, h);
-
#endif
  return h;
}

+
#if defined(__x86_64__) && defined(_MUM_FRESH_GCC)
+

+
/* We want to use AVX2 insn MULX instead of generic x86-64 MULQ where
+
   it is possible.  Although on modern Intel processors MULQ takes
+
   3-cycles vs. 4 for MULX, MULX permits more freedom in insn
+
   scheduling as it uses less fixed registers.  */
+
static inline uint64_t _MUM_TARGET("arch=haswell")
+
_mum_hash_avx2 (const void * key, size_t len, uint64_t seed) {
+
  return _mum_final (_mum_hash_aligned (seed + len, key, len));
+
}
+
#endif
+

#ifndef _MUM_UNALIGNED_ACCESS
#if defined(__x86_64__) || defined(__i386__) || defined(__PPC64__) \
    || defined(__s390__) || defined(__m32c__) || defined(cris)     \
    || defined(__CR16__) || defined(__vax__) || defined(__m68k__) \
-
    || defined(__aarch64__) || defined(_M_AMD64) || defined(_M_IX86)
+
    || defined(__aarch64__)
#define _MUM_UNALIGNED_ACCESS 1
#else
#define _MUM_UNALIGNED_ACCESS 0
@@ -338,9 +324,9 @@ _mum_hash_default (const void *key, size_t len, uint64_t seed) {
  const unsigned char *str = (const unsigned char *) key;
  size_t block_len;
  uint64_t buf[_MUM_BLOCK_LEN / sizeof (uint64_t)];
-
  
+

  result = seed + len;
-
  if (((size_t) str & 0x7) == 0)
+
  if (_MUM_UNALIGNED_ACCESS || ((size_t) str & 0x7) == 0)
    result = _mum_hash_aligned (result, key, len);
  else {
    while (len != 0) {
@@ -358,7 +344,7 @@ static inline uint64_t
_mum_next_factor (void) {
  uint64_t start = 0;
  int i;
-
  
+

  for (i = 0; i < 8; i++)
    start = (start << 8) | rand() % 256;
  return start;
@@ -369,7 +355,7 @@ _mum_next_factor (void) {
/* Set random multiplicators depending on SEED.  */
static inline void
mum_hash_randomize (uint64_t seed) {
-
  size_t i;
+
  int i;

  srand (seed);
  _mum_hash_step_prime = _mum_next_factor ();
@@ -379,7 +365,7 @@ mum_hash_randomize (uint64_t seed) {
  _mum_block_start_prime = _mum_next_factor ();
  _mum_unroll_prime = _mum_next_factor ();
  _mum_tail_prime = _mum_next_factor ();
-
  for (i = 0; i < sizeof (_mum_primes) / sizeof (uint64_t); i++)
+
  for (i = 0; i < (int)(sizeof (_mum_primes) / sizeof (uint64_t)); i++)
    _mum_primes[i] = _mum_next_factor ();
}

@@ -391,7 +377,8 @@ mum_hash_init (uint64_t seed) {

/* Process data KEY with the state H and return the updated state.  */
static inline uint64_t
-
mum_hash_step (uint64_t h, uint64_t key) {
+
mum_hash_step (uint64_t h, uint64_t key)
+
{
  return _mum (h, _mum_hash_step_prime) ^ _mum (key, _mum_key_step_prime);
}

@@ -409,14 +396,22 @@ mum_hash64 (uint64_t key, uint64_t seed) {
}

/* Hash data KEY of length LEN and SEED.  The hash depends on the
-
   target endianess and the unroll factor.  */
+
   target endianness and the unroll factor.  */
static inline uint64_t
mum_hash (const void *key, size_t len, uint64_t seed) {
-
#if _MUM_UNALIGNED_ACCESS
-
  return _mum_final (_mum_hash_aligned (seed + len, key, len));
-
#else
-
  return _mum_hash_default (key, len, seed);
+
#if defined(__x86_64__) && defined(_MUM_FRESH_GCC)
+
  static int avx2_support = 0;
+

+
  if (avx2_support > 0)
+
    return _mum_hash_avx2 (key, len, seed);
+
  else if (! avx2_support) {
+
    __builtin_cpu_init ();
+
    avx2_support =  __builtin_cpu_supports ("avx2") ? 1 : -1;
+
    if (avx2_support > 0)
+
      return _mum_hash_avx2 (key, len, seed);
+
  }
#endif
+
  return _mum_hash_default (key, len, seed);
}

#endif
modified external/libucl/src/ucl_emitter.c
@@ -1,25 +1,4 @@
-
/* Copyright (c) 2013, Vsevolod Stakhov
-
 * All rights reserved.
-
 *
-
 * Redistribution and use in source and binary forms, with or without
-
 * modification, are permitted provided that the following conditions are met:
-
 *       * Redistributions of source code must retain the above copyright
-
 *         notice, this list of conditions and the following disclaimer.
-
 *       * Redistributions in binary form must reproduce the above copyright
-
 *         notice, this list of conditions and the following disclaimer in the
-
 *         documentation and/or other materials provided with the distribution.
-
 *
-
 * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
-
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-
 * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
-
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
 */
+


#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -47,9 +26,9 @@ static void ucl_emitter_common_elt (struct ucl_emitter_context *ctx,
	static void ucl_emit_ ## type ## _elt (struct ucl_emitter_context *ctx,	\
		const ucl_object_t *obj, bool first, bool print_key);	\
	static void ucl_emit_ ## type ## _start_obj (struct ucl_emitter_context *ctx,	\
-
		const ucl_object_t *obj, bool print_key);	\
+
		const ucl_object_t *obj, bool first, bool print_key);	\
	static void ucl_emit_ ## type## _start_array (struct ucl_emitter_context *ctx,	\
-
		const ucl_object_t *obj, bool print_key);	\
+
		const ucl_object_t *obj, bool first, bool print_key);	\
	static void ucl_emit_ ##type## _end_object (struct ucl_emitter_context *ctx,	\
		const ucl_object_t *obj);	\
	static void ucl_emit_ ##type## _end_array (struct ucl_emitter_context *ctx,	\
@@ -248,12 +227,18 @@ ucl_emitter_common_end_array (struct ucl_emitter_context *ctx,
 */
static void
ucl_emitter_common_start_array (struct ucl_emitter_context *ctx,
-
		const ucl_object_t *obj, bool print_key, bool compact)
+
		const ucl_object_t *obj, bool first, bool print_key, bool compact)
{
	const ucl_object_t *cur;
	ucl_object_iter_t iter = NULL;
	const struct ucl_emitter_functions *func = ctx->func;
-
	bool first = true;
+
	bool first_key = true;
+

+
	if (ctx->id != UCL_EMIT_CONFIG && !first) {
+
		if (ctx->id == UCL_EMIT_YAML && ctx->indent == 0) {
+
			func->ucl_emitter_append_len ("\n", 1, func->ud);
+
		}
+
	}

	ucl_emitter_print_key (print_key, ctx, obj, compact);

@@ -269,16 +254,16 @@ ucl_emitter_common_start_array (struct ucl_emitter_context *ctx,
	if (obj->type == UCL_ARRAY) {
		/* explicit array */
		while ((cur = ucl_object_iterate (obj, &iter, true)) != NULL) {
-
			ucl_emitter_common_elt (ctx, cur, first, false, compact);
-
			first = false;
+
			ucl_emitter_common_elt (ctx, cur, first_key, false, compact);
+
			first_key = false;
		}
	}
	else {
		/* implicit array */
		cur = obj;
		while (cur) {
-
			ucl_emitter_common_elt (ctx, cur, first, false, compact);
-
			first = false;
+
			ucl_emitter_common_elt (ctx, cur, first_key, false, compact);
+
			first_key = false;
			cur = cur->next;
		}
	}
@@ -294,12 +279,18 @@ ucl_emitter_common_start_array (struct ucl_emitter_context *ctx,
 */
static void
ucl_emitter_common_start_object (struct ucl_emitter_context *ctx,
-
		const ucl_object_t *obj, bool print_key, bool compact)
+
		const ucl_object_t *obj, bool first, bool print_key, bool compact)
{
	ucl_hash_iter_t it = NULL;
	const ucl_object_t *cur, *elt;
	const struct ucl_emitter_functions *func = ctx->func;
-
	bool first = true;
+
	bool first_key = true;
+

+
	if (ctx->id != UCL_EMIT_CONFIG && !first) {
+
		if (ctx->id == UCL_EMIT_YAML && ctx->indent == 0) {
+
			func->ucl_emitter_append_len ("\n", 1, func->ud);
+
		}
+
	}

	ucl_emitter_print_key (print_key, ctx, obj, compact);
	/*
@@ -320,13 +311,13 @@ ucl_emitter_common_start_object (struct ucl_emitter_context *ctx,

		if (ctx->id == UCL_EMIT_CONFIG) {
			LL_FOREACH (cur, elt) {
-
				ucl_emitter_common_elt (ctx, elt, first, true, compact);
+
				ucl_emitter_common_elt (ctx, elt, first_key, true, compact);
			}
		}
		else {
			/* Expand implicit arrays */
			if (cur->next != NULL) {
-
				if (!first) {
+
				if (!first_key) {
					if (compact) {
						func->ucl_emitter_append_character (',', 1, func->ud);
					}
@@ -335,15 +326,15 @@ ucl_emitter_common_start_object (struct ucl_emitter_context *ctx,
					}
				}
				ucl_add_tabs (func, ctx->indent, compact);
-
				ucl_emitter_common_start_array (ctx, cur, true, compact);
+
				ucl_emitter_common_start_array (ctx, cur, first_key, true, compact);
				ucl_emitter_common_end_array (ctx, cur, compact);
			}
			else {
-
				ucl_emitter_common_elt (ctx, cur, first, true, compact);
+
				ucl_emitter_common_elt (ctx, cur, first_key, true, compact);
			}
		}

-
		first = false;
+
		first_key = false;
	}
}

@@ -367,13 +358,15 @@ ucl_emitter_common_elt (struct ucl_emitter_context *ctx,

	if (ctx->id != UCL_EMIT_CONFIG && !first) {
		if (compact) {
-
			func->ucl_emitter_append_character (',', 1, func->ud);
+
			if (ctx->indent > 0)
+
				func->ucl_emitter_append_character (',', 1, func->ud);
		}
		else {
			if (ctx->id == UCL_EMIT_YAML && ctx->indent == 0) {
				func->ucl_emitter_append_len ("\n", 1, func->ud);
			} else {
-
				func->ucl_emitter_append_len (",\n", 2, func->ud);
+
				if (ctx->indent > 0)
+
					func->ucl_emitter_append_len (",\n", 2, func->ud);
			}
		}
	}
@@ -446,11 +439,11 @@ ucl_emitter_common_elt (struct ucl_emitter_context *ctx,
		ucl_emitter_finish_object (ctx, obj, compact, !print_key);
		break;
	case UCL_OBJECT:
-
		ucl_emitter_common_start_object (ctx, obj, print_key, compact);
+
		ucl_emitter_common_start_object (ctx, obj, true, print_key, compact);
		ucl_emitter_common_end_object (ctx, obj, compact);
		break;
	case UCL_ARRAY:
-
		ucl_emitter_common_start_array (ctx, obj, print_key, compact);
+
		ucl_emitter_common_start_array (ctx, obj, true, print_key, compact);
		ucl_emitter_common_end_array (ctx, obj, compact);
		break;
	case UCL_USERDATA:
@@ -490,12 +483,12 @@ ucl_emitter_common_elt (struct ucl_emitter_context *ctx,
		ucl_emitter_common_elt (ctx, obj, first, print_key, (compact));	\
	}	\
	static void ucl_emit_ ## type ## _start_obj (struct ucl_emitter_context *ctx,	\
-
		const ucl_object_t *obj, bool print_key) {	\
-
		ucl_emitter_common_start_object (ctx, obj, print_key, (compact));	\
+
		const ucl_object_t *obj, bool first, bool print_key) {	\
+
		ucl_emitter_common_start_object (ctx, obj, first, print_key, (compact));	\
	}	\
	static void ucl_emit_ ## type## _start_array (struct ucl_emitter_context *ctx,	\
-
		const ucl_object_t *obj, bool print_key) {	\
-
		ucl_emitter_common_start_array (ctx, obj, print_key, (compact));	\
+
		const ucl_object_t *obj, bool first, bool print_key) {	\
+
		ucl_emitter_common_start_array (ctx, obj, first, print_key, (compact));	\
	}	\
	static void ucl_emit_ ##type## _end_object (struct ucl_emitter_context *ctx,	\
		const ucl_object_t *obj) {	\
@@ -513,7 +506,7 @@ UCL_EMIT_TYPE_IMPL(yaml, false)

static void
ucl_emit_msgpack_elt (struct ucl_emitter_context *ctx,
-
		const ucl_object_t *obj, bool first, bool print_key)
+
		const ucl_object_t *obj, bool _first, bool print_key)
{
	ucl_object_iter_t it;
	struct ucl_object_userdata *ud;
@@ -556,7 +549,7 @@ ucl_emit_msgpack_elt (struct ucl_emitter_context *ctx,

	case UCL_OBJECT:
		ucl_emitter_print_key_msgpack (print_key, ctx, obj);
-
		ucl_emit_msgpack_start_obj (ctx, obj, print_key);
+
		ucl_emit_msgpack_start_obj (ctx, obj, false, print_key);
		it = NULL;

		while ((cur = ucl_object_iterate (obj, &it, true)) != NULL) {
@@ -575,7 +568,7 @@ ucl_emit_msgpack_elt (struct ucl_emitter_context *ctx,

	case UCL_ARRAY:
		ucl_emitter_print_key_msgpack (print_key, ctx, obj);
-
		ucl_emit_msgpack_start_array (ctx, obj, print_key);
+
		ucl_emit_msgpack_start_array (ctx, obj, false, print_key);
		it = NULL;

		while ((cur = ucl_object_iterate (obj, &it, true)) != NULL) {
@@ -601,14 +594,14 @@ ucl_emit_msgpack_elt (struct ucl_emitter_context *ctx,

static void
ucl_emit_msgpack_start_obj (struct ucl_emitter_context *ctx,
-
		const ucl_object_t *obj, bool print_key)
+
		const ucl_object_t *obj, bool _first, bool _print_key)
{
	ucl_emitter_print_object_msgpack (ctx, obj->len);
}

static void
ucl_emit_msgpack_start_array (struct ucl_emitter_context *ctx,
-
		const ucl_object_t *obj, bool print_key)
+
		const ucl_object_t *obj, bool _first, bool _print_key)
{
	ucl_emitter_print_array_msgpack (ctx, obj->len);
}
modified external/libucl/src/ucl_emitter_streamline.c
@@ -103,18 +103,19 @@ ucl_object_emit_streamline_start_container (struct ucl_emitter_context *ctx,
	top = sctx->containers;
	st = malloc (sizeof (*st));
	if (st != NULL) {
-
		if (top != NULL && !top->is_array) {
+
		st->empty = true;
+
		if (top && !top->is_array) {
			print_key = true;
		}
-
		st->empty = true;
+

		st->obj = obj;
		if (obj != NULL && obj->type == UCL_ARRAY) {
			st->is_array = true;
-
			sctx->ops->ucl_emitter_start_array (ctx, obj, print_key);
+
			sctx->ops->ucl_emitter_start_array (ctx, obj, top == NULL, print_key);
		}
		else {
			st->is_array = false;
-
			sctx->ops->ucl_emitter_start_object (ctx, obj, print_key);
+
			sctx->ops->ucl_emitter_start_object (ctx, obj, top == NULL, print_key);
		}
		LL_PREPEND (sctx->containers, st);
	}
modified external/libucl/src/ucl_parser.c
@@ -833,12 +833,12 @@ ucl_maybe_parse_number (ucl_object_t *obj,
	}

	char numbuf[128];
-
	
+

	if ((size_t)(p - c + 1) >= sizeof(numbuf)) {
		*pos = start;
		return EINVAL;
	}
-
	
+

	if (is_neg) {
		numbuf[0] = '-';
		ucl_strlcpy (&numbuf[1], c, p - c + 1);
@@ -846,7 +846,7 @@ ucl_maybe_parse_number (ucl_object_t *obj,
	else {
		ucl_strlcpy (numbuf, c, p - c + 1);
	}
-
	
+

	errno = 0;
	if (need_double) {
		dv = strtod (numbuf, &endptr);
@@ -879,6 +879,7 @@ ucl_maybe_parse_number (ucl_object_t *obj,
	}

	if (endptr < end && endptr != start) {
+
		p = endptr;
		switch (*p) {
		case 'm':
		case 'M':
modified external/libucl/src/ucl_util.c
@@ -3089,13 +3089,13 @@ ucl_object_type (const ucl_object_t *obj)
ucl_object_t*
ucl_object_fromstring (const char *str)
{
-
	return ucl_object_fromstring_common (str, 0, UCL_STRING_ESCAPE);
+
	return ucl_object_fromstring_common (str, 0, UCL_STRING_RAW);
}

ucl_object_t *
ucl_object_fromlstring (const char *str, size_t len)
{
-
	return ucl_object_fromstring_common (str, len, UCL_STRING_ESCAPE);
+
	return ucl_object_fromstring_common (str, len, UCL_STRING_RAW);
}

ucl_object_t *
deleted external/libucl/stamp-h.in
@@ -1 +0,0 @@
-
timestamp
deleted external/libucl/tests/schema/definitions.json
@@ -1,32 +0,0 @@
-
[
-
    {
-
        "description": "valid definition",
-
        "schema": {"$ref": "http://highsecure.ru/ucl-schema/schema#"},
-
        "tests": [
-
            {
-
                "description": "valid definition schema",
-
                "data": {
-
                    "definitions": {
-
                        "foo": {"type": "integer"}
-
                    }
-
                },
-
                "valid": true
-
            }
-
        ]
-
    },
-
    {
-
        "description": "invalid definition",
-
        "schema": {"$ref": "http://highsecure.ru/ucl-schema/schema#"},
-
        "tests": [
-
            {
-
                "description": "invalid definition schema",
-
                "data": {
-
                    "definitions": {
-
                        "foo": {"type": 1}
-
                    }
-
                },
-
                "valid": false
-
            }
-
        ]
-
    }
-
]
modified external/libucl/tests/schema/ref.json
@@ -124,21 +124,5 @@
                "valid": false
            }
        ]
-
    },
-
    {
-
        "description": "remote ref, containing refs itself",
-
        "schema": {"$ref": "http://highsecure.ru/ucl-schema/schema#"},
-
        "tests": [
-
            {
-
                "description": "remote ref valid",
-
                "data": {"minLength": 1},
-
                "valid": true
-
            },
-
            {
-
                "description": "remote ref invalid",
-
                "data": {"minLength": -1},
-
                "valid": false
-
            }
-
        ]
    }
]
deleted external/libucl/tests/schema/refRemote.json
@@ -1,76 +0,0 @@
-
[
-
    {
-
        "description": "remote ref",
-
        "schema": {"$ref": "http://highsecure.ru/ucl-schema/remotes/integer.json"},
-
        "tests": [
-
            {
-
                "description": "remote ref valid",
-
                "data": 1,
-
                "valid": true
-
            },
-
            {
-
                "description": "remote ref invalid",
-
                "data": "a",
-
                "valid": false
-
            }
-
        ]
-
    },
-
    {
-
        "description": "fragment within remote ref",
-
        "schema": {"$ref": "http://highsecure.ru/ucl-schema/remotes/subSchemas.json#/integer"},
-
        "tests": [
-
            {
-
                "description": "remote fragment valid",
-
                "data": 1,
-
                "valid": true
-
            },
-
            {
-
                "description": "remote fragment invalid",
-
                "data": "a",
-
                "valid": false
-
            }
-
        ]
-
    },
-
    {
-
        "description": "ref within remote ref",
-
        "schema": {
-
            "$ref": "http://highsecure.ru/ucl-schema/remotes/subSchemas.json#/refToInteger"
-
        },
-
        "tests": [
-
            {
-
                "description": "ref within ref valid",
-
                "data": 1,
-
                "valid": true
-
            },
-
            {
-
                "description": "ref within ref invalid",
-
                "data": "a",
-
                "valid": false
-
            }
-
        ]
-
    }
-
/*
-
    {
-
        "description": "change resolution scope",
-
        "schema": {
-
            "id": "http://highsecure.ru/ucl-schema/remotes/",
-
            "items": {
-
                "id": "folder/",
-
                "items": {"$ref": "folderInteger.json"}
-
            }
-
        },
-
        "tests": [
-
            {
-
                "description": "changed scope ref valid",
-
                "data": [[1]],
-
                "valid": true
-
            },
-
            {
-
                "description": "changed scope ref invalid",
-
                "data": [["a"]],
-
                "valid": false
-
            }
-
        ]
-
    }
-
*/
-
]
modified external/libucl/tests/test_speed.c
@@ -44,7 +44,7 @@ get_ticks (void)
{
	double res;

-
#ifdef __APPLE__
+
#if defined(__APPLE__) && defined(HAVE_MACH_MACH_TIME_H)
	res = mach_absolute_time () / 1000000000.;
#else
	struct timespec ts;
modified external/libucl/tests/test_streamline.c
@@ -26,6 +26,10 @@
#include <assert.h>
#include "ucl.h"

+
#include <sys/types.h>
+
#include <fcntl.h>
+
#include <unistd.h>
+

int
main (int argc, char **argv)
{
@@ -34,7 +38,28 @@ main (int argc, char **argv)
	const char *fname_out = NULL;
	struct ucl_emitter_context *ctx;
	struct ucl_emitter_functions *f;
-
	int ret = 0;
+
	int ret = 0, opt, json = 0, compact = 0, yaml = 0;
+

+
	while ((opt = getopt(argc, argv, "jcy")) != -1) {
+
		switch (opt) {
+
		case 'j':
+
			json = 1;
+
			break;
+
		case 'c':
+
			compact = 1;
+
			break;
+
		case 'y':
+
			yaml = 1;
+
			break;
+
		default: /* '?' */
+
			fprintf (stderr, "Usage: %s [-jcy] [out]\n",
+
				argv[0]);
+
			exit (EXIT_FAILURE);
+
		}
+
	}
+

+
	argc -= optind;
+
	argv += optind;

	switch (argc) {
	case 2:
@@ -63,7 +88,21 @@ main (int argc, char **argv)
	ucl_object_insert_key (obj, cur, "key3", 0, false);

	f = ucl_object_emit_file_funcs (out);
-
	ctx = ucl_object_emit_streamline_new (obj, UCL_EMIT_CONFIG, f);
+

+
	if (yaml) {
+
		ctx = ucl_object_emit_streamline_new (obj, UCL_EMIT_YAML, f);
+
	}
+
	else if (json) {
+
		if (compact) {
+
			ctx = ucl_object_emit_streamline_new (obj, UCL_EMIT_JSON_COMPACT, f);
+
		}
+
		else {
+
			ctx = ucl_object_emit_streamline_new (obj, UCL_EMIT_JSON, f);
+
		}
+
	}
+
	else {
+
		ctx = ucl_object_emit_streamline_new (obj, UCL_EMIT_CONFIG, f);
+
	}

	assert (ctx != NULL);

modified external/libucl/uthash/utlist.h
@@ -1,5 +1,5 @@
/*
-
Copyright (c) 2007-2013, Troy D. Hanson   http://troydhanson.github.com/uthash/
+
Copyright (c) 2007-2022, Troy D. Hanson  https://troydhanson.github.io/uthash/
All rights reserved.

Redistribution and use in source and binary forms, with or without
@@ -24,11 +24,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef UTLIST_H
#define UTLIST_H

-
#define UTLIST_VERSION 1.9.8
+
#define UTLIST_VERSION 2.3.0

#include <assert.h>

-
/* 
+
/*
 * This file contains macros to manipulate singly and doubly-linked lists.
 *
 * 1. LL_ macros:  singly-linked lists.
@@ -38,7 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * To use singly-linked lists, your structure must have a "next" pointer.
 * To use doubly-linked lists, your structure must "prev" and "next" pointers.
 * Either way, the pointer to the head of the list must be initialized to NULL.
-
 * 
+
 *
 * ----------------.EXAMPLE -------------------------
 * struct item {
 *      int id;
@@ -61,41 +61,46 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/* These macros use decltype or the earlier __typeof GNU extension.
   As decltype is only available in newer compilers (VS2010 or gcc 4.3+
-
   when compiling c++ code), this code uses whatever method is needed
+
   when compiling c++ source) this code uses whatever method is needed
   or, for VS2008 where neither is available, uses casting workarounds. */
-
#ifdef _MSC_VER            /* MS compiler */
+
#if !defined(LDECLTYPE) && !defined(NO_DECLTYPE)
+
#if defined(_MSC_VER)   /* MS compiler */
#if _MSC_VER >= 1600 && defined(__cplusplus)  /* VS2010 or newer in C++ mode */
#define LDECLTYPE(x) decltype(x)
-
#else                     /* VS2008 or older (or VS2010 in C mode) */
+
#else                   /* VS2008 or older (or VS2010 in C mode) */
#define NO_DECLTYPE
-
#define LDECLTYPE(x) char*
#endif
-
#elif defined(__ICCARM__)
+
#elif defined(__MCST__)  /* Elbrus C Compiler */
+
#define LDECLTYPE(x) __typeof(x)
+
#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__)
#define NO_DECLTYPE
-
#define LDECLTYPE(x) char*
-
#else                      /* GNU, Sun and other compilers */
+
#else                   /* GNU, Sun and other compilers */
#define LDECLTYPE(x) __typeof(x)
#endif
+
#endif

/* for VS2008 we use some workarounds to get around the lack of decltype,
 * namely, we always reassign our tmp variable to the list head if we need
 * to dereference its prev/next pointers, and save/restore the real head.*/
#ifdef NO_DECLTYPE
-
#define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
-
#define _NEXT(elt,list,next) ((char*)((list)->next))
-
#define _NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
-
/* #define _PREV(elt,list,prev) ((char*)((list)->prev)) */
-
#define _PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
-
#define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
-
#define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
-
#else 
-
#define _SV(elt,list)
-
#define _NEXT(elt,list,next) ((elt)->next)
-
#define _NEXTASGN(elt,list,to,next) ((elt)->next)=(to)
-
/* #define _PREV(elt,list,prev) ((elt)->prev) */
-
#define _PREVASGN(elt,list,to,prev) ((elt)->prev)=(to)
-
#define _RS(list)
-
#define _CASTASGN(a,b) (a)=(b)
+
#define IF_NO_DECLTYPE(x) x
+
#define LDECLTYPE(x) char*
+
#define UTLIST_SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
+
#define UTLIST_NEXT(elt,list,next) ((char*)((list)->next))
+
#define UTLIST_NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
+
/* #define UTLIST_PREV(elt,list,prev) ((char*)((list)->prev)) */
+
#define UTLIST_PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
+
#define UTLIST_RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
+
#define UTLIST_CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
+
#else
+
#define IF_NO_DECLTYPE(x)
+
#define UTLIST_SV(elt,list)
+
#define UTLIST_NEXT(elt,list,next) ((elt)->next)
+
#define UTLIST_NEXTASGN(elt,list,to,next) ((elt)->next)=(to)
+
/* #define UTLIST_PREV(elt,list,prev) ((elt)->prev) */
+
#define UTLIST_PREVASGN(elt,list,to,prev) ((elt)->prev)=(to)
+
#define UTLIST_RS(list)
+
#define UTLIST_CASTASGN(a,b) (a)=(b)
#endif

/******************************************************************************
@@ -111,13 +116,14 @@ do {
  LDECLTYPE(list) _ls_q;                                                                       \
  LDECLTYPE(list) _ls_e;                                                                       \
  LDECLTYPE(list) _ls_tail;                                                                    \
+
  IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;)                                                        \
  int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping;                       \
  if (list) {                                                                                  \
    _ls_insize = 1;                                                                            \
    _ls_looping = 1;                                                                           \
    while (_ls_looping) {                                                                      \
-
      _CASTASGN(_ls_p,list);                                                                   \
-
      list = NULL;                                                                             \
+
      UTLIST_CASTASGN(_ls_p,list);                                                             \
+
      (list) = NULL;                                                                           \
      _ls_tail = NULL;                                                                         \
      _ls_nmerges = 0;                                                                         \
      while (_ls_p) {                                                                          \
@@ -126,35 +132,35 @@ do {
        _ls_psize = 0;                                                                         \
        for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) {                                         \
          _ls_psize++;                                                                         \
-
          _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list);                          \
+
          UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list);        \
          if (!_ls_q) break;                                                                   \
        }                                                                                      \
        _ls_qsize = _ls_insize;                                                                \
        while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) {                                    \
          if (_ls_psize == 0) {                                                                \
-
            _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
-
              _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
+
            _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q =                                      \
+
              UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--;                      \
          } else if (_ls_qsize == 0 || !_ls_q) {                                               \
-
            _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
-
              _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
+
            _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p =                                      \
+
              UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--;                      \
          } else if (cmp(_ls_p,_ls_q) <= 0) {                                                  \
-
            _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
-
              _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
+
            _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p =                                      \
+
              UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--;                      \
          } else {                                                                             \
-
            _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
-
              _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
+
            _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q =                                      \
+
              UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--;                      \
          }                                                                                    \
          if (_ls_tail) {                                                                      \
-
            _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list);                \
+
            UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \
          } else {                                                                             \
-
            _CASTASGN(list,_ls_e);                                                             \
+
            UTLIST_CASTASGN(list,_ls_e);                                                       \
          }                                                                                    \
          _ls_tail = _ls_e;                                                                    \
        }                                                                                      \
        _ls_p = _ls_q;                                                                         \
      }                                                                                        \
      if (_ls_tail) {                                                                          \
-
        _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list);                     \
+
        UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list);   \
      }                                                                                        \
      if (_ls_nmerges <= 1) {                                                                  \
        _ls_looping=0;                                                                         \
@@ -174,13 +180,14 @@ do {
  LDECLTYPE(list) _ls_q;                                                                       \
  LDECLTYPE(list) _ls_e;                                                                       \
  LDECLTYPE(list) _ls_tail;                                                                    \
+
  IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;)                                                        \
  int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping;                       \
  if (list) {                                                                                  \
    _ls_insize = 1;                                                                            \
    _ls_looping = 1;                                                                           \
    while (_ls_looping) {                                                                      \
-
      _CASTASGN(_ls_p,list);                                                                   \
-
      list = NULL;                                                                             \
+
      UTLIST_CASTASGN(_ls_p,list);                                                             \
+
      (list) = NULL;                                                                           \
      _ls_tail = NULL;                                                                         \
      _ls_nmerges = 0;                                                                         \
      while (_ls_p) {                                                                          \
@@ -189,36 +196,36 @@ do {
        _ls_psize = 0;                                                                         \
        for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) {                                         \
          _ls_psize++;                                                                         \
-
          _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list);                          \
+
          UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list);        \
          if (!_ls_q) break;                                                                   \
        }                                                                                      \
        _ls_qsize = _ls_insize;                                                                \
-
        while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) {                                    \
+
        while ((_ls_psize > 0) || ((_ls_qsize > 0) && _ls_q)) {                                \
          if (_ls_psize == 0) {                                                                \
-
            _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
-
              _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
-
          } else if (_ls_qsize == 0 || !_ls_q) {                                               \
-
            _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
-
              _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
+
            _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q =                                      \
+
              UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--;                      \
+
          } else if ((_ls_qsize == 0) || (!_ls_q)) {                                           \
+
            _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p =                                      \
+
              UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--;                      \
          } else if (cmp(_ls_p,_ls_q) <= 0) {                                                  \
-
            _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
-
              _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
+
            _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p =                                      \
+
              UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--;                      \
          } else {                                                                             \
-
            _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
-
              _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
+
            _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q =                                      \
+
              UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--;                      \
          }                                                                                    \
          if (_ls_tail) {                                                                      \
-
            _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list);                \
+
            UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \
          } else {                                                                             \
-
            _CASTASGN(list,_ls_e);                                                             \
+
            UTLIST_CASTASGN(list,_ls_e);                                                       \
          }                                                                                    \
-
          _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list);                     \
+
          UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list);   \
          _ls_tail = _ls_e;                                                                    \
        }                                                                                      \
        _ls_p = _ls_q;                                                                         \
      }                                                                                        \
-
      _CASTASGN(list->prev, _ls_tail);                                                         \
-
      _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list);                       \
+
      UTLIST_CASTASGN((list)->prev, _ls_tail);                                                 \
+
      UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list);     \
      if (_ls_nmerges <= 1) {                                                                  \
        _ls_looping=0;                                                                         \
      }                                                                                        \
@@ -243,9 +250,9 @@ do {
    _ls_insize = 1;                                                                            \
    _ls_looping = 1;                                                                           \
    while (_ls_looping) {                                                                      \
-
      _CASTASGN(_ls_p,list);                                                                   \
-
      _CASTASGN(_ls_oldhead,list);                                                             \
-
      list = NULL;                                                                             \
+
      UTLIST_CASTASGN(_ls_p,list);                                                             \
+
      UTLIST_CASTASGN(_ls_oldhead,list);                                                       \
+
      (list) = NULL;                                                                           \
      _ls_tail = NULL;                                                                         \
      _ls_nmerges = 0;                                                                         \
      while (_ls_p) {                                                                          \
@@ -254,47 +261,47 @@ do {
        _ls_psize = 0;                                                                         \
        for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) {                                         \
          _ls_psize++;                                                                         \
-
          _SV(_ls_q,list);                                                                     \
-
          if (_NEXT(_ls_q,list,next) == _ls_oldhead) {                                         \
+
          UTLIST_SV(_ls_q,list);                                                               \
+
          if (UTLIST_NEXT(_ls_q,list,next) == _ls_oldhead) {                                   \
            _ls_q = NULL;                                                                      \
          } else {                                                                             \
-
            _ls_q = _NEXT(_ls_q,list,next);                                                    \
+
            _ls_q = UTLIST_NEXT(_ls_q,list,next);                                              \
          }                                                                                    \
-
          _RS(list);                                                                           \
+
          UTLIST_RS(list);                                                                     \
          if (!_ls_q) break;                                                                   \
        }                                                                                      \
        _ls_qsize = _ls_insize;                                                                \
        while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) {                                    \
          if (_ls_psize == 0) {                                                                \
-
            _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
-
              _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
+
            _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q =                                      \
+
              UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--;                      \
            if (_ls_q == _ls_oldhead) { _ls_q = NULL; }                                        \
          } else if (_ls_qsize == 0 || !_ls_q) {                                               \
-
            _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
-
              _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
+
            _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p =                                      \
+
              UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--;                      \
            if (_ls_p == _ls_oldhead) { _ls_p = NULL; }                                        \
          } else if (cmp(_ls_p,_ls_q) <= 0) {                                                  \
-
            _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
-
              _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
+
            _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p =                                      \
+
              UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--;                      \
            if (_ls_p == _ls_oldhead) { _ls_p = NULL; }                                        \
          } else {                                                                             \
-
            _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
-
              _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
+
            _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q =                                      \
+
              UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--;                      \
            if (_ls_q == _ls_oldhead) { _ls_q = NULL; }                                        \
          }                                                                                    \
          if (_ls_tail) {                                                                      \
-
            _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list);                \
+
            UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \
          } else {                                                                             \
-
            _CASTASGN(list,_ls_e);                                                             \
+
            UTLIST_CASTASGN(list,_ls_e);                                                       \
          }                                                                                    \
-
          _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list);                     \
+
          UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list);   \
          _ls_tail = _ls_e;                                                                    \
        }                                                                                      \
        _ls_p = _ls_q;                                                                         \
      }                                                                                        \
-
      _CASTASGN(list->prev,_ls_tail);                                                          \
-
      _CASTASGN(_tmp,list);                                                                    \
-
      _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp,next); _RS(list);                       \
+
      UTLIST_CASTASGN((list)->prev,_ls_tail);                                                  \
+
      UTLIST_CASTASGN(_tmp,list);                                                              \
+
      UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_tmp,next); UTLIST_RS(list);     \
      if (_ls_nmerges <= 1) {                                                                  \
        _ls_looping=0;                                                                         \
      }                                                                                        \
@@ -311,8 +318,8 @@ do {

#define LL_PREPEND2(head,add,next)                                                             \
do {                                                                                           \
-
  (add)->next = head;                                                                          \
-
  head = add;                                                                                  \
+
  (add)->next = (head);                                                                        \
+
  (head) = (add);                                                                              \
} while (0)

#define LL_CONCAT(head1,head2)                                                                 \
@@ -322,7 +329,7 @@ do {
do {                                                                                           \
  LDECLTYPE(head1) _tmp;                                                                       \
  if (head1) {                                                                                 \
-
    _tmp = head1;                                                                              \
+
    _tmp = (head1);                                                                            \
    while (_tmp->next) { _tmp = _tmp->next; }                                                  \
    _tmp->next=(head2);                                                                        \
  } else {                                                                                     \
@@ -338,7 +345,7 @@ do {
  LDECLTYPE(head) _tmp;                                                                        \
  (add)->next=NULL;                                                                            \
  if (head) {                                                                                  \
-
    _tmp = head;                                                                               \
+
    _tmp = (head);                                                                             \
    while (_tmp->next) { _tmp = _tmp->next; }                                                  \
    _tmp->next=(add);                                                                          \
  } else {                                                                                     \
@@ -346,96 +353,76 @@ do {
  }                                                                                            \
} while (0)

-
#define LL_DELETE(head,del)                                                                    \
-
    LL_DELETE2(head,del,next)
+
#define LL_INSERT_INORDER(head,add,cmp)                                                        \
+
    LL_INSERT_INORDER2(head,add,cmp,next)

-
#define LL_DELETE2(head,del,next)                                                              \
+
#define LL_INSERT_INORDER2(head,add,cmp,next)                                                  \
do {                                                                                           \
  LDECLTYPE(head) _tmp;                                                                        \
-
  if ((head) == (del)) {                                                                       \
-
    (head)=(head)->next;                                                                       \
+
  if (head) {                                                                                  \
+
    LL_LOWER_BOUND2(head, _tmp, add, cmp, next);                                               \
+
    LL_APPEND_ELEM2(head, _tmp, add, next);                                                    \
  } else {                                                                                     \
-
    _tmp = head;                                                                               \
-
    while (_tmp->next && (_tmp->next != (del))) {                                              \
-
      _tmp = _tmp->next;                                                                       \
-
    }                                                                                          \
-
    if (_tmp->next) {                                                                          \
-
      _tmp->next = ((del)->next);                                                              \
-
    }                                                                                          \
+
    (head) = (add);                                                                            \
+
    (head)->next = NULL;                                                                       \
  }                                                                                            \
} while (0)

-
/* Here are VS2008 replacements for LL_APPEND and LL_DELETE */
-
#define LL_APPEND_VS2008(head,add)                                                             \
-
    LL_APPEND2_VS2008(head,add,next)
+
#define LL_LOWER_BOUND(head,elt,like,cmp)                                                      \
+
    LL_LOWER_BOUND2(head,elt,like,cmp,next)

-
#define LL_APPEND2_VS2008(head,add,next)                                                       \
-
do {                                                                                           \
-
  if (head) {                                                                                  \
-
    (add)->next = head;     /* use add->next as a temp variable */                             \
-
    while ((add)->next->next) { (add)->next = (add)->next->next; }                             \
-
    (add)->next->next=(add);                                                                   \
-
  } else {                                                                                     \
-
    (head)=(add);                                                                              \
-
  }                                                                                            \
-
  (add)->next=NULL;                                                                            \
-
} while (0)
+
#define LL_LOWER_BOUND2(head,elt,like,cmp,next)                                                \
+
  do {                                                                                         \
+
    if ((head) == NULL || (cmp(head, like)) >= 0) {                                            \
+
      (elt) = NULL;                                                                            \
+
    } else {                                                                                   \
+
      for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) {                         \
+
        if (cmp((elt)->next, like) >= 0) {                                                     \
+
          break;                                                                               \
+
        }                                                                                      \
+
      }                                                                                        \
+
    }                                                                                          \
+
  } while (0)

-
#define LL_DELETE_VS2008(head,del)                                                             \
-
    LL_DELETE2_VS2008(head,del,next)
+
#define LL_DELETE(head,del)                                                                    \
+
    LL_DELETE2(head,del,next)

-
#define LL_DELETE2_VS2008(head,del,next)                                                       \
+
#define LL_DELETE2(head,del,next)                                                              \
do {                                                                                           \
+
  LDECLTYPE(head) _tmp;                                                                        \
  if ((head) == (del)) {                                                                       \
    (head)=(head)->next;                                                                       \
  } else {                                                                                     \
-
    char *_tmp = (char*)(head);                                                                \
-
    while ((head)->next && ((head)->next != (del))) {                                          \
-
      head = (head)->next;                                                                     \
-
    }                                                                                          \
-
    if ((head)->next) {                                                                        \
-
      (head)->next = ((del)->next);                                                            \
+
    _tmp = (head);                                                                             \
+
    while (_tmp->next && (_tmp->next != (del))) {                                              \
+
      _tmp = _tmp->next;                                                                       \
    }                                                                                          \
-
    {                                                                                          \
-
      char **_head_alias = (char**)&(head);                                                    \
-
      *_head_alias = _tmp;                                                                     \
+
    if (_tmp->next) {                                                                          \
+
      _tmp->next = (del)->next;                                                                \
    }                                                                                          \
  }                                                                                            \
} while (0)
-
#ifdef NO_DECLTYPE
-
#undef LL_APPEND
-
#define LL_APPEND LL_APPEND_VS2008
-
#undef LL_DELETE
-
#define LL_DELETE LL_DELETE_VS2008
-
#undef LL_DELETE2
-
#define LL_DELETE2 LL_DELETE2_VS2008
-
#undef LL_APPEND2
-
#define LL_APPEND2 LL_APPEND2_VS2008
-
#undef LL_CONCAT /* no LL_CONCAT_VS2008 */
-
#undef DL_CONCAT /* no DL_CONCAT_VS2008 */
-
#endif
-
/* end VS2008 replacements */

#define LL_COUNT(head,el,counter)                                                              \
    LL_COUNT2(head,el,counter,next)                                                            \

#define LL_COUNT2(head,el,counter,next)                                                        \
-
{                                                                                              \
-
    counter = 0;                                                                               \
-
    LL_FOREACH2(head,el,next){ ++counter; }                                                    \
-
}
+
do {                                                                                           \
+
  (counter) = 0;                                                                               \
+
  LL_FOREACH2(head,el,next) { ++(counter); }                                                   \
+
} while (0)

#define LL_FOREACH(head,el)                                                                    \
    LL_FOREACH2(head,el,next)

#define LL_FOREACH2(head,el,next)                                                              \
-
    for(el=head;el;el=(el)->next)
+
    for ((el) = (head); el; (el) = (el)->next)

#define LL_FOREACH_SAFE(head,el,tmp)                                                           \
    LL_FOREACH_SAFE2(head,el,tmp,next)

#define LL_FOREACH_SAFE2(head,el,tmp,next)                                                     \
-
  for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
+
  for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp))

#define LL_SEARCH_SCALAR(head,out,field,val)                                                   \
    LL_SEARCH_SCALAR2(head,out,field,val,next)
@@ -445,7 +432,7 @@ do {
    LL_FOREACH2(head,out,next) {                                                               \
      if ((out)->field == (val)) break;                                                        \
    }                                                                                          \
-
} while(0) 
+
} while (0)

#define LL_SEARCH(head,out,elt,cmp)                                                            \
    LL_SEARCH2(head,out,elt,cmp,next)
@@ -455,19 +442,19 @@ do {
    LL_FOREACH2(head,out,next) {                                                               \
      if ((cmp(out,elt))==0) break;                                                            \
    }                                                                                          \
-
} while(0) 
+
} while (0)

-
#define LL_REPLACE_ELEM(head, el, add)                                                         \
+
#define LL_REPLACE_ELEM2(head, el, add, next)                                                  \
do {                                                                                           \
 LDECLTYPE(head) _tmp;                                                                         \
-
 assert(head != NULL);                                                                         \
-
 assert(el != NULL);                                                                           \
-
 assert(add != NULL);                                                                          \
+
 assert((head) != NULL);                                                                       \
+
 assert((el) != NULL);                                                                         \
+
 assert((add) != NULL);                                                                        \
 (add)->next = (el)->next;                                                                     \
 if ((head) == (el)) {                                                                         \
  (head) = (add);                                                                              \
 } else {                                                                                      \
-
  _tmp = head;                                                                                 \
+
  _tmp = (head);                                                                               \
  while (_tmp->next && (_tmp->next != (el))) {                                                 \
   _tmp = _tmp->next;                                                                          \
  }                                                                                            \
@@ -477,26 +464,158 @@ do {
 }                                                                                             \
} while (0)

+
#define LL_REPLACE_ELEM(head, el, add)                                                         \
+
    LL_REPLACE_ELEM2(head, el, add, next)
+

+
#define LL_PREPEND_ELEM2(head, el, add, next)                                                  \
+
do {                                                                                           \
+
 if (el) {                                                                                     \
+
  LDECLTYPE(head) _tmp;                                                                        \
+
  assert((head) != NULL);                                                                      \
+
  assert((add) != NULL);                                                                       \
+
  (add)->next = (el);                                                                          \
+
  if ((head) == (el)) {                                                                        \
+
   (head) = (add);                                                                             \
+
  } else {                                                                                     \
+
   _tmp = (head);                                                                              \
+
   while (_tmp->next && (_tmp->next != (el))) {                                                \
+
    _tmp = _tmp->next;                                                                         \
+
   }                                                                                           \
+
   if (_tmp->next) {                                                                           \
+
     _tmp->next = (add);                                                                       \
+
   }                                                                                           \
+
  }                                                                                            \
+
 } else {                                                                                      \
+
  LL_APPEND2(head, add, next);                                                                 \
+
 }                                                                                             \
+
} while (0)                                                                                    \
+

#define LL_PREPEND_ELEM(head, el, add)                                                         \
+
    LL_PREPEND_ELEM2(head, el, add, next)
+

+
#define LL_APPEND_ELEM2(head, el, add, next)                                                   \
do {                                                                                           \
-
 LDECLTYPE(head) _tmp;                                                                         \
-
 assert(head != NULL);                                                                         \
-
 assert(el != NULL);                                                                           \
-
 assert(add != NULL);                                                                          \
-
 (add)->next = (el);                                                                           \
-
 if ((head) == (el)) {                                                                         \
-
  (head) = (add);                                                                              \
+
 if (el) {                                                                                     \
+
  assert((head) != NULL);                                                                      \
+
  assert((add) != NULL);                                                                       \
+
  (add)->next = (el)->next;                                                                    \
+
  (el)->next = (add);                                                                          \
 } else {                                                                                      \
-
  _tmp = head;                                                                                 \
-
  while (_tmp->next && (_tmp->next != (el))) {                                                 \
-
   _tmp = _tmp->next;                                                                          \
+
  LL_PREPEND2(head, add, next);                                                                \
+
 }                                                                                             \
+
} while (0)                                                                                    \
+

+
#define LL_APPEND_ELEM(head, el, add)                                                          \
+
    LL_APPEND_ELEM2(head, el, add, next)
+

+
#ifdef NO_DECLTYPE
+
/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */
+

+
#undef LL_CONCAT2
+
#define LL_CONCAT2(head1,head2,next)                                                           \
+
do {                                                                                           \
+
  char *_tmp;                                                                                  \
+
  if (head1) {                                                                                 \
+
    _tmp = (char*)(head1);                                                                     \
+
    while ((head1)->next) { (head1) = (head1)->next; }                                         \
+
    (head1)->next = (head2);                                                                   \
+
    UTLIST_RS(head1);                                                                          \
+
  } else {                                                                                     \
+
    (head1)=(head2);                                                                           \
  }                                                                                            \
-
  if (_tmp->next) {                                                                            \
-
    _tmp->next = (add);                                                                        \
+
} while (0)
+

+
#undef LL_APPEND2
+
#define LL_APPEND2(head,add,next)                                                              \
+
do {                                                                                           \
+
  if (head) {                                                                                  \
+
    (add)->next = head;     /* use add->next as a temp variable */                             \
+
    while ((add)->next->next) { (add)->next = (add)->next->next; }                             \
+
    (add)->next->next=(add);                                                                   \
+
  } else {                                                                                     \
+
    (head)=(add);                                                                              \
+
  }                                                                                            \
+
  (add)->next=NULL;                                                                            \
+
} while (0)
+

+
#undef LL_INSERT_INORDER2
+
#define LL_INSERT_INORDER2(head,add,cmp,next)                                                  \
+
do {                                                                                           \
+
  if ((head) == NULL || (cmp(head, add)) >= 0) {                                               \
+
    (add)->next = (head);                                                                      \
+
    (head) = (add);                                                                            \
+
  } else {                                                                                     \
+
    char *_tmp = (char*)(head);                                                                \
+
    while ((head)->next != NULL && (cmp((head)->next, add)) < 0) {                             \
+
      (head) = (head)->next;                                                                   \
+
    }                                                                                          \
+
    (add)->next = (head)->next;                                                                \
+
    (head)->next = (add);                                                                      \
+
    UTLIST_RS(head);                                                                           \
+
  }                                                                                            \
+
} while (0)
+

+
#undef LL_DELETE2
+
#define LL_DELETE2(head,del,next)                                                              \
+
do {                                                                                           \
+
  if ((head) == (del)) {                                                                       \
+
    (head)=(head)->next;                                                                       \
+
  } else {                                                                                     \
+
    char *_tmp = (char*)(head);                                                                \
+
    while ((head)->next && ((head)->next != (del))) {                                          \
+
      (head) = (head)->next;                                                                   \
+
    }                                                                                          \
+
    if ((head)->next) {                                                                        \
+
      (head)->next = ((del)->next);                                                            \
+
    }                                                                                          \
+
    UTLIST_RS(head);                                                                           \
+
  }                                                                                            \
+
} while (0)
+

+
#undef LL_REPLACE_ELEM2
+
#define LL_REPLACE_ELEM2(head, el, add, next)                                                  \
+
do {                                                                                           \
+
  assert((head) != NULL);                                                                      \
+
  assert((el) != NULL);                                                                        \
+
  assert((add) != NULL);                                                                       \
+
  if ((head) == (el)) {                                                                        \
+
    (head) = (add);                                                                            \
+
  } else {                                                                                     \
+
    (add)->next = head;                                                                        \
+
    while ((add)->next->next && ((add)->next->next != (el))) {                                 \
+
      (add)->next = (add)->next->next;                                                         \
+
    }                                                                                          \
+
    if ((add)->next->next) {                                                                   \
+
      (add)->next->next = (add);                                                               \
+
    }                                                                                          \
+
  }                                                                                            \
+
  (add)->next = (el)->next;                                                                    \
+
} while (0)
+

+
#undef LL_PREPEND_ELEM2
+
#define LL_PREPEND_ELEM2(head, el, add, next)                                                  \
+
do {                                                                                           \
+
  if (el) {                                                                                    \
+
    assert((head) != NULL);                                                                    \
+
    assert((add) != NULL);                                                                     \
+
    if ((head) == (el)) {                                                                      \
+
      (head) = (add);                                                                          \
+
    } else {                                                                                   \
+
      (add)->next = (head);                                                                    \
+
      while ((add)->next->next && ((add)->next->next != (el))) {                               \
+
        (add)->next = (add)->next->next;                                                       \
+
      }                                                                                        \
+
      if ((add)->next->next) {                                                                 \
+
        (add)->next->next = (add);                                                             \
+
      }                                                                                        \
+
    }                                                                                          \
+
    (add)->next = (el);                                                                        \
+
  } else {                                                                                     \
+
    LL_APPEND2(head, add, next);                                                               \
  }                                                                                            \
-
 }                                                                                             \
} while (0)                                                                                    \

+
#endif /* NO_DECLTYPE */

/******************************************************************************
 * doubly linked list macros (non-circular)                                   *
@@ -506,7 +625,7 @@ do {

#define DL_PREPEND2(head,add,prev,next)                                                        \
do {                                                                                           \
-
 (add)->next = head;                                                                           \
+
 (add)->next = (head);                                                                         \
 if (head) {                                                                                   \
   (add)->prev = (head)->prev;                                                                 \
   (head)->prev = (add);                                                                       \
@@ -531,7 +650,39 @@ do {
      (head)->prev = (head);                                                                   \
      (head)->next = NULL;                                                                     \
  }                                                                                            \
-
} while (0) 
+
} while (0)
+

+
#define DL_INSERT_INORDER(head,add,cmp)                                                        \
+
    DL_INSERT_INORDER2(head,add,cmp,prev,next)
+

+
#define DL_INSERT_INORDER2(head,add,cmp,prev,next)                                             \
+
do {                                                                                           \
+
  LDECLTYPE(head) _tmp;                                                                        \
+
  if (head) {                                                                                  \
+
    DL_LOWER_BOUND2(head, _tmp, add, cmp, next);                                               \
+
    DL_APPEND_ELEM2(head, _tmp, add, prev, next);                                              \
+
  } else {                                                                                     \
+
    (head) = (add);                                                                            \
+
    (head)->prev = (head);                                                                     \
+
    (head)->next = NULL;                                                                       \
+
  }                                                                                            \
+
} while (0)
+

+
#define DL_LOWER_BOUND(head,elt,like,cmp)                                                      \
+
    DL_LOWER_BOUND2(head,elt,like,cmp,next)
+

+
#define DL_LOWER_BOUND2(head,elt,like,cmp,next)                                                \
+
do {                                                                                           \
+
  if ((head) == NULL || (cmp(head, like)) >= 0) {                                              \
+
    (elt) = NULL;                                                                              \
+
  } else {                                                                                     \
+
    for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) {                           \
+
      if ((cmp((elt)->next, like)) >= 0) {                                                     \
+
        break;                                                                                 \
+
      }                                                                                        \
+
    }                                                                                          \
+
  }                                                                                            \
+
} while (0)

#define DL_CONCAT(head1,head2)                                                                 \
    DL_CONCAT2(head1,head2,prev,next)
@@ -541,25 +692,27 @@ do {
  LDECLTYPE(head1) _tmp;                                                                       \
  if (head2) {                                                                                 \
    if (head1) {                                                                               \
-
        _tmp = (head2)->prev;                                                                  \
+
        UTLIST_CASTASGN(_tmp, (head2)->prev);                                                  \
        (head2)->prev = (head1)->prev;                                                         \
        (head1)->prev->next = (head2);                                                         \
-
        (head1)->prev = _tmp;                                                                  \
+
        UTLIST_CASTASGN((head1)->prev, _tmp);                                                  \
    } else {                                                                                   \
        (head1)=(head2);                                                                       \
    }                                                                                          \
  }                                                                                            \
-
} while (0) 
+
} while (0)

#define DL_DELETE(head,del)                                                                    \
    DL_DELETE2(head,del,prev,next)

#define DL_DELETE2(head,del,prev,next)                                                         \
do {                                                                                           \
+
  assert((head) != NULL);                                                                      \
  assert((del)->prev != NULL);                                                                 \
  if ((del)->prev == (del)) {                                                                  \
      (head)=NULL;                                                                             \
-
  } else if ((del)==(head)) {                                                                  \
+
  } else if ((del) == (head)) {                                                                \
+
      assert((del)->next != NULL);                                                             \
      (del)->next->prev = (del)->prev;                                                         \
      (head) = (del)->next;                                                                    \
  } else {                                                                                     \
@@ -570,29 +723,29 @@ do {
          (head)->prev = (del)->prev;                                                          \
      }                                                                                        \
  }                                                                                            \
-
} while (0) 
+
} while (0)

#define DL_COUNT(head,el,counter)                                                              \
    DL_COUNT2(head,el,counter,next)                                                            \

#define DL_COUNT2(head,el,counter,next)                                                        \
-
{                                                                                              \
-
    counter = 0;                                                                               \
-
    DL_FOREACH2(head,el,next){ ++counter; }                                                    \
-
}
+
do {                                                                                           \
+
  (counter) = 0;                                                                               \
+
  DL_FOREACH2(head,el,next) { ++(counter); }                                                   \
+
} while (0)

#define DL_FOREACH(head,el)                                                                    \
    DL_FOREACH2(head,el,next)

#define DL_FOREACH2(head,el,next)                                                              \
-
    for(el=head;el;el=(el)->next)
+
    for ((el) = (head); el; (el) = (el)->next)

/* this version is safe for deleting the elements during iteration */
#define DL_FOREACH_SAFE(head,el,tmp)                                                           \
    DL_FOREACH_SAFE2(head,el,tmp,next)

#define DL_FOREACH_SAFE2(head,el,tmp,next)                                                     \
-
  for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
+
  for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp))

/* these are identical to their singly-linked list counterparts */
#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
@@ -600,11 +753,11 @@ do {
#define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2
#define DL_SEARCH2 LL_SEARCH2

-
#define DL_REPLACE_ELEM(head, el, add)                                                         \
+
#define DL_REPLACE_ELEM2(head, el, add, prev, next)                                            \
do {                                                                                           \
-
 assert(head != NULL);                                                                         \
-
 assert(el != NULL);                                                                           \
-
 assert(add != NULL);                                                                          \
+
 assert((head) != NULL);                                                                       \
+
 assert((el) != NULL);                                                                         \
+
 assert((add) != NULL);                                                                        \
 if ((head) == (el)) {                                                                         \
  (head) = (add);                                                                              \
  (add)->next = (el)->next;                                                                    \
@@ -626,25 +779,104 @@ do {
 }                                                                                             \
} while (0)

+
#define DL_REPLACE_ELEM(head, el, add)                                                         \
+
    DL_REPLACE_ELEM2(head, el, add, prev, next)
+

+
#define DL_PREPEND_ELEM2(head, el, add, prev, next)                                            \
+
do {                                                                                           \
+
 if (el) {                                                                                     \
+
  assert((head) != NULL);                                                                      \
+
  assert((add) != NULL);                                                                       \
+
  (add)->next = (el);                                                                          \
+
  (add)->prev = (el)->prev;                                                                    \
+
  (el)->prev = (add);                                                                          \
+
  if ((head) == (el)) {                                                                        \
+
   (head) = (add);                                                                             \
+
  } else {                                                                                     \
+
   (add)->prev->next = (add);                                                                  \
+
  }                                                                                            \
+
 } else {                                                                                      \
+
  DL_APPEND2(head, add, prev, next);                                                           \
+
 }                                                                                             \
+
} while (0)                                                                                    \
+

#define DL_PREPEND_ELEM(head, el, add)                                                         \
+
    DL_PREPEND_ELEM2(head, el, add, prev, next)
+

+
#define DL_APPEND_ELEM2(head, el, add, prev, next)                                             \
do {                                                                                           \
-
 assert(head != NULL);                                                                         \
-
 assert(el != NULL);                                                                           \
-
 assert(add != NULL);                                                                          \
-
 (add)->next = (el);                                                                           \
-
 (add)->prev = (el)->prev;                                                                     \
-
 (el)->prev = (add);                                                                           \
-
 if ((head) == (el)) {                                                                         \
-
  (head) = (add);                                                                              \
+
 if (el) {                                                                                     \
+
  assert((head) != NULL);                                                                      \
+
  assert((add) != NULL);                                                                       \
+
  (add)->next = (el)->next;                                                                    \
+
  (add)->prev = (el);                                                                          \
+
  (el)->next = (add);                                                                          \
+
  if ((add)->next) {                                                                           \
+
   (add)->next->prev = (add);                                                                  \
+
  } else {                                                                                     \
+
   (head)->prev = (add);                                                                       \
+
  }                                                                                            \
 } else {                                                                                      \
-
  (add)->prev->next = (add);                                                                   \
+
  DL_PREPEND2(head, add, prev, next);                                                          \
 }                                                                                             \
} while (0)                                                                                    \

+
#define DL_APPEND_ELEM(head, el, add)                                                          \
+
   DL_APPEND_ELEM2(head, el, add, prev, next)
+

+
#ifdef NO_DECLTYPE
+
/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */
+

+
#undef DL_INSERT_INORDER2
+
#define DL_INSERT_INORDER2(head,add,cmp,prev,next)                                             \
+
do {                                                                                           \
+
  if ((head) == NULL) {                                                                        \
+
    (add)->prev = (add);                                                                       \
+
    (add)->next = NULL;                                                                        \
+
    (head) = (add);                                                                            \
+
  } else if ((cmp(head, add)) >= 0) {                                                          \
+
    (add)->prev = (head)->prev;                                                                \
+
    (add)->next = (head);                                                                      \
+
    (head)->prev = (add);                                                                      \
+
    (head) = (add);                                                                            \
+
  } else {                                                                                     \
+
    char *_tmp = (char*)(head);                                                                \
+
    while ((head)->next && (cmp((head)->next, add)) < 0) {                                     \
+
      (head) = (head)->next;                                                                   \
+
    }                                                                                          \
+
    (add)->prev = (head);                                                                      \
+
    (add)->next = (head)->next;                                                                \
+
    (head)->next = (add);                                                                      \
+
    UTLIST_RS(head);                                                                           \
+
    if ((add)->next) {                                                                         \
+
      (add)->next->prev = (add);                                                               \
+
    } else {                                                                                   \
+
      (head)->prev = (add);                                                                    \
+
    }                                                                                          \
+
  }                                                                                            \
+
} while (0)
+
#endif /* NO_DECLTYPE */

/******************************************************************************
 * circular doubly linked list macros                                         *
 *****************************************************************************/
+
#define CDL_APPEND(head,add)                                                                   \
+
    CDL_APPEND2(head,add,prev,next)
+

+
#define CDL_APPEND2(head,add,prev,next)                                                        \
+
do {                                                                                           \
+
 if (head) {                                                                                   \
+
   (add)->prev = (head)->prev;                                                                 \
+
   (add)->next = (head);                                                                       \
+
   (head)->prev = (add);                                                                       \
+
   (add)->prev->next = (add);                                                                  \
+
 } else {                                                                                      \
+
   (add)->prev = (add);                                                                        \
+
   (add)->next = (add);                                                                        \
+
   (head) = (add);                                                                             \
+
 }                                                                                             \
+
} while (0)
+

#define CDL_PREPEND(head,add)                                                                  \
    CDL_PREPEND2(head,add,prev,next)

@@ -659,7 +891,39 @@ do {
   (add)->prev = (add);                                                                        \
   (add)->next = (add);                                                                        \
 }                                                                                             \
-
(head)=(add);                                                                                  \
+
 (head) = (add);                                                                               \
+
} while (0)
+

+
#define CDL_INSERT_INORDER(head,add,cmp)                                                       \
+
    CDL_INSERT_INORDER2(head,add,cmp,prev,next)
+

+
#define CDL_INSERT_INORDER2(head,add,cmp,prev,next)                                            \
+
do {                                                                                           \
+
  LDECLTYPE(head) _tmp;                                                                        \
+
  if (head) {                                                                                  \
+
    CDL_LOWER_BOUND2(head, _tmp, add, cmp, next);                                              \
+
    CDL_APPEND_ELEM2(head, _tmp, add, prev, next);                                             \
+
  } else {                                                                                     \
+
    (head) = (add);                                                                            \
+
    (head)->next = (head);                                                                     \
+
    (head)->prev = (head);                                                                     \
+
  }                                                                                            \
+
} while (0)
+

+
#define CDL_LOWER_BOUND(head,elt,like,cmp)                                                     \
+
    CDL_LOWER_BOUND2(head,elt,like,cmp,next)
+

+
#define CDL_LOWER_BOUND2(head,elt,like,cmp,next)                                               \
+
do {                                                                                           \
+
  if ((head) == NULL || (cmp(head, like)) >= 0) {                                              \
+
    (elt) = NULL;                                                                              \
+
  } else {                                                                                     \
+
    for ((elt) = (head); (elt)->next != (head); (elt) = (elt)->next) {                         \
+
      if ((cmp((elt)->next, like)) >= 0) {                                                     \
+
        break;                                                                                 \
+
      }                                                                                        \
+
    }                                                                                          \
+
  }                                                                                            \
} while (0)

#define CDL_DELETE(head,del)                                                                   \
@@ -667,37 +931,37 @@ do {

#define CDL_DELETE2(head,del,prev,next)                                                        \
do {                                                                                           \
-
  if ( ((head)==(del)) && ((head)->next == (head))) {                                          \
-
      (head) = 0L;                                                                             \
+
  if (((head)==(del)) && ((head)->next == (head))) {                                           \
+
      (head) = NULL;                                                                           \
  } else {                                                                                     \
     (del)->next->prev = (del)->prev;                                                          \
     (del)->prev->next = (del)->next;                                                          \
     if ((del) == (head)) (head)=(del)->next;                                                  \
  }                                                                                            \
-
} while (0) 
+
} while (0)

#define CDL_COUNT(head,el,counter)                                                             \
    CDL_COUNT2(head,el,counter,next)                                                           \

#define CDL_COUNT2(head, el, counter,next)                                                     \
-
{                                                                                              \
-
    counter = 0;                                                                               \
-
    CDL_FOREACH2(head,el,next){ ++counter; }                                                   \
-
}
+
do {                                                                                           \
+
  (counter) = 0;                                                                               \
+
  CDL_FOREACH2(head,el,next) { ++(counter); }                                                  \
+
} while (0)

#define CDL_FOREACH(head,el)                                                                   \
    CDL_FOREACH2(head,el,next)

#define CDL_FOREACH2(head,el,next)                                                             \
-
    for(el=head;el;el=((el)->next==head ? 0L : (el)->next)) 
+
    for ((el)=(head);el;(el)=(((el)->next==(head)) ? NULL : (el)->next))

#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2)                                                    \
    CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next)

#define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next)                                         \
-
  for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL);                                        \
-
      (el) && ((tmp2)=(el)->next, 1);                                                          \
-
      ((el) = (((el)==(tmp1)) ? 0L : (tmp2))))
+
  for ((el) = (head), (tmp1) = (head) ? (head)->prev : NULL;                                   \
+
       (el) && ((tmp2) = (el)->next, 1);                                                       \
+
       (el) = ((el) == (tmp1) ? NULL : (tmp2)))

#define CDL_SEARCH_SCALAR(head,out,field,val)                                                  \
    CDL_SEARCH_SCALAR2(head,out,field,val,next)
@@ -707,7 +971,7 @@ do {
    CDL_FOREACH2(head,out,next) {                                                              \
      if ((out)->field == (val)) break;                                                        \
    }                                                                                          \
-
} while(0) 
+
} while (0)

#define CDL_SEARCH(head,out,elt,cmp)                                                           \
    CDL_SEARCH2(head,out,elt,cmp,next)
@@ -717,13 +981,13 @@ do {
    CDL_FOREACH2(head,out,next) {                                                              \
      if ((cmp(out,elt))==0) break;                                                            \
    }                                                                                          \
-
} while(0) 
+
} while (0)

-
#define CDL_REPLACE_ELEM(head, el, add)                                                        \
+
#define CDL_REPLACE_ELEM2(head, el, add, prev, next)                                           \
do {                                                                                           \
-
 assert(head != NULL);                                                                         \
-
 assert(el != NULL);                                                                           \
-
 assert(add != NULL);                                                                          \
+
 assert((head) != NULL);                                                                       \
+
 assert((el) != NULL);                                                                         \
+
 assert((add) != NULL);                                                                        \
 if ((el)->next == (el)) {                                                                     \
  (add)->next = (add);                                                                         \
  (add)->prev = (add);                                                                         \
@@ -739,19 +1003,74 @@ do {
 }                                                                                             \
} while (0)

+
#define CDL_REPLACE_ELEM(head, el, add)                                                        \
+
    CDL_REPLACE_ELEM2(head, el, add, prev, next)
+

+
#define CDL_PREPEND_ELEM2(head, el, add, prev, next)                                           \
+
do {                                                                                           \
+
  if (el) {                                                                                    \
+
    assert((head) != NULL);                                                                    \
+
    assert((add) != NULL);                                                                     \
+
    (add)->next = (el);                                                                        \
+
    (add)->prev = (el)->prev;                                                                  \
+
    (el)->prev = (add);                                                                        \
+
    (add)->prev->next = (add);                                                                 \
+
    if ((head) == (el)) {                                                                      \
+
      (head) = (add);                                                                          \
+
    }                                                                                          \
+
  } else {                                                                                     \
+
    CDL_APPEND2(head, add, prev, next);                                                        \
+
  }                                                                                            \
+
} while (0)
+

#define CDL_PREPEND_ELEM(head, el, add)                                                        \
+
    CDL_PREPEND_ELEM2(head, el, add, prev, next)
+

+
#define CDL_APPEND_ELEM2(head, el, add, prev, next)                                            \
do {                                                                                           \
-
 assert(head != NULL);                                                                         \
-
 assert(el != NULL);                                                                           \
-
 assert(add != NULL);                                                                          \
-
 (add)->next = (el);                                                                           \
-
 (add)->prev = (el)->prev;                                                                     \
-
 (el)->prev = (add);                                                                           \
-
 (add)->prev->next = (add);                                                                    \
-
 if ((head) == (el)) {                                                                         \
-
  (head) = (add);                                                                              \
+
 if (el) {                                                                                     \
+
  assert((head) != NULL);                                                                      \
+
  assert((add) != NULL);                                                                       \
+
  (add)->next = (el)->next;                                                                    \
+
  (add)->prev = (el);                                                                          \
+
  (el)->next = (add);                                                                          \
+
  (add)->next->prev = (add);                                                                   \
+
 } else {                                                                                      \
+
  CDL_PREPEND2(head, add, prev, next);                                                         \
 }                                                                                             \
-
} while (0)                                                                                    \
+
} while (0)

-
#endif /* UTLIST_H */
+
#define CDL_APPEND_ELEM(head, el, add)                                                         \
+
    CDL_APPEND_ELEM2(head, el, add, prev, next)
+

+
#ifdef NO_DECLTYPE
+
/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */

+
#undef CDL_INSERT_INORDER2
+
#define CDL_INSERT_INORDER2(head,add,cmp,prev,next)                                            \
+
do {                                                                                           \
+
  if ((head) == NULL) {                                                                        \
+
    (add)->prev = (add);                                                                       \
+
    (add)->next = (add);                                                                       \
+
    (head) = (add);                                                                            \
+
  } else if ((cmp(head, add)) >= 0) {                                                          \
+
    (add)->prev = (head)->prev;                                                                \
+
    (add)->next = (head);                                                                      \
+
    (add)->prev->next = (add);                                                                 \
+
    (head)->prev = (add);                                                                      \
+
    (head) = (add);                                                                            \
+
  } else {                                                                                     \
+
    char *_tmp = (char*)(head);                                                                \
+
    while ((char*)(head)->next != _tmp && (cmp((head)->next, add)) < 0) {                      \
+
      (head) = (head)->next;                                                                   \
+
    }                                                                                          \
+
    (add)->prev = (head);                                                                      \
+
    (add)->next = (head)->next;                                                                \
+
    (add)->next->prev = (add);                                                                 \
+
    (head)->next = (add);                                                                      \
+
    UTLIST_RS(head);                                                                           \
+
  }                                                                                            \
+
} while (0)
+
#endif /* NO_DECLTYPE */
+

+
#endif /* UTLIST_H */