Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Add siphash and rbtree to the external deps.
Vsevolod Stakhov committed 11 years ago
commit 01cd9421955823583229c8e3b6485c75b3947ec8
parent 8c595b2
4 files changed +544 -0
modified external/Makefile.am
@@ -60,6 +60,8 @@ noinst_HEADERS= expat/amiga/expat_68k.h \
		uthash/utarray.h \
		uthash/uthash.h \
		uthash/utlist.h \
+
		include/tree.h \
+
		include/siphash.h \
		config.h

EXTRA_LTLIBRARIES=	libelf.la
added external/include/siphash.h
@@ -0,0 +1,329 @@
+
/* ==========================================================================
+
 * siphash.h - SipHash-2-4 in a single header file
+
 * --------------------------------------------------------------------------
+
 * Derived by William Ahern from the reference implementation[1] published[2]
+
 * by Jean-Philippe Aumasson and Daniel J. Berstein. Licensed in kind.
+
 *
+
 * 1. https://www.131002.net/siphash/siphash24.c
+
 * 2. https://www.131002.net/siphash/
+
 * --------------------------------------------------------------------------
+
 * HISTORY:
+
 *
+
 * 2012-11-04 - Born.
+
 * --------------------------------------------------------------------------
+
 * USAGE:
+
 *
+
 * SipHash-2-4 takes as input two 64-bit words as the key, some number of
+
 * message bytes, and outputs a 64-bit word as the message digest. This
+
 * implementation employs two data structures: a struct sipkey for
+
 * representing the key, and a struct siphash for representing the hash
+
 * state.
+
 *
+
 * For converting a 16-byte unsigned char array to a key, use either the
+
 * macro sip_keyof or the routine sip_tokey. The former instantiates a
+
 * compound literal key, while the latter requires a key object as a
+
 * parameter.
+
 *
+
 * 	unsigned char secret[16];
+
 * 	arc4random_buf(secret, sizeof secret);
+
 * 	struct sipkey *key = sip_keyof(secret);
+
 *
+
 * For hashing a message, use either the convenience macro siphash24 or the
+
 * routines sip24_init, sip24_update, and sip24_final.
+
 *
+
 * 	struct siphash state;
+
 * 	void *msg;
+
 * 	size_t len;
+
 * 	uint64_t hash;
+
 *
+
 * 	sip24_init(&state, key);
+
 * 	sip24_update(&state, msg, len);
+
 * 	hash = sip24_final(&state);
+
 *
+
 * or
+
 *
+
 * 	hash = siphash24(msg, len, key);
+
 *
+
 * To convert the 64-bit hash value to a canonical 8-byte little-endian
+
 * binary representation, use either the macro sip_binof or the routine
+
 * sip_tobin. The former instantiates and returns a compound literal array,
+
 * while the latter requires an array object as a parameter.
+
 * --------------------------------------------------------------------------
+
 * NOTES:
+
 *
+
 * o Neither sip_keyof, sip_binof, nor siphash24 will work with compilers
+
 *   lacking compound literal support. Instead, you must use the lower-level
+
 *   interfaces which take as parameters the temporary state objects.
+
 *
+
 * o Uppercase macros may evaluate parameters more than once. Lowercase
+
 *   macros should not exhibit any such side effects.
+
 * ==========================================================================
+
 */
+
#ifndef SIPHASH_H
+
#define SIPHASH_H
+

+
#include <stddef.h> /* size_t */
+
#include <stdint.h> /* uint64_t uint32_t uint8_t */
+

+

+
#define SIP_ROTL(x, b) (uint64_t)(((x) << (b)) | ( (x) >> (64 - (b))))
+

+
#define SIP_U32TO8_LE(p, v) \
+
	(p)[0] = (uint8_t)((v) >>  0); (p)[1] = (uint8_t)((v) >>  8); \
+
	(p)[2] = (uint8_t)((v) >> 16); (p)[3] = (uint8_t)((v) >> 24);
+

+
#define SIP_U64TO8_LE(p, v) \
+
	SIP_U32TO8_LE((p) + 0, (uint32_t)((v) >>  0)); \
+
	SIP_U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
+

+
#define SIP_U8TO64_LE(p) \
+
	(((uint64_t)((p)[0]) <<  0) | \
+
	 ((uint64_t)((p)[1]) <<  8) | \
+
	 ((uint64_t)((p)[2]) << 16) | \
+
	 ((uint64_t)((p)[3]) << 24) | \
+
	 ((uint64_t)((p)[4]) << 32) | \
+
	 ((uint64_t)((p)[5]) << 40) | \
+
	 ((uint64_t)((p)[6]) << 48) | \
+
	 ((uint64_t)((p)[7]) << 56))
+

+

+
#define SIPHASH_INITIALIZER { 0, 0, 0, 0, { 0 }, 0, 0 }
+

+
struct siphash {
+
	uint64_t v0, v1, v2, v3;
+

+
	unsigned char buf[8], *p;
+
	uint64_t c;
+
}; /* struct siphash */
+

+

+
#define SIP_KEYLEN 16
+

+
struct sipkey {
+
	uint64_t k[2];
+
}; /* struct sipkey */
+

+
#define sip_keyof(k) sip_tokey(&(struct sipkey){ { 0 } }, (k))
+

+
static inline struct sipkey *sip_tokey(struct sipkey *key, const void *src) {
+
	key->k[0] = SIP_U8TO64_LE((const unsigned char *)src);
+
	key->k[1] = SIP_U8TO64_LE((const unsigned char *)src + 8);
+
	return key;
+
} /* sip_tokey() */
+

+

+
#define sip_binof(v) sip_tobin((unsigned char[8]){ 0 }, (v))
+

+
static inline void *sip_tobin(void *dst, uint64_t u64) {
+
	SIP_U64TO8_LE((unsigned char *)dst, u64);
+
	return dst;
+
} /* sip_tobin() */
+

+

+
static inline void sip_round(struct siphash *H, const int rounds) {
+
	int i;
+

+
	for (i = 0; i < rounds; i++) {
+
		H->v0 += H->v1;
+
		H->v1 = SIP_ROTL(H->v1, 13);
+
		H->v1 ^= H->v0;
+
		H->v0 = SIP_ROTL(H->v0, 32);
+

+
		H->v2 += H->v3;
+
		H->v3 = SIP_ROTL(H->v3, 16);
+
		H->v3 ^= H->v2;
+

+
		H->v0 += H->v3;
+
		H->v3 = SIP_ROTL(H->v3, 21);
+
		H->v3 ^= H->v0;
+

+
		H->v2 += H->v1;
+
		H->v1 = SIP_ROTL(H->v1, 17);
+
		H->v1 ^= H->v2;
+
		H->v2 = SIP_ROTL(H->v2, 32);
+
	}
+
} /* sip_round() */
+

+

+
static inline struct siphash *sip24_init(struct siphash *H, const struct sipkey *key) {
+
	H->v0 = 0x736f6d6570736575ULL ^ key->k[0];
+
	H->v1 = 0x646f72616e646f6dULL ^ key->k[1];
+
	H->v2 = 0x6c7967656e657261ULL ^ key->k[0];
+
	H->v3 = 0x7465646279746573ULL ^ key->k[1];
+

+
	H->p = H->buf;
+
	H->c = 0;
+

+
	return H;
+
} /* sip24_init() */
+

+

+
#define sip_endof(a) (&(a)[sizeof (a) / sizeof *(a)])
+

+
static inline struct siphash *sip24_update(struct siphash *H, const void *src, size_t len) {
+
	const unsigned char *p = src, *pe = p + len;
+
	uint64_t m;
+

+
	do {
+
		while (p < pe && H->p < sip_endof(H->buf))
+
			*H->p++ = *p++;
+

+
		if (H->p < sip_endof(H->buf))
+
			break;
+

+
		m = SIP_U8TO64_LE(H->buf);
+
		H->v3 ^= m;
+
		sip_round(H, 2);
+
		H->v0 ^= m;
+

+
		H->p = H->buf;
+
		H->c += 8;
+
	} while (p < pe);
+

+
	return H;
+
} /* sip24_update() */
+

+

+
static inline uint64_t sip24_final(struct siphash *H) {
+
	char left = H->p - H->buf;
+
	uint64_t b = (H->c + left) << 56;
+

+
	switch (left) {
+
	case 7: b |= (uint64_t)H->buf[6] << 48;
+
	case 6: b |= (uint64_t)H->buf[5] << 40;
+
	case 5: b |= (uint64_t)H->buf[4] << 32;
+
	case 4: b |= (uint64_t)H->buf[3] << 24;
+
	case 3: b |= (uint64_t)H->buf[2] << 16;
+
	case 2: b |= (uint64_t)H->buf[1] << 8;
+
	case 1: b |= (uint64_t)H->buf[0] << 0;
+
	case 0: break;
+
	}
+

+
	H->v3 ^= b;
+
	sip_round(H, 2);
+
	H->v0 ^= b;
+
	H->v2 ^= 0xff;
+
	sip_round(H, 4);
+

+
	return H->v0 ^ H->v1 ^ H->v2  ^ H->v3;
+
} /* sip24_final() */
+

+

+
#define siphash24(src, len, key) \
+
	sip24_final(sip24_update(sip24_init(&(struct siphash)SIPHASH_INITIALIZER, (key)), (src), (len)))
+

+

+
#if SIPHASH_MAIN
+

+
/*
+
 * SipHash-2-4 output with
+
 * k = 00 01 02 ...
+
 * and
+
 * in = (empty string)
+
 * in = 00 (1 byte)
+
 * in = 00 01 (2 bytes)
+
 * in = 00 01 02 (3 bytes)
+
 * ...
+
 * in = 00 01 02 ... 3e (63 bytes)
+
 */
+
static inline _Bool sip24_valid(void) {
+
	static const unsigned char vectors[64][8] = {
+
		{ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, },
+
		{ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, },
+
		{ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, },
+
		{ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, },
+
		{ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, },
+
		{ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, },
+
		{ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, },
+
		{ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, },
+
		{ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, },
+
		{ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, },
+
		{ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, },
+
		{ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, },
+
		{ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, },
+
		{ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, },
+
		{ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, },
+
		{ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, },
+
		{ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, },
+
		{ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, },
+
		{ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, },
+
		{ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, },
+
		{ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, },
+
		{ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, },
+
		{ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, },
+
		{ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, },
+
		{ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, },
+
		{ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, },
+
		{ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, },
+
		{ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, },
+
		{ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, },
+
		{ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, },
+
		{ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, },
+
		{ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, },
+
		{ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, },
+
		{ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, },
+
		{ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, },
+
		{ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, },
+
		{ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, },
+
		{ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, },
+
		{ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, },
+
		{ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, },
+
		{ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, },
+
		{ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, },
+
		{ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, },
+
		{ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, },
+
		{ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, },
+
		{ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, },
+
		{ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, },
+
		{ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, },
+
		{ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, },
+
		{ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, },
+
		{ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, },
+
		{ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, },
+
		{ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, },
+
		{ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, },
+
		{ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, },
+
		{ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, },
+
		{ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, },
+
		{ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, },
+
		{ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, },
+
		{ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, },
+
		{ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, },
+
		{ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, },
+
		{ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, },
+
		{ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, }
+
	};
+
	unsigned char in[64];
+
	struct sipkey k;
+
	size_t i;
+

+
	sip_tokey(&k, "\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017");
+

+
	for (i = 0; i < sizeof in; ++i) {
+
		in[i] = i;
+

+
		if (siphash24(in, i, &k) != SIP_U8TO64_LE(vectors[i]))
+
			return 0;
+
	}
+

+
	return 1;
+
} /* sip24_valid() */
+

+

+
#include <stdio.h>
+

+
int main(void) {
+
	_Bool ok = sip24_valid();
+

+
	if (ok)
+
		puts("OK");
+
	else
+
		puts("FAIL");
+

+
	return !ok;
+
} /* main() */
+

+
#endif /* SIPHASH_MAIN */
+

+

+
#endif /* SIPHASH_H */
added external/include/tree.h
@@ -0,0 +1,212 @@
+
/* tree.h -- AVL trees (in the spirit of BSD's 'queue.h')	-*- C -*-	*/
+

+
/* Copyright (c) 2005 Ian Piumarta
+
 * 
+
 * All rights reserved.
+
 * 
+
 * Permission is hereby granted, free of charge, to any person obtaining a copy
+
 * of this software and associated documentation files (the 'Software'), to deal
+
 * in the Software without restriction, including without limitation the rights
+
 * to use, copy, modify, merge, publish, distribute, and/or sell copies of the
+
 * Software, and to permit persons to whom the Software is furnished to do so,
+
 * provided that the above copyright notice(s) and this permission notice appear
+
 * in all copies of the Software and that both the above copyright notice(s) and
+
 * this permission notice appear in supporting documentation.
+
 *
+
 * THE SOFTWARE IS PROVIDED 'AS IS'.  USE ENTIRELY AT YOUR OWN RISK.
+
 */
+

+
/* This file defines an AVL balanced binary tree [Georgii M. Adelson-Velskii and
+
 * Evgenii M. Landis, 'An algorithm for the organization of information',
+
 * Doklady Akademii Nauk SSSR, 146:263-266, 1962 (Russian).  Also in Myron
+
 * J. Ricci (trans.), Soviet Math, 3:1259-1263, 1962 (English)].
+
 * 
+
 * An AVL tree is headed by pointers to the root node and to a function defining
+
 * the ordering relation between nodes.  Each node contains an arbitrary payload
+
 * plus three fields per tree entry: the depth of the subtree for which it forms
+
 * the root and two pointers to child nodes (singly-linked for minimum space, at
+
 * the expense of direct access to the parent node given a pointer to one of the
+
 * children).  The tree is rebalanced after every insertion or removal.  The
+
 * tree may be traversed in two directions: forward (in-order left-to-right) and
+
 * reverse (in-order, right-to-left).
+
 * 
+
 * Because of the recursive nature of many of the operations on trees it is
+
 * necessary to define a number of helper functions for each type of tree node.
+
 * The macro TREE_DEFINE(node_tag, entry_name) defines these functions with
+
 * unique names according to the node_tag.  This macro should be invoked,
+
 * thereby defining the necessary functions, once per node tag in the program.
+
 * 
+
 * For details on the use of these macros, see the tree(3) manual page.
+
 */
+

+
#ifndef __tree_h
+
#define __tree_h
+

+

+
#define TREE_DELTA_MAX	1
+

+
#define TREE_ENTRY(type)			\
+
  struct {					\
+
    struct type	*avl_left;			\
+
    struct type	*avl_right;			\
+
    int		 avl_height;			\
+
  }
+

+
#define TREE_HEAD(name, type)				\
+
  struct name {						\
+
    struct type *th_root;				\
+
    int  (*th_cmp)(struct type *lhs, struct type *rhs);	\
+
  }
+

+
#define TREE_INITIALIZER(cmp) { 0, cmp }
+

+
#define TREE_DELTA(self, field)								\
+
  (( (((self)->field.avl_left)  ? (self)->field.avl_left->field.avl_height  : 0))	\
+
   - (((self)->field.avl_right) ? (self)->field.avl_right->field.avl_height : 0))
+

+
/* Recursion prevents the following from being defined as macros. */
+

+
#define TREE_DEFINE(node, field)									\
+
													\
+
  struct node *TREE_BALANCE_##node##_##field(struct node *);						\
+
													\
+
  struct node *TREE_ROTL_##node##_##field(struct node *self)						\
+
  {													\
+
    struct node *r= self->field.avl_right;								\
+
    self->field.avl_right= r->field.avl_left;								\
+
    r->field.avl_left= TREE_BALANCE_##node##_##field(self);						\
+
    return TREE_BALANCE_##node##_##field(r);								\
+
  }													\
+
													\
+
  struct node *TREE_ROTR_##node##_##field(struct node *self)						\
+
  {													\
+
    struct node *l= self->field.avl_left;								\
+
    self->field.avl_left= l->field.avl_right;								\
+
    l->field.avl_right= TREE_BALANCE_##node##_##field(self);						\
+
    return TREE_BALANCE_##node##_##field(l);								\
+
  }													\
+
													\
+
  struct node *TREE_BALANCE_##node##_##field(struct node *self)						\
+
  {													\
+
    int delta= TREE_DELTA(self, field);									\
+
													\
+
    if (delta < -TREE_DELTA_MAX)									\
+
      {													\
+
	if (TREE_DELTA(self->field.avl_right, field) > 0)						\
+
	  self->field.avl_right= TREE_ROTR_##node##_##field(self->field.avl_right);			\
+
	return TREE_ROTL_##node##_##field(self);							\
+
      }													\
+
    else if (delta > TREE_DELTA_MAX)									\
+
      {													\
+
	if (TREE_DELTA(self->field.avl_left, field) < 0)						\
+
	  self->field.avl_left= TREE_ROTL_##node##_##field(self->field.avl_left);			\
+
	return TREE_ROTR_##node##_##field(self);							\
+
      }													\
+
    self->field.avl_height= 0;										\
+
    if (self->field.avl_left && (self->field.avl_left->field.avl_height > self->field.avl_height))	\
+
      self->field.avl_height= self->field.avl_left->field.avl_height;					\
+
    if (self->field.avl_right && (self->field.avl_right->field.avl_height > self->field.avl_height))	\
+
      self->field.avl_height= self->field.avl_right->field.avl_height;					\
+
    self->field.avl_height += 1;									\
+
    return self;											\
+
  }													\
+
													\
+
  struct node *TREE_INSERT_##node##_##field								\
+
    (struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs))		\
+
  {													\
+
    if (!self)												\
+
      return elm;											\
+
    if (compare(elm, self) < 0)										\
+
      self->field.avl_left= TREE_INSERT_##node##_##field(self->field.avl_left, elm, compare);		\
+
    else												\
+
      self->field.avl_right= TREE_INSERT_##node##_##field(self->field.avl_right, elm, compare);		\
+
    return TREE_BALANCE_##node##_##field(self);								\
+
  }													\
+
													\
+
  struct node *TREE_FIND_##node##_##field								\
+
    (struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs))		\
+
  {													\
+
    if (!self)												\
+
      return 0;												\
+
    if (compare(elm, self) == 0)									\
+
      return self;											\
+
    if (compare(elm, self) < 0)										\
+
      return TREE_FIND_##node##_##field(self->field.avl_left, elm, compare);				\
+
    else												\
+
      return TREE_FIND_##node##_##field(self->field.avl_right, elm, compare);				\
+
  }													\
+
													\
+
  struct node *TREE_MOVE_RIGHT(struct node *self, struct node *rhs)					\
+
  {													\
+
    if (!self)												\
+
      return rhs;											\
+
    self->field.avl_right= TREE_MOVE_RIGHT(self->field.avl_right, rhs);					\
+
    return TREE_BALANCE_##node##_##field(self);								\
+
  }													\
+
													\
+
  struct node *TREE_REMOVE_##node##_##field								\
+
    (struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs))		\
+
  {													\
+
    if (!self) return 0;										\
+
													\
+
    if (compare(elm, self) == 0)									\
+
      {													\
+
	struct node *tmp= TREE_MOVE_RIGHT(self->field.avl_left, self->field.avl_right);			\
+
	self->field.avl_left= 0;									\
+
	self->field.avl_right= 0;									\
+
	return tmp;											\
+
      }													\
+
    if (compare(elm, self) < 0)										\
+
      self->field.avl_left= TREE_REMOVE_##node##_##field(self->field.avl_left, elm, compare);		\
+
    else												\
+
      self->field.avl_right= TREE_REMOVE_##node##_##field(self->field.avl_right, elm, compare);		\
+
    return TREE_BALANCE_##node##_##field(self);								\
+
  }													\
+
													\
+
  void TREE_FORWARD_APPLY_ALL_##node##_##field								\
+
    (struct node *self, void (*function)(struct node *node, void *data), void *data)			\
+
  {													\
+
    if (self)												\
+
      {													\
+
	TREE_FORWARD_APPLY_ALL_##node##_##field(self->field.avl_left, function, data);			\
+
	function(self, data);										\
+
	TREE_FORWARD_APPLY_ALL_##node##_##field(self->field.avl_right, function, data);			\
+
      }													\
+
  }													\
+
													\
+
  void TREE_REVERSE_APPLY_ALL_##node##_##field								\
+
    (struct node *self, void (*function)(struct node *node, void *data), void *data)			\
+
  {													\
+
    if (self)												\
+
      {													\
+
	TREE_REVERSE_APPLY_ALL_##node##_##field(self->field.avl_right, function, data);			\
+
	function(self, data);										\
+
	TREE_REVERSE_APPLY_ALL_##node##_##field(self->field.avl_left, function, data);			\
+
      }													\
+
  }
+

+
#define TREE_INSERT(head, node, field, elm)						\
+
  ((head)->th_root= TREE_INSERT_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
+

+
#define TREE_FIND(head, node, field, elm)				\
+
  (TREE_FIND_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
+

+
#define TREE_REMOVE(head, node, field, elm)						\
+
  ((head)->th_root= TREE_REMOVE_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
+

+
#define TREE_DEPTH(head, field)			\
+
  ((head)->th_root->field.avl_height)
+

+
#define TREE_FORWARD_APPLY(head, node, field, function, data)	\
+
  TREE_FORWARD_APPLY_ALL_##node##_##field((head)->th_root, function, data)
+

+
#define TREE_REVERSE_APPLY(head, node, field, function, data)	\
+
  TREE_REVERSE_APPLY_ALL_##node##_##field((head)->th_root, function, data)
+

+
#define TREE_INIT(head, cmp) do {		\
+
    (head)->th_root= 0;				\
+
    (head)->th_cmp= (cmp);			\
+
  } while (0)
+

+

+
#endif /* __tree_h */
modified libpkg/Makefile.am
@@ -9,6 +9,7 @@ pkg_common_cflags= -I$(top_srcdir)/libpkg \
			-I$(top_srcdir)/external/picosat \
			-I$(top_srcdir)/external/uthash \
			-I$(top_srcdir)/external/sqlite \
+
			-I$(top_srcdir)/external/include \
			-DPREFIX=\"$(prefix)\" \
			-Wno-pointer-sign
libpkg_la_SOURCES=	pkg.c \